@@ -52,21 +52,36 @@ class LiveRange {
52
52
// / introducer and not to be forwarding.
53
53
OwnedValueIntroducer introducer;
54
54
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
+
55
68
// / 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;
57
72
58
73
// / A list of forwarding instructions that forward owned ownership, but that
59
74
// / are also able to be converted to guaranteed ownership. If we are able to
60
75
// / eliminate this LiveRange due to it being from a guaranteed value, we must
61
76
// / flip the ownership of all of these instructions to guaranteed from owned.
62
77
// /
63
78
// / Corresponds to isOwnershipForwardingInst(...).
64
- SmallVector <Operand *, 2 > ownershipForwardingUses;
79
+ ArrayRef <Operand *> ownershipForwardingUses;
65
80
66
81
// / Consuming uses that we were not able to understand as a forwarding
67
82
// / instruction or a destroy_value. These must be passed a strongly control
68
83
// / equivalent +1 value.
69
- SmallVector <Operand *, 2 > unknownConsumingUses;
84
+ ArrayRef <Operand *> unknownConsumingUses;
70
85
71
86
public:
72
87
LiveRange (SILValue value);
@@ -87,6 +102,11 @@ class LiveRange {
87
102
HasConsumingUse_t
88
103
hasUnknownConsumingUse (bool assumingFixedPoint = false ) const ;
89
104
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
+
90
110
ArrayRef<Operand *> getDestroyingUses () const { return destroyingUses; }
91
111
92
112
private:
@@ -121,7 +141,7 @@ class LiveRange {
121
141
return ownershipForwardingUses;
122
142
}
123
143
124
- void convertOwnedGeneralForwardingUsesToGuaranteed ();
144
+ void convertOwnedGeneralForwardingUsesToGuaranteed () && ;
125
145
126
146
// / A consuming operation that:
127
147
// /
@@ -192,6 +212,10 @@ LiveRange::LiveRange(SILValue value)
192
212
ownershipForwardingUses(), unknownConsumingUses() {
193
213
assert (introducer.value .getOwnershipKind () == ValueOwnershipKind::Owned);
194
214
215
+ SmallVector<Operand *, 32 > tmpDestroyingUses;
216
+ SmallVector<Operand *, 32 > tmpForwardingConsumingUses;
217
+ SmallVector<Operand *, 32 > tmpUnknownConsumingUses;
218
+
195
219
// We know that our silvalue produces an @owned value. Look through all of our
196
220
// uses and classify them as either consuming or not.
197
221
SmallVector<Operand *, 32 > worklist (introducer.value ->getUses ());
@@ -220,7 +244,7 @@ LiveRange::LiveRange(SILValue value)
220
244
// Ok, we know now that we have a consuming use. See if we have a destroy
221
245
// value, quickly up front. If we do have one, stash it and continue.
222
246
if (isa<DestroyValueInst>(user)) {
223
- destroyingUses .push_back (op);
247
+ tmpDestroyingUses .push_back (op);
224
248
continue ;
225
249
}
226
250
@@ -244,13 +268,13 @@ LiveRange::LiveRange(SILValue value)
244
268
return v.getOwnershipKind () ==
245
269
ValueOwnershipKind::Owned;
246
270
})) {
247
- unknownConsumingUses .push_back (op);
271
+ tmpUnknownConsumingUses .push_back (op);
248
272
continue ;
249
273
}
250
274
251
275
// Ok, this is a forwarding instruction whose ownership we can flip from
252
276
// owned -> guaranteed.
253
- ownershipForwardingUses .push_back (op);
277
+ tmpForwardingConsumingUses .push_back (op);
254
278
255
279
// If we have a non-terminator, just visit its users recursively to see if
256
280
// the the users force the live range to be alive.
@@ -284,6 +308,20 @@ LiveRange::LiveRange(SILValue value)
284
308
}
285
309
}
286
310
}
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 ());
287
325
}
288
326
289
327
void LiveRange::insertEndBorrowsAtDestroys (
@@ -339,9 +377,10 @@ void LiveRange::insertEndBorrowsAtDestroys(
339
377
}
340
378
}
341
379
342
- void LiveRange::convertOwnedGeneralForwardingUsesToGuaranteed () {
380
+ void LiveRange::convertOwnedGeneralForwardingUsesToGuaranteed () && {
343
381
while (!ownershipForwardingUses.empty ()) {
344
- auto *i = ownershipForwardingUses.pop_back_val ()->getUser ();
382
+ auto *i = ownershipForwardingUses.back ()->getUser ();
383
+ ownershipForwardingUses = ownershipForwardingUses.drop_back ();
345
384
346
385
// If this is a term inst, just convert all of its incoming values that are
347
386
// owned to be guaranteed.
@@ -402,7 +441,8 @@ void LiveRange::convertToGuaranteedAndRAUW(SILValue newGuaranteedValue,
402
441
InstModCallbacks callbacks) && {
403
442
auto *value = cast<SingleValueInstruction>(introducer.value );
404
443
while (!destroyingUses.empty ()) {
405
- auto *d = destroyingUses.pop_back_val ();
444
+ auto *d = destroyingUses.back ();
445
+ destroyingUses = destroyingUses.drop_back ();
406
446
callbacks.deleteInst (d->getUser ());
407
447
++NumEliminatedInsts;
408
448
}
@@ -412,7 +452,7 @@ void LiveRange::convertToGuaranteedAndRAUW(SILValue newGuaranteedValue,
412
452
// Then change all of our guaranteed forwarding insts to have guaranteed
413
453
// ownership kind instead of what ever they previously had (ignoring trivial
414
454
// results);
415
- convertOwnedGeneralForwardingUsesToGuaranteed ();
455
+ std::move (* this ). convertOwnedGeneralForwardingUsesToGuaranteed ();
416
456
}
417
457
418
458
void LiveRange::convertArgToGuaranteed (DeadEndBlocks &deadEndBlocks,
@@ -429,15 +469,16 @@ void LiveRange::convertArgToGuaranteed(DeadEndBlocks &deadEndBlocks,
429
469
430
470
// Then eliminate all of the destroys...
431
471
while (!destroyingUses.empty ()) {
432
- auto *d = destroyingUses.pop_back_val ();
472
+ auto *d = destroyingUses.back ();
473
+ destroyingUses = destroyingUses.drop_back ();
433
474
callbacks.deleteInst (d->getUser ());
434
475
++NumEliminatedInsts;
435
476
}
436
477
437
478
// and change all of our guaranteed forwarding insts to have guaranteed
438
479
// ownership kind instead of what ever they previously had (ignoring trivial
439
480
// results);
440
- convertOwnedGeneralForwardingUsesToGuaranteed ();
481
+ std::move (* this ). convertOwnedGeneralForwardingUsesToGuaranteed ();
441
482
}
442
483
443
484
LiveRange::HasConsumingUse_t
@@ -1297,8 +1338,9 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst
1297
1338
SmallVector<Operand *, 8 > scratchSpace;
1298
1339
SmallPtrSet<SILBasicBlock *, 4 > visitedBlocks;
1299
1340
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 ());
1302
1344
})) {
1303
1345
return false ;
1304
1346
}
@@ -1330,12 +1372,11 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst
1330
1372
return false ;
1331
1373
}
1332
1374
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
+ })) {
1339
1380
return false ;
1340
1381
}
1341
1382
}
@@ -1641,7 +1682,7 @@ class StorageGuaranteesLoadVisitor
1641
1682
SmallPtrSet<SILBasicBlock *, 4 > visitedBlocks;
1642
1683
LinearLifetimeChecker checker (visitedBlocks, ARCOpt.getDeadEndBlocks ());
1643
1684
if (!checker.validateLifetime (access , endScopeUses,
1644
- liveRange.getDestroyingUses ())) {
1685
+ liveRange.getAllConsumingUses ())) {
1645
1686
// If we fail the linear lifetime check, then just recur:
1646
1687
return next (access ->getOperand ());
1647
1688
}
@@ -1738,8 +1779,8 @@ class StorageGuaranteesLoadVisitor
1738
1779
LinearLifetimeChecker checker (visitedBlocks, ARCOpt.getDeadEndBlocks ());
1739
1780
1740
1781
// 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 ());
1743
1784
return answer (foundError);
1744
1785
}
1745
1786
@@ -1777,7 +1818,7 @@ class StorageGuaranteesLoadVisitor
1777
1818
// Returns true on success. So we invert.
1778
1819
bool foundError = !checker.validateLifetime (
1779
1820
stack, destroyAddrOperands /* consuming users*/ ,
1780
- liveRange.getDestroyingUses () /* non consuming users*/ );
1821
+ liveRange.getAllConsumingUses () /* non consuming users*/ );
1781
1822
return answer (foundError);
1782
1823
}
1783
1824
0 commit comments