@@ -54,9 +54,13 @@ class LiveRange {
54
54
// / A list of destroy_values of the live range.
55
55
SmallVector<Operand *, 2 > destroyingUses;
56
56
57
- // / A list of forwarding instructions that forward our destroys ownership, but
58
- // / that are also able to forward guaranteed ownership.
59
- SmallVector<Operand *, 2 > generalForwardingUses;
57
+ // / A list of forwarding instructions that forward owned ownership, but that
58
+ // / are also able to be converted to guaranteed ownership. If we are able to
59
+ // / eliminate this LiveRange due to it being from a guaranteed value, we must
60
+ // / flip the ownership of all of these instructions to guaranteed from owned.
61
+ // /
62
+ // / Corresponds to isOwnershipForwardingInst(...).
63
+ SmallVector<Operand *, 2 > ownershipForwardingUses;
60
64
61
65
// / Consuming uses that we were not able to understand as a forwarding
62
66
// / instruction or a destroy_value. These must be passed a strongly control
@@ -80,8 +84,7 @@ class LiveRange {
80
84
// / Semantically this implies that a value is never passed off as +1 to memory
81
85
// / or another function implying it can be used everywhere at +0.
82
86
HasConsumingUse_t
83
- hasConsumingUse (FrozenMultiMap<SILPhiArgument *, OwnedValueIntroducer>
84
- *phiToIncomingValueMultiMap = nullptr ) const ;
87
+ hasUnknownConsumingUse (bool assumingFixedPoint = false ) const ;
85
88
86
89
ArrayRef<Operand *> getDestroyingUses () const { return destroyingUses; }
87
90
@@ -113,8 +116,8 @@ class LiveRange {
113
116
114
117
OwnedValueIntroducer getIntroducer () const { return introducer; }
115
118
116
- ArrayRef<Operand *> getNonConsumingForwardingUses () const {
117
- return generalForwardingUses ;
119
+ ArrayRef<Operand *> getOwnershipForwardingUses () const {
120
+ return ownershipForwardingUses ;
118
121
}
119
122
120
123
void convertOwnedGeneralForwardingUsesToGuaranteed ();
@@ -185,7 +188,7 @@ LiveRange::DestroyingInstsRange LiveRange::getDestroyingInsts() const {
185
188
186
189
LiveRange::LiveRange (SILValue value)
187
190
: introducer(*OwnedValueIntroducer::get (value)), destroyingUses(),
188
- generalForwardingUses (), unknownConsumingUses() {
191
+ ownershipForwardingUses (), unknownConsumingUses() {
189
192
assert (introducer.value .getOwnershipKind () == ValueOwnershipKind::Owned);
190
193
191
194
// We know that our silvalue produces an @owned value. Look through all of our
@@ -246,7 +249,7 @@ LiveRange::LiveRange(SILValue value)
246
249
247
250
// Ok, this is a forwarding instruction whose ownership we can flip from
248
251
// owned -> guaranteed.
249
- generalForwardingUses .push_back (op);
252
+ ownershipForwardingUses .push_back (op);
250
253
251
254
// If we have a non-terminator, just visit its users recursively to see if
252
255
// the the users force the live range to be alive.
@@ -336,8 +339,8 @@ void LiveRange::insertEndBorrowsAtDestroys(
336
339
}
337
340
338
341
void LiveRange::convertOwnedGeneralForwardingUsesToGuaranteed () {
339
- while (!generalForwardingUses .empty ()) {
340
- auto *i = generalForwardingUses .pop_back_val ()->getUser ();
342
+ while (!ownershipForwardingUses .empty ()) {
343
+ auto *i = ownershipForwardingUses .pop_back_val ()->getUser ();
341
344
342
345
// If this is a term inst, just convert all of its incoming values that are
343
346
// owned to be guaranteed.
@@ -436,9 +439,8 @@ void LiveRange::convertArgToGuaranteed(DeadEndBlocks &deadEndBlocks,
436
439
convertOwnedGeneralForwardingUsesToGuaranteed ();
437
440
}
438
441
439
- LiveRange::HasConsumingUse_t LiveRange::hasConsumingUse (
440
- FrozenMultiMap<SILPhiArgument *, OwnedValueIntroducer>
441
- *phiToIncomingValueMultiMap) const {
442
+ LiveRange::HasConsumingUse_t
443
+ LiveRange::hasUnknownConsumingUse (bool assumingAtFixPoint) const {
442
444
// First do a quick check if we have /any/ unknown consuming
443
445
// uses. If we do not have any, return false early.
444
446
if (unknownConsumingUses.empty ()) {
@@ -447,7 +449,7 @@ LiveRange::HasConsumingUse_t LiveRange::hasConsumingUse(
447
449
448
450
// Ok, we do have some unknown consuming uses. If we aren't asked to
449
451
// update phiToIncomingValueMultiMap, then just return true quickly.
450
- if (!phiToIncomingValueMultiMap ) {
452
+ if (!assumingAtFixPoint ) {
451
453
return HasConsumingUse_t::Yes;
452
454
}
453
455
@@ -828,7 +830,6 @@ static bool canEliminatePhi(
828
830
if (!introducer.isConvertableToGuaranteed ()) {
829
831
return false ;
830
832
}
831
-
832
833
// If this linear search is too slow, we can change the
833
834
// multimap to sort the mapped to list by pointer
834
835
// instead of insertion order. In such a case, we could
@@ -870,17 +871,17 @@ bool SemanticARCOptVisitor::performPostPeepholeOwnedArgElimination() {
870
871
// First compute the LiveRange for our phi argument. For simplicity, we only
871
872
// handle cases now where our phi argument does not have any phi unknown
872
873
// consumers.
873
- SILPhiArgument *phiArg = pair.first ;
874
- LiveRange phiArgLiveRange (phiArg );
875
- if (bool (phiArgLiveRange. hasConsumingUse ())) {
874
+ SILPhiArgument *phi = pair.first ;
875
+ LiveRange phiLiveRange (phi );
876
+ if (bool (phiLiveRange. hasUnknownConsumingUse ())) {
876
877
continue ;
877
878
}
878
879
879
880
// Ok, we know that our phi argument /could/ be converted to guaranteed if
880
881
// our incoming values are able to be converted to guaranteed. Now for each
881
882
// incoming value, compute the incoming values ownership roots and see if
882
883
// all of the ownership roots are in our owned incoming value array.
883
- if (!phiArg ->getIncomingPhiOperands (incomingValueOperandList)) {
884
+ if (!phi ->getIncomingPhiOperands (incomingValueOperandList)) {
884
885
continue ;
885
886
}
886
887
@@ -903,7 +904,7 @@ bool SemanticARCOptVisitor::performPostPeepholeOwnedArgElimination() {
903
904
for (Operand *incomingValueOperand : incomingValueOperandList) {
904
905
originalIncomingValues.push_back (incomingValueOperand->get ());
905
906
SILType type = incomingValueOperand->get ()->getType ();
906
- auto *undef = SILUndef::get (type, *phiArg ->getFunction ());
907
+ auto *undef = SILUndef::get (type, *phi ->getFunction ());
907
908
incomingValueOperand->set (undef);
908
909
}
909
910
@@ -956,7 +957,7 @@ bool SemanticARCOptVisitor::performPostPeepholeOwnedArgElimination() {
956
957
}
957
958
958
959
// Then convert the phi's live range to be guaranteed.
959
- std::move (phiArgLiveRange )
960
+ std::move (phiLiveRange )
960
961
.convertArgToGuaranteed (getDeadEndBlocks (), lifetimeFrontier,
961
962
getCallbacks ());
962
963
@@ -980,7 +981,7 @@ bool SemanticARCOptVisitor::performPostPeepholeOwnedArgElimination() {
980
981
981
982
madeChange = true ;
982
983
if (VerifyAfterTransform) {
983
- phiArg ->getFunction ()->verify ();
984
+ phi ->getFunction ()->verify ();
984
985
}
985
986
}
986
987
@@ -1175,9 +1176,9 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst
1175
1176
// forwarding or a user that truly represents a necessary consume of the value
1176
1177
// (e.x. storing into memory).
1177
1178
LiveRange lr (cvi);
1178
- auto hasConsumingUseState =
1179
- lr.hasConsumingUse (getPhiToIncomingValueMultiMap ());
1180
- if (hasConsumingUseState == LiveRange::HasConsumingUse_t::Yes) {
1179
+ auto hasUnknownConsumingUseState =
1180
+ lr.hasUnknownConsumingUse (getPhiToIncomingValueMultiMap ());
1181
+ if (hasUnknownConsumingUseState == LiveRange::HasConsumingUse_t::Yes) {
1181
1182
return false ;
1182
1183
}
1183
1184
@@ -1286,7 +1287,8 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst
1286
1287
// was consumed, the hasConsumedUse code updated phiToIncomingValueMultiMap
1287
1288
// for us before returning its prognosis. After we reach a fixed point, we
1288
1289
// will try to eliminate this value then.
1289
- if (hasConsumingUseState == LiveRange::HasConsumingUse_t::YesButAllPhiArgs) {
1290
+ if (hasUnknownConsumingUseState ==
1291
+ LiveRange::HasConsumingUse_t::YesButAllPhiArgs) {
1290
1292
auto *op = lr.getSingleUnknownConsumingUse ();
1291
1293
assert (op);
1292
1294
unsigned opNum = op->getOperandNumber ();
@@ -1302,7 +1304,7 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst
1302
1304
1303
1305
auto *arg = succBlock->getSILPhiArguments ()[opNum];
1304
1306
LiveRange phiArgLR (arg);
1305
- if (bool (phiArgLR.hasConsumingUse ())) {
1307
+ if (bool (phiArgLR.hasUnknownConsumingUse ())) {
1306
1308
return false ;
1307
1309
}
1308
1310
@@ -1784,7 +1786,7 @@ bool SemanticARCOptVisitor::visitLoadInst(LoadInst *li) {
1784
1786
// -> load_borrow if we can put a copy_value on a cold path and thus
1785
1787
// eliminate RR traffic on a hot path.
1786
1788
LiveRange lr (li);
1787
- if (bool (lr.hasConsumingUse ()))
1789
+ if (bool (lr.hasUnknownConsumingUse ()))
1788
1790
return false ;
1789
1791
1790
1792
// Then check if our address is ever written to. If it is, then we cannot use
0 commit comments