Skip to content

Commit 4e048a8

Browse files
committed
Expose findInnerTransitiveGuaranteedUses
1 parent 2f34014 commit 4e048a8

File tree

2 files changed

+37
-11
lines changed

2 files changed

+37
-11
lines changed

include/swift/SIL/OwnershipUtils.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,31 @@ inline bool isForwardingConsume(SILValue value) {
7575
return canOpcodeForwardOwnedValues(value);
7676
}
7777

78+
/// Find all "use points" of \p guaranteedValue that determine its lifetime
79+
/// requirement.
80+
///
81+
/// Precondition: \p guaranteedValue is not a BorrowedValue.
82+
///
83+
/// In general, if the client does not know whether \p guaranteed value
84+
/// introduces a borrow scope or not, it should instead call
85+
/// findTransitiveGuaranteedUses() which efficiently gathers use
86+
/// points for arbitrary guaranteed values, including those that introduce a
87+
/// borrow scope and may be reborrowed.
88+
///
89+
/// In valid OSSA, this should never be called on values that introduce a new
90+
/// scope (doing so would be extremely innefficient). The lifetime of a borrow
91+
/// introducing instruction is always determined by its direct EndBorrow uses
92+
/// (see BorrowedValue::visitLocalScopeEndingUses). None of the non-scope-ending
93+
/// uses are relevant, and there's no need to transively follow forwarding
94+
/// uses. However, this utility may be used on borrow-introducing values when
95+
/// updating OSSA form to place EndBorrow uses after introducing new phis.
96+
///
97+
/// When this is called on a value that does not introduce a new scope, none of
98+
/// the use points can be EndBorrows or Reborrows. Those uses are only allowed
99+
/// on borrow-introducing values.
100+
bool findInnerTransitiveGuaranteedUses(SILValue guaranteedValue,
101+
SmallVectorImpl<Operand *> &usePoints);
102+
78103
/// Find all "use points" of a guaranteed value within its enclosing borrow
79104
/// scope (without looking through reborrows). To find the use points of the
80105
/// extended borrow scope, after looking through reborrows, use
@@ -101,7 +126,7 @@ inline bool isForwardingConsume(SILValue value) {
101126
/// 2. If \p guaranteedValue does not introduce a borrow scope (it is not a
102127
/// valid BorrowedValue), then its uses are discovered transitively by looking
103128
/// through forwarding operations. If any use is a PointerEscape, then this
104-
/// returns false without adding more uses--the guaranteed values lifetime is
129+
/// returns false without adding more uses--the guaranteed value's lifetime is
105130
/// indeterminite. If a use introduces a nested borrow scope, it creates use
106131
/// points where the "extended" borrow scope ends. An extended borrow
107132
/// scope is found by looking through any reborrows that end the nested

lib/SIL/Utils/OwnershipUtils.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -147,21 +147,18 @@ bool swift::canOpcodeForwardOwnedValues(Operand *use) {
147147
// Guaranteed Use-Point (Lifetime) Discovery
148148
//===----------------------------------------------------------------------===//
149149

150-
// Find all use points of \p guaranteedValue within its borrow scope where \p
151-
// guaranteedValue is not itself a BorrowedValue (it does not introduce a borrow
152-
// scope). This means there is no need to consider reborrows, and all uses are
153-
// naturally dominated by \p guaranteedValue. On the other hand, if a
154-
// PointerEscape is found, then no assumption can be made about \p
155-
// guaranteedValue's lifetime. Therefore the use points are incomplete and this
156-
// returns false.
150+
// Find all use points of \p guaranteedValue within its borrow scope. All uses
151+
// are naturally dominated by \p guaranteedValue. If a PointerEscape is found,
152+
// then no assumption can be made about \p guaranteedValue's lifetime. Therefore
153+
// the use points are incomplete and this returns false.
157154
//
158155
// Accumulate results in \p usePoints, ignoring existing elements.
159156
//
160157
// Skip over nested borrow scopes. Their scope-ending instructions are their use
161158
// points. Transitively find all nested scope-ending instructions by looking
162159
// through nested reborrows. Nested reborrows are not use points and \p
163160
// visitReborrow is not called for them.
164-
static bool
161+
bool swift::
165162
findInnerTransitiveGuaranteedUses(SILValue guaranteedValue,
166163
SmallVectorImpl<Operand *> &usePoints) {
167164
// Push the value's immediate uses.
@@ -195,7 +192,6 @@ findInnerTransitiveGuaranteedUses(SILValue guaranteedValue,
195192
case OperandOwnership::TrivialUse:
196193
case OperandOwnership::ForwardingConsume:
197194
case OperandOwnership::DestroyingConsume:
198-
case OperandOwnership::Reborrow:
199195
llvm_unreachable("this operand cannot handle an inner guaranteed use");
200196

201197
case OperandOwnership::ForwardingUnowned:
@@ -205,7 +201,12 @@ findInnerTransitiveGuaranteedUses(SILValue guaranteedValue,
205201
case OperandOwnership::InstantaneousUse:
206202
case OperandOwnership::UnownedInstantaneousUse:
207203
case OperandOwnership::BitwiseEscape:
208-
// An end_borrow may be pushed as a use when processing a nested borrow.
204+
// Reborrow only happens when this is called on a value that creates a
205+
// borrow scope.
206+
case OperandOwnership::Reborrow:
207+
// EndBorrow either happens when this is called on a value that creates a
208+
// borrow scope, or when it is pushed as a use when processing a nested
209+
// borrow.
209210
case OperandOwnership::EndBorrow:
210211
break;
211212

0 commit comments

Comments
 (0)