Skip to content

Commit 52e1fc2

Browse files
committed
Fix findTransitiveGuaranteedUses to only record leaf uses.
Recording uses is now optional. This utility is also used simply to check for PointerEscape. When uses are recorded, they are used to extend a live range. There could be a large number of transitive uses that we don't want to pass back to the caller.
1 parent ca0ad84 commit 52e1fc2

File tree

1 file changed

+33
-23
lines changed

1 file changed

+33
-23
lines changed

lib/SIL/Utils/OwnershipUtils.cpp

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,14 @@ bool swift::canOpcodeForwardOwnedValues(Operand *use) {
163163
// visitReborrow is not called for them.
164164
bool swift::findInnerTransitiveGuaranteedUses(
165165
SILValue guaranteedValue, SmallVectorImpl<Operand *> *usePoints) {
166+
167+
auto leafUse = [&](Operand *use) {
168+
if (usePoints && use->getOperandOwnership() != OperandOwnership::NonUse) {
169+
usePoints->push_back(use);
170+
}
171+
return true;
172+
};
173+
166174
// Push the value's immediate uses.
167175
//
168176
// TODO: The worklist can be a simple vector without any a membership check if
@@ -179,13 +187,6 @@ bool swift::findInnerTransitiveGuaranteedUses(
179187

180188
// --- Transitively follow forwarded uses and look for escapes.
181189

182-
auto recordLeafUse = [&](Operand *use) {
183-
if (usePoints && use->getOperandOwnership() != OperandOwnership::NonUse) {
184-
usePoints->push_back(use);
185-
}
186-
return true;
187-
};
188-
189190
// usePoints grows in this loop.
190191
while (Operand *use = worklist.pop()) {
191192
switch (use->getOperandOwnership()) {
@@ -209,6 +210,7 @@ bool swift::findInnerTransitiveGuaranteedUses(
209210
// borrow scope, or when it is pushed as a use when processing a nested
210211
// borrow.
211212
case OperandOwnership::EndBorrow:
213+
leafUse(use);
212214
break;
213215

214216
case OperandOwnership::InteriorPointer:
@@ -220,24 +222,32 @@ bool swift::findInnerTransitiveGuaranteedUses(
220222
}
221223
break;
222224

223-
case OperandOwnership::ForwardingBorrow:
224-
ForwardingOperand(use).visitForwardedValues(
225-
[&](SILValue transitiveValue) {
226-
// Do not include transitive uses with 'none' ownership
227-
if (transitiveValue.getOwnershipKind() == OwnershipKind::None)
228-
return true;
229-
for (auto *transitiveUse : transitiveValue->getUses()) {
230-
if (transitiveUse->getOperandOwnership()
231-
!= OperandOwnership::NonUse) {
232-
worklist.insert(use);
233-
}
234-
}
235-
return true;
236-
});
225+
case OperandOwnership::ForwardingBorrow: {
226+
bool nonLeaf = false;
227+
ForwardingOperand(use).visitForwardedValues([&](SILValue result) {
228+
// Do not include transitive uses with 'none' ownership
229+
if (result.getOwnershipKind() == OwnershipKind::None)
230+
return true;
231+
for (auto *resultUse : result->getUses()) {
232+
if (resultUse->getOperandOwnership() != OperandOwnership::NonUse) {
233+
nonLeaf = true;
234+
worklist.insert(resultUse);
235+
}
236+
}
237+
return true;
238+
});
239+
// e.g. A dead forwarded value, e.g. a switch_enum with only trivial uses,
240+
// must itself be a leaf use.
241+
if (!nonLeaf) {
242+
leafUse(use);
243+
}
237244
break;
238-
245+
}
239246
case OperandOwnership::Borrow:
240-
BorrowingOperand(use).visitExtendedScopeEndingUses(recordLeafUse);
247+
BorrowingOperand(use).visitExtendedScopeEndingUses([&](Operand *endUse) {
248+
leafUse(endUse);
249+
return true;
250+
});
241251
}
242252
}
243253
return true;

0 commit comments

Comments
 (0)