mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[region-isolation] When assigning RValues into memory, use tuple_addr_constructor instead of doing it in pieces.
I also included changes to the rest of the SIL optimizer pipeline to ensure that the part of the optimizer pipeline before we lower tuple_addr_constructor (which is right after we run TransferNonSendable) work as before. The reason why I am doing this is that this ensures that diagnostic passes can tell the difference in between: ``` x = (a, b, c) ``` and ``` x.0 = a x.1 = b x.2 = c ``` This is important for things like TransferNonSendable where assigning over the entire tuple element is treated differently from if one were to initialize it in pieces using projections. rdar://117880194
This commit is contained in:
@@ -2184,11 +2184,29 @@ SILCloner<ImplClass>::visitTupleInst(TupleInst *Inst) {
|
||||
template <typename ImplClass>
|
||||
void SILCloner<ImplClass>::visitTupleAddrConstructorInst(
|
||||
TupleAddrConstructorInst *Inst) {
|
||||
auto Elements = getOpValueArray<8>(Inst->getElements());
|
||||
SmallVector<SILValue, 8> Elements;
|
||||
for (auto e : Inst->getElements()) {
|
||||
SILValue mappedValue = getOpValue(e);
|
||||
|
||||
// Check if mappedValue only consists of empty tuple elements. If it does,
|
||||
// then we do not add it to our result. This is because we know that the
|
||||
// corresponding elements in getOpValue(Inst->getDest()) will also change
|
||||
// into an empty exploded tuple. Since we only have leaf non-empty non-tuple
|
||||
// elements as operands, these are not represented.
|
||||
bool FoundNonTuple = false;
|
||||
mappedValue->getType().getASTType().visit(
|
||||
[&](CanType ty) { FoundNonTuple |= !ty->is<TupleType>(); });
|
||||
if (FoundNonTuple)
|
||||
Elements.push_back(mappedValue);
|
||||
}
|
||||
|
||||
if (Elements.empty())
|
||||
return;
|
||||
|
||||
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
|
||||
recordClonedInstruction(Inst, getBuilder().createTupleAddrConstructor(
|
||||
getOpLocation(Inst->getLoc()),
|
||||
getOpValue(Inst->getDestValue()), Elements,
|
||||
getOpValue(Inst->getDest()), Elements,
|
||||
Inst->isInitializationOfDest()));
|
||||
}
|
||||
|
||||
|
||||
@@ -6372,10 +6372,10 @@ public:
|
||||
Dest = 0,
|
||||
};
|
||||
|
||||
Operand &getDest() { return getAllOperands().front(); }
|
||||
const Operand &getDest() const { return getAllOperands().front(); }
|
||||
Operand &getDestOperand() { return getAllOperands().front(); }
|
||||
const Operand &getDestOperand() const { return getAllOperands().front(); }
|
||||
|
||||
SILValue getDestValue() const { return getDest().get(); }
|
||||
SILValue getDest() const { return getDestOperand().get(); }
|
||||
|
||||
/// The elements referenced by this TupleInst.
|
||||
MutableArrayRef<Operand> getElementOperands() {
|
||||
@@ -6392,14 +6392,16 @@ public:
|
||||
|
||||
unsigned getElementIndex(Operand *operand) {
|
||||
assert(operand->getUser() == this);
|
||||
assert(operand != &getDest() && "Cannot pass in the destination");
|
||||
assert(operand != &getDestOperand() && "Cannot pass in the destination");
|
||||
return operand->getOperandNumber() + 1;
|
||||
}
|
||||
|
||||
unsigned getNumElements() const { return getTupleType()->getNumElements(); }
|
||||
|
||||
TupleType *getTupleType() const {
|
||||
return getDest().get()->getType().getRawASTType()->castTo<TupleType>();
|
||||
// We use getASTType() since we want to look through a wrapped noncopyable
|
||||
// type to get to the underlying tuple type.
|
||||
return getDest()->getType().getASTType()->castTo<TupleType>();
|
||||
}
|
||||
|
||||
IsInitialization_t isInitializationOfDest() const {
|
||||
|
||||
Reference in New Issue
Block a user