@@ -406,24 +406,38 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst
406
406
// dead end blocks that use the value in a non-consuming way.
407
407
//
408
408
// TODO: There may be some way of sinking this into the loop below.
409
- if (destroys.empty () &&
410
- llvm::any_of (borrowScopeIntroducers,
411
- [](BorrowScopeIntroducingValue borrowScope) {
412
- return borrowScope.isLocalScope ();
413
- })) {
409
+ bool haveAnyLocalScopes = llvm::any_of (
410
+ borrowScopeIntroducers, [](BorrowScopeIntroducingValue borrowScope) {
411
+ return borrowScope.isLocalScope ();
412
+ });
413
+
414
+ if (destroys.empty () && haveAnyLocalScopes) {
414
415
return false ;
415
416
}
416
417
417
418
// If we reached this point, then we know that all of our users can accept a
418
- // guaranteed value and our owned value is destroyed only by
419
- // destroy_value. Check if all of our destroys are joint post-dominated by the
420
- // our end borrow scope set. If they do not, then the copy_value is lifetime
421
- // extending the guaranteed value, we can not eliminate it.
419
+ // guaranteed value and our owned value is destroyed only by a set of
420
+ // destroy_values. Check if:
421
+ //
422
+ // 1. All of our destroys are joint post-dominated by our end borrow scope
423
+ // set. If they do not, then the copy_value is lifetime extending the
424
+ // guaranteed value, we can not eliminate it.
425
+ //
426
+ // 2. If all of our destroy_values are dead end. In such a case, the linear
427
+ // lifetime checker will not perform any checks since it assumes that dead
428
+ // end destroys can be ignored. Since we are going to end the program
429
+ // anyways, we want to be conservative here and optimize only if we do not
430
+ // need to insert an end_borrow since all of our borrow introducers are
431
+ // non-local scopes.
422
432
{
423
433
SmallVector<BranchPropagatedUser, 8 > destroysForLinearLifetimeCheck;
434
+ bool foundNonDeadEnd = false ;
424
435
for (auto *dvi : destroys) {
436
+ foundNonDeadEnd |= !getDeadEndBlocks ().isDeadEnd (dvi->getParent ());
425
437
destroysForLinearLifetimeCheck.push_back (&dvi->getAllOperands ()[0 ]);
426
438
}
439
+ if (!foundNonDeadEnd && haveAnyLocalScopes)
440
+ return false ;
427
441
SmallVector<BranchPropagatedUser, 8 > scratchSpace;
428
442
SmallPtrSet<SILBasicBlock *, 4 > visitedBlocks;
429
443
if (llvm::any_of (borrowScopeIntroducers,
0 commit comments