25
25
26
26
using namespace swift ;
27
27
28
- bool swift::hasPointerEscape (BorrowedValue original) {
29
- ValueWorklist worklist (original->getFunction ());
30
- worklist.push (*original);
28
+ bool swift::findPointerEscape (SILValue original) {
29
+ if (original->getOwnershipKind () != OwnershipKind::Owned &&
30
+ original->getOwnershipKind () != OwnershipKind::Guaranteed) {
31
+ return false ;
32
+ }
31
33
32
- if (auto *phi = SILArgument::asPhi (*original)) {
34
+ ValueWorklist worklist (original->getFunction ());
35
+ worklist.push (original);
36
+ if (auto *phi = SILArgument::asPhi (original)) {
33
37
phi->visitTransitiveIncomingPhiOperands ([&](auto *phi, auto *operand) {
34
38
worklist.pushIfNotVisited (operand->get ());
35
39
return true ;
36
40
});
37
41
}
38
42
39
43
while (auto value = worklist.pop ()) {
40
- for (auto *op : value->getUses ()) {
41
- switch (op->getOperandOwnership ()) {
42
- case OperandOwnership::ForwardingUnowned:
44
+ for (auto use : value->getUses ()) {
45
+ switch (use->getOperandOwnership ()) {
43
46
case OperandOwnership::PointerEscape:
47
+ case OperandOwnership::ForwardingUnowned:
44
48
return true ;
45
-
49
+ case OperandOwnership::ForwardingConsume: {
50
+ auto *branch = dyn_cast<BranchInst>(use->getUser ());
51
+ if (!branch) {
52
+ // Non-phi forwarding consumes end the lifetime of an owned value.
53
+ break ;
54
+ }
55
+ auto *phi = branch->getDestBB ()->getArgument (use->getOperandNumber ());
56
+ worklist.pushIfNotVisited (phi);
57
+ break ;
58
+ }
59
+ case OperandOwnership::Borrow: {
60
+ auto borrowOp = BorrowingOperand (use);
61
+ if (auto borrowValue = borrowOp.getBorrowIntroducingUserResult ()) {
62
+ worklist.pushIfNotVisited (borrowValue.value );
63
+ }
64
+ break ;
65
+ }
46
66
case OperandOwnership::Reborrow: {
47
- SILArgument *phi = PhiOperand (op ).getValue ();
67
+ SILArgument *phi = PhiOperand (use ).getValue ();
48
68
worklist.pushIfNotVisited (phi);
49
69
break ;
50
70
}
51
-
52
71
case OperandOwnership::GuaranteedForwarding: {
53
72
// This may follow guaranteed phis.
54
- ForwardingOperand (op ).visitForwardedValues ([&](SILValue result) {
73
+ ForwardingOperand (use ).visitForwardedValues ([&](SILValue result) {
55
74
// Do not include transitive uses with 'none' ownership
56
75
if (result->getOwnershipKind () == OwnershipKind::None)
57
76
return true ;
@@ -60,42 +79,11 @@ bool swift::hasPointerEscape(BorrowedValue original) {
60
79
});
61
80
break ;
62
81
}
63
- default :
64
- break ;
65
- }
66
- }
67
- }
68
- return false ;
69
- }
70
-
71
- bool swift::hasPointerEscape (SILValue original) {
72
- if (auto borrowedValue = BorrowedValue (original)) {
73
- return hasPointerEscape (borrowedValue);
74
- }
75
- assert (original->getOwnershipKind () == OwnershipKind::Owned);
76
-
77
- ValueWorklist worklist (original->getFunction ());
78
- worklist.push (original);
79
- if (auto *phi = SILArgument::asPhi (original)) {
80
- phi->visitTransitiveIncomingPhiOperands ([&](auto *phi, auto *operand) {
81
- worklist.pushIfNotVisited (operand->get ());
82
- return true ;
83
- });
84
- }
85
- while (auto value = worklist.pop ()) {
86
- for (auto use : value->getUses ()) {
87
- switch (use->getOperandOwnership ()) {
88
- case OperandOwnership::PointerEscape:
89
- case OperandOwnership::ForwardingUnowned:
90
- return true ;
91
- case OperandOwnership::ForwardingConsume: {
92
- auto *branch = dyn_cast<BranchInst>(use->getUser ());
93
- if (!branch) {
94
- // Non-phi forwarding consumes end the lifetime of an owned value.
95
- break ;
82
+ case OperandOwnership::InteriorPointer: {
83
+ if (InteriorPointerOperand (use).findTransitiveUses () !=
84
+ AddressUseKind::NonEscaping) {
85
+ return true ;
96
86
}
97
- auto *phi = branch->getDestBB ()->getArgument (use->getOperandNumber ());
98
- worklist.pushIfNotVisited (phi);
99
87
break ;
100
88
}
101
89
default :
@@ -2282,27 +2270,27 @@ bool swift::isRedundantMoveValue(MoveValueInst *mvi) {
2282
2270
//
2283
2271
// Check this in two ways, one cheaper than the other.
2284
2272
2285
- // First, avoid calling hasPointerEscape (original).
2273
+ // First, avoid calling findPointerEscape (original).
2286
2274
//
2287
2275
// If the original value is not a phi (a phi's incoming values might have
2288
2276
// escaping uses) and its only user is the move, then it doesn't escape. Also
2289
2277
// if its only user is the move, then its only _consuming_ user is the move.
2290
2278
auto *singleUser =
2291
2279
original->getSingleUse () ? original->getSingleUse ()->getUser () : nullptr ;
2292
2280
if (mvi == singleUser && !SILArgument::asPhi (original)) {
2293
- assert (!hasPointerEscape (original));
2281
+ assert (!findPointerEscape (original));
2294
2282
assert (original->getSingleConsumingUse ()->getUser () == mvi);
2295
2283
// - !escaping(original)
2296
2284
// - singleConsumingUser(original) == move
2297
2285
return true ;
2298
2286
}
2299
2287
2300
- // Second, call hasPointerEscape (original).
2288
+ // Second, call findPointerEscape (original).
2301
2289
//
2302
2290
// Explicitly check both
2303
2291
// - !escaping(original)
2304
2292
// - singleConsumingUser(original) == move
2305
- auto originalHasEscape = hasPointerEscape (original);
2293
+ auto originalHasEscape = findPointerEscape (original);
2306
2294
auto *singleConsumingUser = original->getSingleConsumingUse ()
2307
2295
? original->getSingleConsumingUse ()->getUser ()
2308
2296
: nullptr ;
@@ -2311,6 +2299,6 @@ bool swift::isRedundantMoveValue(MoveValueInst *mvi) {
2311
2299
}
2312
2300
2313
2301
// (3) Escaping matches? (Expensive check, saved for last.)
2314
- auto moveHasEscape = hasPointerEscape (mvi);
2302
+ auto moveHasEscape = findPointerEscape (mvi);
2315
2303
return moveHasEscape == originalHasEscape;
2316
2304
}
0 commit comments