@@ -163,6 +163,14 @@ bool swift::canOpcodeForwardOwnedValues(Operand *use) {
163
163
// visitReborrow is not called for them.
164
164
bool swift::findInnerTransitiveGuaranteedUses (
165
165
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
+
166
174
// Push the value's immediate uses.
167
175
//
168
176
// TODO: The worklist can be a simple vector without any a membership check if
@@ -179,13 +187,6 @@ bool swift::findInnerTransitiveGuaranteedUses(
179
187
180
188
// --- Transitively follow forwarded uses and look for escapes.
181
189
182
- auto recordLeafUse = [&](Operand *use) {
183
- if (usePoints && use->getOperandOwnership () != OperandOwnership::NonUse) {
184
- usePoints->push_back (use);
185
- }
186
- return true ;
187
- };
188
-
189
190
// usePoints grows in this loop.
190
191
while (Operand *use = worklist.pop ()) {
191
192
switch (use->getOperandOwnership ()) {
@@ -209,6 +210,7 @@ bool swift::findInnerTransitiveGuaranteedUses(
209
210
// borrow scope, or when it is pushed as a use when processing a nested
210
211
// borrow.
211
212
case OperandOwnership::EndBorrow:
213
+ leafUse (use);
212
214
break ;
213
215
214
216
case OperandOwnership::InteriorPointer:
@@ -220,24 +222,32 @@ bool swift::findInnerTransitiveGuaranteedUses(
220
222
}
221
223
break ;
222
224
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
+ }
237
244
break ;
238
-
245
+ }
239
246
case OperandOwnership::Borrow:
240
- BorrowingOperand (use).visitExtendedScopeEndingUses (recordLeafUse);
247
+ BorrowingOperand (use).visitExtendedScopeEndingUses ([&](Operand *endUse) {
248
+ leafUse (endUse);
249
+ return true ;
250
+ });
241
251
}
242
252
}
243
253
return true ;
0 commit comments