@@ -162,8 +162,10 @@ bool CanonicalizeOSSALifetime::computeCanonicalLiveness() {
162
162
liveness.updateForUse (user, /* lifetimeEnding*/ true );
163
163
break ;
164
164
case OperandOwnership::DestroyingConsume:
165
- // destroy_value does not force pruned liveness (but store etc. does).
166
- if (!isa<DestroyValueInst>(user)) {
165
+ if (auto *dvi = dyn_cast<DestroyValueInst>(user)) {
166
+ destroys.insert (dvi);
167
+ } else {
168
+ // destroy_value does not force pruned liveness (but store etc. does).
167
169
liveness.updateForUse (user, /* lifetimeEnding*/ true );
168
170
}
169
171
recordConsumingUse (use);
@@ -335,18 +337,33 @@ void CanonicalizeOSSALifetime::extendLivenessThroughOverlappingAccess() {
335
337
bool changed = true ;
336
338
while (changed) {
337
339
changed = false ;
338
- blockWorklist.initializeRange (consumingBlocks);
339
- while (auto *bb = blockWorklist.pop ()) {
340
+ // The blocks in which we may have to extend liveness over access scopes.
341
+ //
342
+ // It must be populated first so that we can test membership during the loop
343
+ // (see findLastConsume).
344
+ BasicBlockSetVector blocksToVisit (currentDef->getFunction ());
345
+ for (auto *block : consumingBlocks) {
346
+ blocksToVisit.insert (block);
347
+ }
348
+ for (auto iterator = blocksToVisit.begin (); iterator != blocksToVisit.end ();
349
+ ++iterator) {
350
+ auto *bb = *iterator;
351
+ // If the block isn't dead, then we won't need to extend liveness within
352
+ // any of its predecessors (though we may within it).
353
+ if (liveness.getBlockLiveness (bb) != PrunedLiveBlocks::Dead)
354
+ continue ;
355
+ // Continue searching upward to find the pruned liveness boundary.
356
+ for (auto *predBB : bb->getPredecessorBlocks ()) {
357
+ blocksToVisit.insert (predBB);
358
+ }
359
+ }
360
+ for (auto *bb : blocksToVisit) {
340
361
auto blockLiveness = liveness.getBlockLiveness (bb);
341
362
// Ignore blocks within pruned liveness.
342
363
if (blockLiveness == PrunedLiveBlocks::LiveOut) {
343
364
continue ;
344
365
}
345
366
if (blockLiveness == PrunedLiveBlocks::Dead) {
346
- // Continue searching upward to find the pruned liveness boundary.
347
- for (auto *predBB : bb->getPredecessorBlocks ()) {
348
- blockWorklist.insert (predBB);
349
- }
350
367
// Otherwise, ignore dead blocks with no nonlocal end_access.
351
368
if (!accessBlocks->containsNonLocalEndAccess (bb)) {
352
369
continue ;
@@ -356,7 +373,43 @@ void CanonicalizeOSSALifetime::extendLivenessThroughOverlappingAccess() {
356
373
// Find the latest partially overlapping access scope, if one exists:
357
374
// use %def // pruned liveness ends here
358
375
// end_access
376
+
377
+ // Whether to look for the last consume in the block.
378
+ //
379
+ // If the block is consuming, we need to determine whether any subsequent
380
+ // block contains a destroy_value. If any does, then we need to count
381
+ // every end_access in this block as a use. If none do, then we only
382
+ // need to count end_accesses which occur before the consuming use in
383
+ // this block as uses.
384
+ bool findLastConsume =
385
+ consumingBlocks.contains (bb) &&
386
+ llvm::none_of (bb->getSuccessorBlocks (), [&](auto *successor) {
387
+ // If a block was originally live, then it either contained or was
388
+ // backwards reachable from a destroy or a use. If it was dead,
389
+ // then it was only backward reachable from a destroy.
390
+ //
391
+ // If we've seen a destroy, then we've seen the last consuming use.
392
+ return originalLiveBlocks.contains (successor) &&
393
+ liveness.getBlockLiveness (successor) ==
394
+ PrunedLiveBlocks::Dead;
395
+ });
359
396
for (auto &inst : llvm::reverse (*bb)) {
397
+ if (findLastConsume) {
398
+ // The value is consumed in the block, and we haven't already seen the
399
+ // consuming use.
400
+ //
401
+ // If this instruction is the consuming use, note that we've seen it.
402
+ //
403
+ // We only need to check for destroys because we exit the loop if the
404
+ // use is interesting.
405
+ if (auto *dvi = dyn_cast<DestroyValueInst>(&inst))
406
+ findLastConsume = !destroys.contains (dvi);
407
+ // Either this instruction is the consuming use or we haven't seen the
408
+ // consuming use yet. If it's the consuming use, it's not an
409
+ // overlapping end_access. If we haven't seen it yet, if it's an
410
+ // end_access, it doesn't overlap.
411
+ continue ;
412
+ }
360
413
// Stop at the latest use. An earlier end_access does not overlap.
361
414
if (blockHasUse && liveness.isInterestingUser (&inst)) {
362
415
break ;
0 commit comments