Skip to content

Commit 0f3f85a

Browse files
Merge pull request swiftlang#40598 from nate-chandler/lexical_lifetimes/shrink-borrow-scope/hoist-over-copy-users
[CopyPropagation] Hoist end_borrows over users of copies.
2 parents 3ec0413 + 7c1da20 commit 0f3f85a

File tree

10 files changed

+424
-97
lines changed

10 files changed

+424
-97
lines changed

include/swift/SIL/OwnershipUtils.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,9 @@ inline bool isForwardingConsume(SILValue value) {
104104
bool findInnerTransitiveGuaranteedUses(
105105
SILValue guaranteedValue, SmallVectorImpl<Operand *> *usePoints = nullptr);
106106

107-
/// Like findInnerTransitiveGuaranteedUses except that rather than it being a
108-
/// precondition that the provided value not be a BorrowedValue, it is a [type-
109-
/// system-enforced] precondition that the provided value be a BorrowedValue.
110-
///
111-
/// TODO: Merge with findInnerTransitiveGuaranteedUses.
112-
bool findInnerTransitiveGuaranteedUsesOfBorrowedValue(
107+
/// Find all uses in the extended lifetime (i.e. including copies) of a simple
108+
/// (i.e. not reborrowed) borrow scope and its transitive uses.
109+
bool findExtendedUsesOfSimpleBorrowedValue(
113110
BorrowedValue borrowedValue,
114111
SmallVectorImpl<Operand *> *usePoints = nullptr);
115112

include/swift/SIL/SILValue.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ class ValueBase : public SILNode, public SILAllocated<ValueBase> {
438438

439439
template <class T> inline T *getSingleConsumingUserOfType() const;
440440

441-
/// Returns true if this operand has exactly two.
441+
/// Returns true if this operand has exactly two uses.
442442
///
443443
/// This is useful if one has found a predefined set of 2 unique users and
444444
/// wants to check if there are any other users without iterating over the

include/swift/SILOptimizer/Utils/CanonicalizeBorrowScope.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,9 @@ class CanonicalizeBorrowScope {
147147
bool consolidateBorrowScope();
148148
};
149149

150-
bool shrinkBorrowScope(BeginBorrowInst *bbi, InstructionDeleter &deleter);
150+
bool shrinkBorrowScope(
151+
BeginBorrowInst *bbi, InstructionDeleter &deleter,
152+
SmallVectorImpl<CopyValueInst *> &modifiedCopyValueInsts);
151153

152154
} // namespace swift
153155

lib/SIL/Utils/OwnershipUtils.cpp

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -195,14 +195,9 @@ bool swift::findInnerTransitiveGuaranteedUses(
195195
return true;
196196
}
197197

198-
/// Like findInnerTransitiveGuaranteedUses except that rather than it being a
199-
/// precondition that the provided value not be a BorrowedValue, it is a [type-
200-
/// system-enforced] precondition that the provided value be a BorrowedValue.
201-
///
202-
/// TODO: Merge with findInnerTransitiveGuaranteedUses. Note that at the moment
203-
/// the two are _almost_ identical, but not quite because the other has a
204-
/// #if 0 and not just leaf uses but ALL uses are recorded.
205-
bool swift::findInnerTransitiveGuaranteedUsesOfBorrowedValue(
198+
/// Find all uses in the extended lifetime (i.e. including copies) of a simple
199+
/// (i.e. not reborrowed) borrow scope and its transitive uses.
200+
bool swift::findExtendedUsesOfSimpleBorrowedValue(
206201
BorrowedValue borrowedValue, SmallVectorImpl<Operand *> *usePoints) {
207202

208203
auto recordUse = [&](Operand *use) {
@@ -220,21 +215,31 @@ bool swift::findInnerTransitiveGuaranteedUsesOfBorrowedValue(
220215
// membership check locally in this function (within a borrow scope) because
221216
// it isn't needed for the immediate uses, only the transitive uses.
222217
GraphNodeWorklist<Operand *, 8> worklist;
223-
for (Operand *use : borrowedValue.value->getUses()) {
224-
if (use->getOperandOwnership() != OperandOwnership::NonUse)
225-
worklist.insert(use);
226-
}
218+
auto addUsesToWorklist = [&worklist](SILValue value) {
219+
for (Operand *use : value->getUses()) {
220+
if (use->getOperandOwnership() != OperandOwnership::NonUse)
221+
worklist.insert(use);
222+
}
223+
};
224+
225+
addUsesToWorklist(borrowedValue.value);
227226

228227
// --- Transitively follow forwarded uses and look for escapes.
229228

230229
// usePoints grows in this loop.
231230
while (Operand *use = worklist.pop()) {
231+
if (auto *cvi = dyn_cast<CopyValueInst>(use->getUser())) {
232+
addUsesToWorklist(cvi);
233+
}
232234
switch (use->getOperandOwnership()) {
233235
case OperandOwnership::NonUse:
236+
break;
237+
234238
case OperandOwnership::TrivialUse:
235239
case OperandOwnership::ForwardingConsume:
236240
case OperandOwnership::DestroyingConsume:
237-
llvm_unreachable("this operand cannot handle an inner guaranteed use");
241+
recordUse(use);
242+
break;
238243

239244
case OperandOwnership::ForwardingUnowned:
240245
case OperandOwnership::PointerEscape:
@@ -264,6 +269,7 @@ bool swift::findInnerTransitiveGuaranteedUsesOfBorrowedValue(
264269
AddressUseKind::NonEscaping) {
265270
return false;
266271
}
272+
recordUse(use);
267273
break;
268274

269275
case OperandOwnership::ForwardingBorrow: {

lib/SILOptimizer/Transforms/CopyPropagation.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,8 +438,12 @@ void CopyPropagation::run() {
438438
// blocks and pushing begin_borrows as we see them and then popping them
439439
// off the end will result in shrinking inner borrow scopes first.
440440
while (auto *bbi = beginBorrowsToShrink.pop()) {
441-
changed |= shrinkBorrowScope(bbi, deleter);
441+
SmallVector<CopyValueInst *, 4> modifiedCopyValueInsts;
442+
changed |= shrinkBorrowScope(bbi, deleter, modifiedCopyValueInsts);
443+
for (auto *cvi : modifiedCopyValueInsts)
444+
defWorklist.updateForCopy(cvi);
442445
}
446+
deleter.cleanupDeadInstructions();
443447

444448
// canonicalizer performs all modifications through deleter's callbacks, so we
445449
// don't need to explicitly check for changes.

0 commit comments

Comments
 (0)