Skip to content

Commit 421adda

Browse files
committed
[ownership] Change store_borrow to be an interior pointer and update interior pointer formalism to use it.
For those who are unaware, a store_borrow is an instruction that is needed so that we can without adding ARC traffic materialize a guaranteed object value into memory so we can pass it as an in_guaranteed argument. It has not had its model completely implemented due to time. I am going to add some information about it in this commit message for others. From a model semantic perspective, a store_borrow is meant to allow for a guaranteed value to be materialized into memory safely for a scoped region of time and be able to guarantee that: 1. The guaranteed value that was stored is always live. 2. The memory is never written to within that region. The natural way to model this type of guaranteeing behavior from an object to an address is via a safe interior pointer formulation and thus with that in mind I made it so that store_borrow returned an address that was an interior pointer of the guaranteed value. Sadly, we have not changed the compiler yet to use this effectively since we in store_borrow code paths generally just use the input address. That being said, in this PR I begin to move us toward this world by making store_borrow's src operand an InteriorPointerOperand. This means that we will require the borrowed value to be alive at all use points of the store_borrow result. That will not have a large effect today but I am going to loop back around and extend that. There is additional work here that I wish to accomplish in the future is that I would like to define an end_store_borrow instruction to explicitly end the scope in which there is a condition on the borrow. Then we would require that the memory we are using to for sure never be written to in that region and maybe additionally try to give some sort of guarantee around exclusivity (consider if we made it so that we could only store_borrow into an alloc_stack with certain conditions). Not sure about the last one yet. But philosophically since we are using this to just handle reabstraction suggests we can do something more constrained.
1 parent cbbeb91 commit 421adda

File tree

3 files changed

+12
-3
lines changed

3 files changed

+12
-3
lines changed

include/swift/SIL/OwnershipUtils.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -618,10 +618,11 @@ BorrowedValue getSingleBorrowIntroducingValue(SILValue inputValue);
618618
class InteriorPointerOperandKind {
619619
public:
620620
enum Kind : uint8_t {
621-
Invalid=0,
621+
Invalid = 0,
622622
RefElementAddr,
623623
RefTailAddr,
624624
OpenExistentialBox,
625+
StoreBorrow,
625626
};
626627

627628
private:
@@ -648,6 +649,8 @@ class InteriorPointerOperandKind {
648649
return Kind::RefTailAddr;
649650
case SILInstructionKind::OpenExistentialBoxInst:
650651
return Kind::OpenExistentialBox;
652+
case SILInstructionKind::StoreBorrowInst:
653+
return Kind::StoreBorrow;
651654
}
652655
}
653656

@@ -664,6 +667,8 @@ class InteriorPointerOperandKind {
664667
return Kind::RefTailAddr;
665668
case ValueKind::OpenExistentialBoxInst:
666669
return Kind::OpenExistentialBox;
670+
case ValueKind::StoreBorrowInst:
671+
return Kind::StoreBorrow;
667672
}
668673
}
669674

@@ -714,7 +719,8 @@ struct InteriorPointerOperand {
714719
return {};
715720
case InteriorPointerOperandKind::RefElementAddr:
716721
case InteriorPointerOperandKind::RefTailAddr:
717-
case InteriorPointerOperandKind::OpenExistentialBox: {
722+
case InteriorPointerOperandKind::OpenExistentialBox:
723+
case InteriorPointerOperandKind::StoreBorrow: {
718724
// Ok, we have a valid instruction. Return the relevant operand.
719725
auto *op =
720726
&cast<SingleValueInstruction>(resultValue)->getAllOperands()[0];
@@ -754,6 +760,8 @@ struct InteriorPointerOperand {
754760
return cast<RefTailAddrInst>(operand->getUser());
755761
case InteriorPointerOperandKind::OpenExistentialBox:
756762
return cast<OpenExistentialBoxInst>(operand->getUser());
763+
case InteriorPointerOperandKind::StoreBorrow:
764+
return cast<StoreBorrowInst>(operand->getUser());
757765
}
758766
llvm_unreachable("Covered switch isn't covered?!");
759767
}

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ OperandOwnership OperandOwnershipClassifier::visitBranchInst(BranchInst *bi) {
391391
OperandOwnership
392392
OperandOwnershipClassifier::visitStoreBorrowInst(StoreBorrowInst *i) {
393393
if (getValue() == i->getSrc()) {
394-
return OperandOwnership::ForwardingBorrow;
394+
return OperandOwnership::InteriorPointer;
395395
}
396396
return OperandOwnership::TrivialUse;
397397
}

lib/SILOptimizer/SILCombiner/SILCombinerBuiltinVisitors.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ SILCombiner::optimizeBuiltinCOWBufferForReadingOSSA(BuiltinInst *bi) {
185185
cast<RefTailAddrInst>(intPtrOperand->getUser())->setImmutable();
186186
return;
187187
case InteriorPointerOperandKind::OpenExistentialBox:
188+
case InteriorPointerOperandKind::StoreBorrow:
188189
// Can not mark this immutable.
189190
return;
190191
}

0 commit comments

Comments
 (0)