@@ -39,11 +39,12 @@ STATISTIC(NumLoadCopyConvertedToLoadBorrow,
39
39
// Utility
40
40
// ===----------------------------------------------------------------------===//
41
41
42
- // / Return true if v only has invalidating uses that are destroy_value.
42
+ // / Return true if v only has invalidating uses that are destroy_value. Such an
43
+ // / owned value is said to represent a dead "live range".
43
44
// /
44
45
// / Semantically this implies that a value is never passed off as +1 to memory
45
46
// / or another function implying it can be used everywhere at +0.
46
- static bool isConsumed (
47
+ static bool isDeadLiveRange (
47
48
SILValue v, SmallVectorImpl<DestroyValueInst *> &destroys,
48
49
NullablePtr<SmallVectorImpl<SILInstruction *>> forwardingInsts = nullptr ) {
49
50
assert (v.getOwnershipKind () == ValueOwnershipKind::Owned);
@@ -99,8 +100,9 @@ static bool isConsumed(
99
100
continue ;
100
101
}
101
102
102
- // Otherwise be conservative and assume that we /may consume/ the value.
103
- return true ;
103
+ // Otherwise be conservative and assume that we /may consume/ the value,
104
+ // so the live range must not be eliminated.
105
+ return false ;
104
106
}
105
107
case UseLifetimeConstraint::MustBeLive:
106
108
// Ok, this constraint can take something owned as live. Assert that it
@@ -114,7 +116,9 @@ static bool isConsumed(
114
116
}
115
117
}
116
118
117
- return false ;
119
+ // We visited all of our users and were able to prove that all of them were
120
+ // benign. Return true.
121
+ return true ;
118
122
}
119
123
120
124
// ===----------------------------------------------------------------------===//
@@ -334,17 +338,14 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst
334
338
if (!canHandleOperand (cvi->getOperand (), borrowIntroducers))
335
339
return false ;
336
340
337
- // Then go over all of our uses. Find our destroying instructions (ignoring
338
- // forwarding instructions that can forward both owned and guaranteed) and
339
- // make sure all of them are destroy_value. For our non-destroying
340
- // instructions, make sure that they accept a guaranteed value. After that,
341
- // make sure that our destroys are within the lifetime of our borrowed values.
342
- //
343
- // TODO: Change isConsumed to return branch propagated users for destroys, so
344
- // we do not need to construct another array.
341
+ // Then go over all of our uses and see if the value returned by our copy
342
+ // value forms a dead live range. If we do not have a dead live range, there
343
+ // must be some consuming use that we either do not understand is /actually/
344
+ // forwarding or a user that truly represents a necessary consume of the
345
+ // value (e.x. storing into memory).
345
346
SmallVector<DestroyValueInst *, 16 > destroys;
346
347
SmallVector<SILInstruction *, 16 > guaranteedForwardingInsts;
347
- if (isConsumed (cvi, destroys, &guaranteedForwardingInsts))
348
+ if (! isDeadLiveRange (cvi, destroys, &guaranteedForwardingInsts))
348
349
return false ;
349
350
350
351
// Next check if we have any destroys at all of our copy_value and an operand
@@ -726,15 +727,15 @@ bool SemanticARCOptVisitor::visitLoadInst(LoadInst *li) {
726
727
if (li->getOwnershipQualifier () != LoadOwnershipQualifier::Copy)
727
728
return false ;
728
729
729
- // Ok, we have our load [copy]. Make sure its value is never
730
- // consumed. If it is consumed, we need to pass off a +1 value, so
731
- // bail.
730
+ // Ok, we have our load [copy]. Make sure its value is truly a dead live range
731
+ // implying it is only ever consumed by destroy_value instructions. If it is
732
+ // consumed, we need to pass off a +1 value, so bail.
732
733
//
733
734
// FIXME: We should consider if it is worth promoting a load [copy]
734
735
// -> load_borrow if we can put a copy_value on a cold path and thus
735
736
// eliminate RR traffic on a hot path.
736
737
SmallVector<DestroyValueInst *, 32 > destroyValues;
737
- if (isConsumed (li, destroyValues))
738
+ if (! isDeadLiveRange (li, destroyValues))
738
739
return false ;
739
740
740
741
// Then check if our address is guaranteed to never be written to within the
0 commit comments