@@ -52,21 +52,36 @@ class LiveRange {
5252 // / introducer and not to be forwarding.
5353 OwnedValueIntroducer introducer;
5454
55+ // / A vector that we store all of our uses into.
56+ // /
57+ // / Some properties of this array are:
58+ // /
59+ // / 1. It is only mutated in the constructor of LiveRange.
60+ // /
61+ // / 2. destroyingUses, ownershipForwardingUses, and unknownConsumingUses are
62+ // / views into this array. We store the respective uses in the aforementioned
63+ // / order. This is why it is important not to mutate consumingUses after we
64+ // / construct the LiveRange since going from small -> large could invalidate
65+ // / the uses.
66+ SmallVector<Operand *, 6 > consumingUses;
67+
5568 // / A list of destroy_values of the live range.
56- SmallVector<Operand *, 2 > destroyingUses;
69+ // /
70+ // / This is just a view into consuming uses.
71+ ArrayRef<Operand *> destroyingUses;
5772
5873 // / A list of forwarding instructions that forward owned ownership, but that
5974 // / are also able to be converted to guaranteed ownership. If we are able to
6075 // / eliminate this LiveRange due to it being from a guaranteed value, we must
6176 // / flip the ownership of all of these instructions to guaranteed from owned.
6277 // /
6378 // / Corresponds to isOwnershipForwardingInst(...).
64- SmallVector <Operand *, 2 > ownershipForwardingUses;
79+ ArrayRef <Operand *> ownershipForwardingUses;
6580
6681 // / Consuming uses that we were not able to understand as a forwarding
6782 // / instruction or a destroy_value. These must be passed a strongly control
6883 // / equivalent +1 value.
69- SmallVector <Operand *, 2 > unknownConsumingUses;
84+ ArrayRef <Operand *> unknownConsumingUses;
7085
7186public:
7287 LiveRange (SILValue value);
@@ -87,6 +102,11 @@ class LiveRange {
87102 HasConsumingUse_t
88103 hasUnknownConsumingUse (bool assumingFixedPoint = false ) const ;
89104
105+ // / Return an array ref to /all/ consuming uses. Will include all 3 sorts of
106+ // / consuming uses: destroying uses, forwarding consuming uses, and unknown
107+ // / forwarding instruction.
108+ ArrayRef<Operand *> getAllConsumingUses () const { return consumingUses; }
109+
90110 ArrayRef<Operand *> getDestroyingUses () const { return destroyingUses; }
91111
92112private:
@@ -121,7 +141,7 @@ class LiveRange {
121141 return ownershipForwardingUses;
122142 }
123143
124- void convertOwnedGeneralForwardingUsesToGuaranteed ();
144+ void convertOwnedGeneralForwardingUsesToGuaranteed () && ;
125145
126146 // / A consuming operation that:
127147 // /
@@ -192,6 +212,10 @@ LiveRange::LiveRange(SILValue value)
192212 ownershipForwardingUses(), unknownConsumingUses() {
193213 assert (introducer.value .getOwnershipKind () == ValueOwnershipKind::Owned);
194214
215+ SmallVector<Operand *, 32 > tmpDestroyingUses;
216+ SmallVector<Operand *, 32 > tmpForwardingConsumingUses;
217+ SmallVector<Operand *, 32 > tmpUnknownConsumingUses;
218+
195219 // We know that our silvalue produces an @owned value. Look through all of our
196220 // uses and classify them as either consuming or not.
197221 SmallVector<Operand *, 32 > worklist (introducer.value ->getUses ());
@@ -220,7 +244,7 @@ LiveRange::LiveRange(SILValue value)
220244 // Ok, we know now that we have a consuming use. See if we have a destroy
221245 // value, quickly up front. If we do have one, stash it and continue.
222246 if (isa<DestroyValueInst>(user)) {
223- destroyingUses .push_back (op);
247+ tmpDestroyingUses .push_back (op);
224248 continue ;
225249 }
226250
@@ -244,13 +268,13 @@ LiveRange::LiveRange(SILValue value)
244268 return v.getOwnershipKind () ==
245269 ValueOwnershipKind::Owned;
246270 })) {
247- unknownConsumingUses .push_back (op);
271+ tmpUnknownConsumingUses .push_back (op);
248272 continue ;
249273 }
250274
251275 // Ok, this is a forwarding instruction whose ownership we can flip from
252276 // owned -> guaranteed.
253- ownershipForwardingUses .push_back (op);
277+ tmpForwardingConsumingUses .push_back (op);
254278
255279 // If we have a non-terminator, just visit its users recursively to see if
256280 // the the users force the live range to be alive.
@@ -284,6 +308,20 @@ LiveRange::LiveRange(SILValue value)
284308 }
285309 }
286310 }
311+
312+ // The order in which we append these to consumingUses matters since we assume
313+ // their order as an invariant. This is done to ensure that we can pass off
314+ // all of our uses or individual sub-arrays of our users without needing to
315+ // move around memory.
316+ llvm::copy (tmpDestroyingUses, std::back_inserter (consumingUses));
317+ llvm::copy (tmpForwardingConsumingUses, std::back_inserter (consumingUses));
318+ llvm::copy (tmpUnknownConsumingUses, std::back_inserter (consumingUses));
319+
320+ auto cUseArrayRef = llvm::makeArrayRef (consumingUses);
321+ destroyingUses = cUseArrayRef.take_front (tmpDestroyingUses.size ());
322+ ownershipForwardingUses = cUseArrayRef.slice (
323+ tmpDestroyingUses.size (), tmpForwardingConsumingUses.size ());
324+ unknownConsumingUses = cUseArrayRef.take_back (tmpUnknownConsumingUses.size ());
287325}
288326
289327void LiveRange::insertEndBorrowsAtDestroys (
@@ -339,9 +377,10 @@ void LiveRange::insertEndBorrowsAtDestroys(
339377 }
340378}
341379
342- void LiveRange::convertOwnedGeneralForwardingUsesToGuaranteed () {
380+ void LiveRange::convertOwnedGeneralForwardingUsesToGuaranteed () && {
343381 while (!ownershipForwardingUses.empty ()) {
344- auto *i = ownershipForwardingUses.pop_back_val ()->getUser ();
382+ auto *i = ownershipForwardingUses.back ()->getUser ();
383+ ownershipForwardingUses = ownershipForwardingUses.drop_back ();
345384
346385 // If this is a term inst, just convert all of its incoming values that are
347386 // owned to be guaranteed.
@@ -402,7 +441,8 @@ void LiveRange::convertToGuaranteedAndRAUW(SILValue newGuaranteedValue,
402441 InstModCallbacks callbacks) && {
403442 auto *value = cast<SingleValueInstruction>(introducer.value );
404443 while (!destroyingUses.empty ()) {
405- auto *d = destroyingUses.pop_back_val ();
444+ auto *d = destroyingUses.back ();
445+ destroyingUses = destroyingUses.drop_back ();
406446 callbacks.deleteInst (d->getUser ());
407447 ++NumEliminatedInsts;
408448 }
@@ -412,7 +452,7 @@ void LiveRange::convertToGuaranteedAndRAUW(SILValue newGuaranteedValue,
412452 // Then change all of our guaranteed forwarding insts to have guaranteed
413453 // ownership kind instead of what ever they previously had (ignoring trivial
414454 // results);
415- convertOwnedGeneralForwardingUsesToGuaranteed ();
455+ std::move (* this ). convertOwnedGeneralForwardingUsesToGuaranteed ();
416456}
417457
418458void LiveRange::convertArgToGuaranteed (DeadEndBlocks &deadEndBlocks,
@@ -429,15 +469,16 @@ void LiveRange::convertArgToGuaranteed(DeadEndBlocks &deadEndBlocks,
429469
430470 // Then eliminate all of the destroys...
431471 while (!destroyingUses.empty ()) {
432- auto *d = destroyingUses.pop_back_val ();
472+ auto *d = destroyingUses.back ();
473+ destroyingUses = destroyingUses.drop_back ();
433474 callbacks.deleteInst (d->getUser ());
434475 ++NumEliminatedInsts;
435476 }
436477
437478 // and change all of our guaranteed forwarding insts to have guaranteed
438479 // ownership kind instead of what ever they previously had (ignoring trivial
439480 // results);
440- convertOwnedGeneralForwardingUsesToGuaranteed ();
481+ std::move (* this ). convertOwnedGeneralForwardingUsesToGuaranteed ();
441482}
442483
443484LiveRange::HasConsumingUse_t
@@ -1297,8 +1338,9 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst
12971338 SmallVector<Operand *, 8 > scratchSpace;
12981339 SmallPtrSet<SILBasicBlock *, 4 > visitedBlocks;
12991340 if (llvm::any_of (borrowScopeIntroducers, [&](BorrowedValue borrowScope) {
1300- return !borrowScope.areUsesWithinScope (
1301- destroys, scratchSpace, visitedBlocks, getDeadEndBlocks ());
1341+ return !borrowScope.areUsesWithinScope (lr.getAllConsumingUses (),
1342+ scratchSpace, visitedBlocks,
1343+ getDeadEndBlocks ());
13021344 })) {
13031345 return false ;
13041346 }
@@ -1330,12 +1372,11 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst
13301372 return false ;
13311373 }
13321374
1333- if (llvm::any_of (borrowScopeIntroducers,
1334- [&](BorrowedValue borrowScope) {
1335- return !borrowScope.areUsesWithinScope (
1336- phiArgLR.getDestroyingUses (), scratchSpace,
1337- visitedBlocks, getDeadEndBlocks ());
1338- })) {
1375+ if (llvm::any_of (borrowScopeIntroducers, [&](BorrowedValue borrowScope) {
1376+ return !borrowScope.areUsesWithinScope (
1377+ phiArgLR.getAllConsumingUses (), scratchSpace, visitedBlocks,
1378+ getDeadEndBlocks ());
1379+ })) {
13391380 return false ;
13401381 }
13411382 }
@@ -1641,7 +1682,7 @@ class StorageGuaranteesLoadVisitor
16411682 SmallPtrSet<SILBasicBlock *, 4 > visitedBlocks;
16421683 LinearLifetimeChecker checker (visitedBlocks, ARCOpt.getDeadEndBlocks ());
16431684 if (!checker.validateLifetime (access, endScopeUses,
1644- liveRange.getDestroyingUses ())) {
1685+ liveRange.getAllConsumingUses ())) {
16451686 // If we fail the linear lifetime check, then just recur:
16461687 return next (access->getOperand ());
16471688 }
@@ -1738,8 +1779,8 @@ class StorageGuaranteesLoadVisitor
17381779 LinearLifetimeChecker checker (visitedBlocks, ARCOpt.getDeadEndBlocks ());
17391780
17401781 // Returns true on success. So we invert.
1741- bool foundError = !checker.validateLifetime (baseObject, endScopeInsts,
1742- liveRange.getDestroyingUses ());
1782+ bool foundError = !checker.validateLifetime (
1783+ baseObject, endScopeInsts, liveRange.getAllConsumingUses ());
17431784 return answer (foundError);
17441785 }
17451786
@@ -1777,7 +1818,7 @@ class StorageGuaranteesLoadVisitor
17771818 // Returns true on success. So we invert.
17781819 bool foundError = !checker.validateLifetime (
17791820 stack, destroyAddrOperands /* consuming users*/ ,
1780- liveRange.getDestroyingUses () /* non consuming users*/ );
1821+ liveRange.getAllConsumingUses () /* non consuming users*/ );
17811822 return answer (foundError);
17821823 }
17831824
0 commit comments