Skip to content

Commit dcf90ba

Browse files
authored
Merge pull request #63512 from rjmccall/tuple_pack_element_addr
Add the tuple_pack_element_addr SIL instruction
2 parents d2e022d + 159c653 commit dcf90ba

20 files changed

+231
-3
lines changed

include/swift/SIL/SILBuilder.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,6 +1991,14 @@ class SILBuilder {
19911991
elementValue, packIndex, pack));
19921992
}
19931993

1994+
TuplePackElementAddrInst *
1995+
createTuplePackElementAddr(SILLocation loc, SILValue packIndex,
1996+
SILValue tupleAddr, SILType elementType) {
1997+
return insert(TuplePackElementAddrInst::create(getFunction(),
1998+
getSILDebugLocation(loc),
1999+
packIndex, tupleAddr, elementType));
2000+
}
2001+
19942002
ProjectBlockStorageInst *createProjectBlockStorage(SILLocation Loc,
19952003
SILValue Storage) {
19962004
auto CaptureTy = Storage->getType()

include/swift/SIL/SILCloner.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2539,6 +2539,21 @@ void SILCloner<ImplClass>::visitPackElementSetInst(PackElementSetInst *Inst) {
25392539
newIndex, newPack));
25402540
}
25412541

2542+
template <typename ImplClass>
2543+
void SILCloner<ImplClass>::visitTuplePackElementAddrInst(
2544+
TuplePackElementAddrInst *Inst) {
2545+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
2546+
auto loc = getOpLocation(Inst->getLoc());
2547+
auto newIndex = getOpValue(Inst->getIndex());
2548+
auto newTuple = getOpValue(Inst->getTuple());
2549+
auto newElementType = getOpType(Inst->getElementType());
2550+
// FIXME: do we need to rewrite when substitution removes the
2551+
// tuple-ness of the type? If so, what do we rewrite to?
2552+
recordClonedInstruction(
2553+
Inst, getBuilder().createTuplePackElementAddr(loc, newIndex, newTuple,
2554+
newElementType));
2555+
}
2556+
25422557
template<typename ImplClass>
25432558
void
25442559
SILCloner<ImplClass>::visitCopyBlockInst(CopyBlockInst *Inst) {

include/swift/SIL/SILInstruction.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7747,6 +7747,53 @@ class PackElementSetInst
77477747
}
77487748
};
77497749

7750+
/// Projects a tuple element as appropriate for the given
7751+
/// pack element index. The pack index must index into a pack with
7752+
/// the same shape as the tuple element type list.
7753+
class TuplePackElementAddrInst final
7754+
: public InstructionBaseWithTrailingOperands<
7755+
SILInstructionKind::TuplePackElementAddrInst,
7756+
TuplePackElementAddrInst,
7757+
SingleValueInstruction> {
7758+
public:
7759+
enum {
7760+
IndexOperand = 0,
7761+
TupleOperand = 1
7762+
};
7763+
7764+
private:
7765+
friend SILBuilder;
7766+
7767+
TuplePackElementAddrInst(SILDebugLocation debugLoc,
7768+
ArrayRef<SILValue> allOperands,
7769+
SILType elementType)
7770+
: InstructionBaseWithTrailingOperands(allOperands, debugLoc,
7771+
elementType) {}
7772+
7773+
static TuplePackElementAddrInst *create(SILFunction &F,
7774+
SILDebugLocation debugLoc,
7775+
SILValue indexOperand,
7776+
SILValue tupleOperand,
7777+
SILType elementType);
7778+
7779+
public:
7780+
SILValue getIndex() const {
7781+
return getAllOperands()[IndexOperand].get();
7782+
}
7783+
7784+
SILValue getTuple() const {
7785+
return getAllOperands()[TupleOperand].get();
7786+
}
7787+
7788+
CanTupleType getTupleType() const {
7789+
return getTuple()->getType().castTo<TupleType>();
7790+
}
7791+
7792+
SILType getElementType() const {
7793+
return getType();
7794+
}
7795+
};
7796+
77507797
/// Projects the capture storage address from a @block_storage address.
77517798
class ProjectBlockStorageInst
77527799
: public UnaryInstructionBase<SILInstructionKind::ProjectBlockStorageInst,

include/swift/SIL/SILNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,8 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
550550
SingleValueInstruction, None, DoesNotRelease)
551551
SINGLE_VALUE_INST(TupleElementAddrInst, tuple_element_addr,
552552
SingleValueInstruction, None, DoesNotRelease)
553+
SINGLE_VALUE_INST(TuplePackElementAddrInst, tuple_pack_element_addr,
554+
SingleValueInstruction, None, DoesNotRelease)
553555
SINGLE_VALUE_INST(PackElementGetInst, pack_element_get,
554556
SingleValueInstruction, None, DoesNotRelease)
555557
SINGLE_VALUE_INST(StructInst, struct,

lib/IRGen/GenTuple.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,21 @@ Address irgen::projectTupleElementAddress(IRGenFunction &IGF,
489489
tupleType, fieldNo);
490490
}
491491

492+
Address irgen::projectTupleElementAddressByDynamicIndex(IRGenFunction &IGF,
493+
Address tuple,
494+
SILType tupleType,
495+
llvm::Value *index,
496+
SILType elementType) {
497+
// TODO: retrieve type metadata (ForLayout) for the tuple type
498+
// and retrieve the field offset for the given index. Consider
499+
// special-casing constant indices if we can reason statically
500+
// about the prior elements. It's probably not necessary to try
501+
// to handle fixed-size tuples specially, because the optimizer
502+
// should ideally be lowering this operation to something static
503+
// in that case.
504+
llvm_unreachable("unimplemented");
505+
}
506+
492507
Optional<Size> irgen::getFixedTupleElementOffset(IRGenModule &IGM,
493508
SILType tupleType,
494509
unsigned fieldNo) {

lib/IRGen/GenTuple.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919

2020
#include "swift/Basic/LLVM.h"
2121

22+
namespace llvm {
23+
class Value;
24+
}
25+
2226
namespace swift {
2327
class CanType;
2428

@@ -34,6 +38,13 @@ namespace irgen {
3438
SILType tupleType,
3539
unsigned fieldNo);
3640

41+
/// Project the address of a tuple element, given a dynamic index.
42+
Address projectTupleElementAddressByDynamicIndex(IRGenFunction &IGF,
43+
Address base,
44+
SILType tupleType,
45+
llvm::Value *index,
46+
SILType elementType);
47+
3748
/// Project a tuple element rvalue from an already-exploded tuple rvalue.
3849
void projectTupleElementFromExplosion(IRGenFunction &IGF,
3950
SILType tupleType,

lib/IRGen/IRGenSIL.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,6 +1281,7 @@ class IRGenSILFunction :
12811281
void visitScalarPackIndexInst(ScalarPackIndexInst *i);
12821282
void visitPackElementGetInst(PackElementGetInst *i);
12831283
void visitPackElementSetInst(PackElementSetInst *i);
1284+
void visitTuplePackElementAddrInst(TuplePackElementAddrInst *i);
12841285

12851286
void visitProjectBlockStorageInst(ProjectBlockStorageInst *i);
12861287
void visitInitBlockStorageHeaderInst(InitBlockStorageHeaderInst *i);
@@ -6925,6 +6926,19 @@ void IRGenSILFunction::visitPackElementSetInst(PackElementSetInst *i) {
69256926
Builder.CreateStore(elementValue.getAddress(), elementStorageAddress);
69266927
}
69276928

6929+
void IRGenSILFunction::visitTuplePackElementAddrInst(
6930+
TuplePackElementAddrInst *i) {
6931+
Address tuple = getLoweredAddress(i->getTuple());
6932+
llvm::Value *index = getLoweredSingletonExplosion(i->getIndex());
6933+
6934+
auto elementType = i->getElementType();
6935+
auto elementAddr =
6936+
projectTupleElementAddressByDynamicIndex(*this, tuple,
6937+
i->getTuple()->getType(),
6938+
index, elementType);
6939+
setLoweredAddress(i, elementAddr);
6940+
}
6941+
69286942
void IRGenSILFunction::visitProjectBlockStorageInst(ProjectBlockStorageInst *i){
69296943
// TODO
69306944
Address block = getLoweredAddress(i->getOperand());

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ OPERAND_OWNERSHIP(TrivialUse, DynamicPackIndex)
199199
OPERAND_OWNERSHIP(TrivialUse, PackPackIndex)
200200
OPERAND_OWNERSHIP(TrivialUse, PackElementGet)
201201
OPERAND_OWNERSHIP(TrivialUse, PackElementSet)
202+
OPERAND_OWNERSHIP(TrivialUse, TuplePackElementAddr)
202203

203204
// The dealloc_stack_ref operand needs to have NonUse ownership because
204205
// this use comes after the last consuming use (which is usually a dealloc_ref).

lib/SIL/IR/SILInstructions.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2400,6 +2400,28 @@ PackElementGetInst *PackElementGetInst::create(SILFunction &F,
24002400
return ::new (buffer) PackElementGetInst(debugLoc, allOperands, elementType);
24012401
}
24022402

2403+
TuplePackElementAddrInst *
2404+
TuplePackElementAddrInst::create(SILFunction &F,
2405+
SILDebugLocation debugLoc,
2406+
SILValue indexOperand,
2407+
SILValue tupleOperand,
2408+
SILType elementType) {
2409+
assert(indexOperand->getType().is<BuiltinPackIndexType>());
2410+
assert(tupleOperand->getType().isAddress() &&
2411+
tupleOperand->getType().is<TupleType>());
2412+
2413+
SmallVector<SILValue, 8> allOperands;
2414+
allOperands.push_back(indexOperand);
2415+
allOperands.push_back(tupleOperand);
2416+
collectTypeDependentOperands(allOperands, F, elementType);
2417+
2418+
auto size = totalSizeToAlloc<swift::Operand>(allOperands.size());
2419+
auto buffer =
2420+
F.getModule().allocateInst(size, alignof(TuplePackElementAddrInst));
2421+
return ::new (buffer) TuplePackElementAddrInst(debugLoc, allOperands,
2422+
elementType);
2423+
}
2424+
24032425
BeginCOWMutationInst::BeginCOWMutationInst(SILDebugLocation loc,
24042426
SILValue operand,
24052427
ArrayRef<SILType> resultTypes,

lib/SIL/IR/SILPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2318,6 +2318,11 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
23182318
<< Ctx.getID(I->getIndex()) << " of "
23192319
<< getIDAndType(I->getPack());
23202320
}
2321+
void visitTuplePackElementAddrInst(TuplePackElementAddrInst *I) {
2322+
*this << Ctx.getID(I->getIndex()) << " of "
2323+
<< getIDAndType(I->getTuple()) << " as "
2324+
<< I->getElementType();
2325+
}
23212326
void visitProjectBlockStorageInst(ProjectBlockStorageInst *PBSI) {
23222327
*this << getIDAndType(PBSI->getOperand());
23232328
}

lib/SIL/IR/ValueOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ CONSTANT_OWNERSHIP_INST(None, DynamicPackIndex)
160160
CONSTANT_OWNERSHIP_INST(None, PackPackIndex)
161161
CONSTANT_OWNERSHIP_INST(None, ScalarPackIndex)
162162
CONSTANT_OWNERSHIP_INST(None, PackElementGet)
163+
CONSTANT_OWNERSHIP_INST(None, TuplePackElementAddr)
163164

164165
#undef CONSTANT_OWNERSHIP_INST
165166

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3455,6 +3455,18 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
34553455
ResultVal = B.createPackElementSet(InstLoc, value, index, pack);
34563456
break;
34573457
}
3458+
case SILInstructionKind::TuplePackElementAddrInst: {
3459+
SILValue index, tuple;
3460+
SILType elementType;
3461+
if (parseValueRef(index, SILType::getPackIndexType(P.Context), InstLoc, B) ||
3462+
parseVerbatim("of") ||
3463+
parseTypedValueRef(tuple, B) ||
3464+
parseVerbatim("as") ||
3465+
parseSILType(elementType))
3466+
return true;
3467+
ResultVal = B.createTuplePackElementAddr(InstLoc, index, tuple, elementType);
3468+
break;
3469+
}
34583470

34593471
#define UNARY_INSTRUCTION(ID) \
34603472
case SILInstructionKind::ID##Inst: \

lib/SIL/Utils/InstructionUtils.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,9 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType)
512512
return RuntimeEffect::Allocating | RuntimeEffect::Releasing |
513513
RuntimeEffect::MetaData;
514514

515+
case SILInstructionKind::TuplePackElementAddrInst:
516+
return RuntimeEffect::MetaData;
517+
515518
case SILInstructionKind::SwitchEnumAddrInst:
516519
case SILInstructionKind::InjectEnumAddrInst:
517520
case SILInstructionKind::TupleElementAddrInst:

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5728,6 +5728,27 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
57285728
verifyPackElementType(i->getPackType(), index, i->getElementType());
57295729
}
57305730

5731+
void checkTuplePackElementAddrInst(TuplePackElementAddrInst *i) {
5732+
auto index = requireValueKind<AnyPackIndexInst>(i->getIndex(),
5733+
"pack index operand must be one of the pack_index instructions");
5734+
if (!index) return;
5735+
5736+
// Remove the extra tuple element type structure.
5737+
SmallVector<CanType, 8> tupleElements; {
5738+
auto tupleType = requireAddressType(TupleType, i->getTuple()->getType(),
5739+
"tuple operand of tuple_pack_element_addr");
5740+
auto eltTypes = tupleType.getElementTypes();
5741+
tupleElements.append(eltTypes.begin(), eltTypes.end());
5742+
}
5743+
5744+
require(i->getElementType().isAddress(),
5745+
"result of tuple_pack_element_addr must be an address");
5746+
5747+
verifyPackElementType(tupleElements, index,
5748+
i->getElementType().getASTType(),
5749+
/*types are SIL types*/ true);
5750+
}
5751+
57315752
// This verifies that the entry block of a SIL function doesn't have
57325753
// any predecessors and also verifies the entry point arguments.
57335754
void verifyEntryBlock(SILBasicBlock *entry) {

lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ static bool hasOpaqueArchetype(TypeExpansionContext context,
349349
case SILInstructionKind::HasSymbolInst:
350350
case SILInstructionKind::PackElementGetInst:
351351
case SILInstructionKind::PackElementSetInst:
352+
case SILInstructionKind::TuplePackElementAddrInst:
352353
// Handle by operand and result check.
353354
break;
354355

lib/SILOptimizer/Utils/SILInliner.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,12 @@ InlineCost swift::instructionInlineCost(SILInstruction &I) {
879879
case SILInstructionKind::ProjectBlockStorageInst:
880880
return InlineCost::Free;
881881

882+
// tuple_pack_element_addr is just a GEP, but getting the offset
883+
// can require accessing metadata, so conservatively treat it as
884+
// expensive.
885+
case SILInstructionKind::TuplePackElementAddrInst:
886+
return InlineCost::Expensive;
887+
882888
// dynamic_pack_index is free. The other pack-indexing instructions
883889
// are just adds of values that should be trivially dynamically
884890
// available; that's cheap enough to still consider free under the

lib/Serialization/DeserializeSIL.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,6 +1444,19 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn,
14441444
ResultInst = Builder.createPackElementSet(Loc, value, index, pack);
14451445
break;
14461446
}
1447+
case SILInstructionKind::TuplePackElementAddrInst: {
1448+
assert(RecordKind == SIL_PACK_ELEMENT_GET);
1449+
auto elementType = getSILType(MF->getType(TyID),
1450+
(SILValueCategory) TyCategory, Fn);
1451+
auto tupleType = getSILType(MF->getType(TyID2),
1452+
(SILValueCategory) TyCategory2, Fn);
1453+
auto tuple = getLocalValue(ValID2, tupleType);
1454+
auto indexType = SILType::getPackIndexType(MF->getContext());
1455+
auto index = getLocalValue(ValID3, indexType);
1456+
ResultInst = Builder.createTuplePackElementAddr(Loc, index, tuple,
1457+
elementType);
1458+
break;
1459+
}
14471460

14481461
#define ONEOPERAND_ONETYPE_INST(ID) \
14491462
case SILInstructionKind::ID##Inst: \

lib/Serialization/SILFormat.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ namespace sil_block {
160160
SIL_MOVEONLY_DEINIT,
161161
SIL_INST_HAS_SYMBOL,
162162
SIL_PACK_ELEMENT_GET,
163-
SIL_PACK_ELEMENT_SET,
163+
SIL_PACK_ELEMENT_SET,
164164
};
165165

166166
using SILInstNoOperandLayout = BCRecordLayout<
@@ -474,7 +474,7 @@ namespace sil_block {
474474
SILTypeCategoryField, // element type category
475475
TypeIDField, // pack type
476476
SILTypeCategoryField, // pack type category
477-
ValueIDField, // pack value
477+
ValueIDField, // pack value
478478
ValueIDField // index value
479479
>;
480480

@@ -486,7 +486,7 @@ namespace sil_block {
486486
ValueIDField, // element value
487487
TypeIDField, // pack type
488488
SILTypeCategoryField, // pack type category
489-
ValueIDField, // pack value
489+
ValueIDField, // pack value
490490
ValueIDField // index value
491491
>;
492492

lib/Serialization/SerializeSIL.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,6 +1695,25 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
16951695
indexRef);
16961696
break;
16971697
}
1698+
case SILInstructionKind::TuplePackElementAddrInst: {
1699+
auto TPEAI = cast<TuplePackElementAddrInst>(&SI);
1700+
auto elementType = TPEAI->getElementType();
1701+
auto elementTypeRef = S.addTypeRef(elementType.getASTType());
1702+
auto tuple = TPEAI->getTuple();
1703+
auto tupleType = tuple->getType();
1704+
auto tupleTypeRef = S.addTypeRef(tupleType.getASTType());
1705+
auto tupleRef = addValueRef(tuple);
1706+
auto indexRef = addValueRef(TPEAI->getIndex());
1707+
SILPackElementGetLayout::emitRecord(Out, ScratchRecord,
1708+
SILAbbrCodes[SILPackElementGetLayout::Code],
1709+
elementTypeRef,
1710+
(unsigned) elementType.getCategory(),
1711+
tupleTypeRef,
1712+
(unsigned) tupleType.getCategory(),
1713+
tupleRef,
1714+
indexRef);
1715+
break;
1716+
}
16981717
case SILInstructionKind::TailAddrInst: {
16991718
const TailAddrInst *TAI = cast<TailAddrInst>(&SI);
17001719
SILTailAddrLayout::emitRecord(Out, ScratchRecord,

test/SIL/Parser/variadic_generics.sil

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,15 @@ bb0(%i : $Builtin.Word):
7676
%ret = tuple ()
7777
return %ret : $()
7878
}
79+
80+
// CHECK-LABEL: sil @test6
81+
// CHECK: [[INDEX:%.*]] = dynamic_pack_index
82+
// CHECK: tuple_pack_element_addr [[INDEX]] of %0 : $*(String, repeat each T, Int) as $*@pack_element("01234567-89AB-CDEF-0123-000000000004") U
83+
sil @test6 : $<T...> (@inout (String, repeat each T, Int), Builtin.Word) -> () {
84+
bb0(%tuple : $*(String, repeat each T, Int), %i : $Builtin.Word):
85+
%index = dynamic_pack_index %i of $Pack{Float, repeat each T, Float}
86+
%0 = open_pack_element %index of <U...> at <Pack{String, repeat each T, Int}>, shape $U, uuid "01234567-89AB-CDEF-0123-000000000004"
87+
%elt = tuple_pack_element_addr %index of %tuple : $*(String, repeat each T, Int) as $*@pack_element("01234567-89AB-CDEF-0123-000000000004") U
88+
%ret = tuple ()
89+
return %ret : $()
90+
}

0 commit comments

Comments
 (0)