@@ -53,8 +53,6 @@ bool swift::hasPointerEscape(BorrowedValue value) {
53
53
case OperandOwnership::InteriorPointer:
54
54
case OperandOwnership::BitwiseEscape:
55
55
break ;
56
-
57
- case OperandOwnership::GuaranteedForwardingPhi:
58
56
case OperandOwnership::Reborrow: {
59
57
SILArgument *phi = cast<BranchInst>(op->getUser ())
60
58
->getDestBB ()
@@ -84,17 +82,23 @@ bool swift::hasPointerEscape(BorrowedValue value) {
84
82
return false ;
85
83
}
86
84
87
- bool swift::canOpcodeForwardGuaranteedValues (SILValue value) {
88
- if (auto *inst = value->getDefiningInstructionOrTerminator ()) {
89
- if (auto *mixin = OwnershipForwardingMixin::get (inst)) {
85
+ bool swift::canOpcodeForwardInnerGuaranteedValues (SILValue value) {
86
+ // If we have an argument from a transforming terminator, we can forward
87
+ // guaranteed.
88
+ if (auto *arg = dyn_cast<SILArgument>(value))
89
+ if (auto *ti = arg->getSingleTerminator ())
90
+ if (ti->mayHaveTerminatorResult ())
91
+ return OwnershipForwardingMixin::get (ti)->preservesOwnership ();
92
+
93
+ if (auto *inst = value->getDefiningInstruction ())
94
+ if (auto *mixin = OwnershipForwardingMixin::get (inst))
90
95
return mixin->preservesOwnership () &&
91
- !isa<OwnedFirstArgForwardingSingleValueInst>(inst);
92
- }
93
- }
96
+ !isa<OwnedFirstArgForwardingSingleValueInst>(inst);
97
+
94
98
return false ;
95
99
}
96
100
97
- bool swift::canOpcodeForwardGuaranteedValues (Operand *use) {
101
+ bool swift::canOpcodeForwardInnerGuaranteedValues (Operand *use) {
98
102
if (auto *mixin = OwnershipForwardingMixin::get (use->getUser ()))
99
103
return mixin->preservesOwnership () &&
100
104
!isa<OwnedFirstArgForwardingSingleValueInst>(use->getUser ());
@@ -213,6 +217,11 @@ bool swift::findInnerTransitiveGuaranteedUses(
213
217
// Do not include transitive uses with 'none' ownership
214
218
if (result->getOwnershipKind () == OwnershipKind::None)
215
219
return true ;
220
+ if (auto *phi = SILArgument::asPhi (result)) {
221
+ leafUse (use);
222
+ foundPointerEscape = true ;
223
+ return true ;
224
+ }
216
225
for (auto *resultUse : result->getUses ()) {
217
226
if (resultUse->getOperandOwnership () != OperandOwnership::NonUse) {
218
227
nonLeaf = true ;
@@ -228,11 +237,6 @@ bool swift::findInnerTransitiveGuaranteedUses(
228
237
}
229
238
break ;
230
239
}
231
- case OperandOwnership::GuaranteedForwardingPhi: {
232
- leafUse (use);
233
- foundPointerEscape = true ;
234
- break ;
235
- }
236
240
case OperandOwnership::Borrow:
237
241
// FIXME: Use visitExtendedScopeEndingUses and audit all clients to handle
238
242
// reborrows.
@@ -330,17 +334,6 @@ bool swift::findExtendedUsesOfSimpleBorrowedValue(
330
334
}
331
335
recordUse (use);
332
336
break ;
333
- // \p borrowedValue will dominate this GuaranteedForwardingPhi, because we
334
- // return false in the case of Reborrow.
335
- case OperandOwnership::GuaranteedForwardingPhi: {
336
- SILArgument *phi = PhiOperand (use).getValue ();
337
- for (auto *use : phi->getUses ()) {
338
- if (use->getOperandOwnership () != OperandOwnership::NonUse)
339
- worklist.insert (use);
340
- }
341
- recordUse (use);
342
- break ;
343
- }
344
337
case OperandOwnership::GuaranteedForwarding: {
345
338
ForwardingOperand (use).visitForwardedValues ([&](SILValue result) {
346
339
// Do not include transitive uses with 'none' ownership
@@ -413,15 +406,12 @@ bool swift::visitGuaranteedForwardingPhisForSSAValue(
413
406
// GuaranteedForwardingPhi uses.
414
407
for (auto *use : value->getUses ()) {
415
408
if (use->getOperandOwnership () == OperandOwnership::GuaranteedForwarding) {
416
- guaranteedForwardingOps.insert (use);
417
- continue ;
418
- }
419
- if (use->getOperandOwnership () ==
420
- OperandOwnership::GuaranteedForwardingPhi) {
421
- if (!visitor (use)) {
422
- return false ;
409
+ if (PhiOperand (use)) {
410
+ if (!visitor (use)) {
411
+ return false ;
412
+ }
423
413
}
424
- continue ;
414
+ guaranteedForwardingOps. insert (use) ;
425
415
}
426
416
}
427
417
@@ -431,15 +421,12 @@ bool swift::visitGuaranteedForwardingPhisForSSAValue(
431
421
for (auto *valUse : val->getUses ()) {
432
422
if (valUse->getOperandOwnership () ==
433
423
OperandOwnership::GuaranteedForwarding) {
434
- guaranteedForwardingOps.insert (valUse);
435
- continue ;
436
- }
437
- if (valUse->getOperandOwnership () ==
438
- OperandOwnership::GuaranteedForwardingPhi) {
439
- if (!visitor (valUse)) {
440
- return false ;
424
+ if (PhiOperand (valUse)) {
425
+ if (!visitor (valUse)) {
426
+ return false ;
427
+ }
441
428
}
442
- continue ;
429
+ guaranteedForwardingOps. insert (valUse) ;
443
430
}
444
431
}
445
432
}
@@ -1208,11 +1195,12 @@ bool swift::getAllBorrowIntroducingValues(SILValue inputValue,
1208
1195
if (inputValue->getOwnershipKind () != OwnershipKind::Guaranteed)
1209
1196
return false ;
1210
1197
1211
- SmallVector <SILValue, 32 > worklist;
1212
- worklist.emplace_back (inputValue);
1198
+ SmallSetVector <SILValue, 32 > worklist;
1199
+ worklist.insert (inputValue);
1213
1200
1214
- while (!worklist.empty ()) {
1215
- SILValue value = worklist.pop_back_val ();
1201
+ // worklist grows in this loop.
1202
+ for (unsigned idx = 0 ; idx < worklist.size (); idx++) {
1203
+ SILValue value = worklist[idx];
1216
1204
1217
1205
// First check if v is an introducer. If so, stash it and continue.
1218
1206
if (auto scopeIntroducer = BorrowedValue (value)) {
@@ -1230,11 +1218,26 @@ bool swift::getAllBorrowIntroducingValues(SILValue inputValue,
1230
1218
// Otherwise if v is an ownership forwarding value, add its defining
1231
1219
// instruction
1232
1220
if (isGuaranteedForwarding (value)) {
1233
- if (auto *i = value->getDefiningInstructionOrTerminator ()) {
1234
- llvm::copy (i->getNonTypeDependentOperandValues (),
1235
- std::back_inserter (worklist));
1221
+ if (auto *i = value->getDefiningInstruction ()) {
1222
+ for (SILValue opValue : i->getNonTypeDependentOperandValues ()) {
1223
+ worklist.insert (opValue);
1224
+ }
1236
1225
continue ;
1237
1226
}
1227
+
1228
+ // Otherwise, we should have a block argument that is defined by a single
1229
+ // predecessor terminator.
1230
+ auto *arg = cast<SILPhiArgument>(value);
1231
+ if (arg->isTerminatorResult ()) {
1232
+ if (auto *forwardedOper = arg->forwardedTerminatorResultOperand ()) {
1233
+ worklist.insert (forwardedOper->get ());
1234
+ continue ;
1235
+ }
1236
+ }
1237
+ arg->visitIncomingPhiOperands ([&](auto *operand) {
1238
+ worklist.insert (operand->get ());
1239
+ return true ;
1240
+ });
1238
1241
}
1239
1242
1240
1243
// Otherwise, this is an introducer we do not understand. Bail and return
@@ -1373,31 +1376,16 @@ ForwardingOperand::ForwardingOperand(Operand *use) {
1373
1376
if (use->isTypeDependent ())
1374
1377
return ;
1375
1378
1376
- if (!OwnershipForwardingMixin::isa (use->getUser ())) {
1377
- return ;
1378
- }
1379
- #ifndef NDEBUG
1380
1379
switch (use->getOperandOwnership ()) {
1381
1380
case OperandOwnership::ForwardingUnowned:
1382
1381
case OperandOwnership::ForwardingConsume:
1383
1382
case OperandOwnership::GuaranteedForwarding:
1383
+ this ->use = use;
1384
1384
break ;
1385
- case OperandOwnership::NonUse:
1386
- case OperandOwnership::TrivialUse:
1387
- case OperandOwnership::InstantaneousUse:
1388
- case OperandOwnership::UnownedInstantaneousUse:
1389
- case OperandOwnership::PointerEscape:
1390
- case OperandOwnership::BitwiseEscape:
1391
- case OperandOwnership::Borrow:
1392
- case OperandOwnership::DestroyingConsume:
1393
- case OperandOwnership::InteriorPointer:
1394
- case OperandOwnership::GuaranteedForwardingPhi:
1395
- case OperandOwnership::EndBorrow:
1396
- case OperandOwnership::Reborrow:
1397
- llvm_unreachable (" this isn't the operand being forwarding!" );
1385
+ default :
1386
+ this ->use = nullptr ;
1387
+ return ;
1398
1388
}
1399
- #endif
1400
- this ->use = use;
1401
1389
}
1402
1390
1403
1391
ValueOwnershipKind ForwardingOperand::getForwardingOwnershipKind () const {
@@ -1603,15 +1591,22 @@ bool ForwardingOperand::visitForwardedValues(
1603
1591
// "transforming terminators"... We know that this means that we should at
1604
1592
// most have a single phi argument.
1605
1593
auto *ti = cast<TermInst>(user);
1606
- return llvm::all_of (ti->getSuccessorBlocks (), [&](SILBasicBlock *succBlock) {
1607
- // If we do not have any arguments, then continue.
1608
- if (succBlock->args_empty ())
1609
- return true ;
1594
+ if (ti->mayHaveTerminatorResult ()) {
1595
+ return llvm::all_of (
1596
+ ti->getSuccessorBlocks (), [&](SILBasicBlock *succBlock) {
1597
+ // If we do not have any arguments, then continue.
1598
+ if (succBlock->args_empty ())
1599
+ return true ;
1610
1600
1611
- auto args = succBlock->getSILPhiArguments ();
1612
- assert (args.size () == 1 && " Transforming terminator with multiple args?!" );
1613
- return visitor (args[0 ]);
1614
- });
1601
+ auto args = succBlock->getSILPhiArguments ();
1602
+ assert (args.size () == 1 &&
1603
+ " Transforming terminator with multiple args?!" );
1604
+ return visitor (args[0 ]);
1605
+ });
1606
+ }
1607
+
1608
+ auto *succArg = PhiOperand (use).getValue ();
1609
+ return visitor (succArg);
1615
1610
}
1616
1611
1617
1612
void swift::visitExtendedReborrowPhiBaseValuePairs (
0 commit comments