@@ -89,20 +89,23 @@ struct CanonicalDefWorklist {
89
89
90
90
while (true ) {
91
91
def = CanonicalizeOSSALifetime::getCanonicalCopiedDef (def);
92
- if (!canonicalizeBorrows) {
93
- ownedValues.insert (def);
94
- return ;
95
- }
92
+
96
93
// If the copy's source is guaranteed, find the root of a borrowed
97
94
// extended lifetime.
98
95
if (auto *copy = dyn_cast<CopyValueInst>(def)) {
99
96
if (SILValue borrowDef =
100
97
CanonicalizeBorrowScope::getCanonicalBorrowedDef (
101
98
copy->getOperand ())) {
102
- borrowedValues.insert (borrowDef);
103
- return ;
99
+ if (canonicalizeBorrows || isa<SILFunctionArgument>(borrowDef)) {
100
+ borrowedValues.insert (borrowDef);
101
+ return ;
102
+ }
104
103
}
105
104
}
105
+ if (!canonicalizeBorrows) {
106
+ ownedValues.insert (def);
107
+ return ;
108
+ }
106
109
// Look through hoistable owned forwarding instructions on the
107
110
// use-def chain.
108
111
if (SILInstruction *defInst = def->getDefiningInstruction ()) {
@@ -491,60 +494,63 @@ void CopyPropagation::run() {
491
494
// of the copiedDefs. If the are converted, they are removed from copiedDefs
492
495
// and the source of the new destructure is added.
493
496
changed |= convertExtractsToDestructures (defWorklist, deleter);
494
-
495
- // borrowCanonicalizer performs all modifications through deleter's
496
- // callbacks, so we don't need to explicitly check for changes.
497
- CanonicalizeBorrowScope borrowCanonicalizer (deleter);
498
- // The utilities in this loop cannot delete borrows before they are popped
499
- // from the worklist.
500
- while (true ) {
501
- while (!defWorklist.ownedForwards .empty ()) {
502
- SILInstruction *ownedForward = defWorklist.ownedForwards .pop_back_val ();
503
- // Delete a dead forwarded value before sinking to avoid this pattern:
504
- // %outerVal = destructure_struct %def
505
- // destroy %outerVal <= delete this destroy now
506
- // destroy %def <= so we don't delete this one later
507
- if (deleter.deleteIfDead (ownedForward)) {
508
- LLVM_DEBUG (llvm::dbgs () << " Deleted " << *ownedForward);
509
- continue ;
510
- }
511
- // Canonicalize a forwarded owned value before sinking the forwarding
512
- // instruction, and sink the instruction before canonicalizing the owned
513
- // value being forwarded. Process 'ownedForwards' in reverse since
514
- // they may be chained, and CanonicalizeBorrowScopes pushes them
515
- // top-down.
516
- for (auto result : ownedForward->getResults ()) {
517
- canonicalizer.canonicalizeValueLifetime (result);
518
- }
519
- if (sinkOwnedForward (ownedForward, postOrderAnalysis, domTree)) {
520
- changed = true ;
521
- // Sinking 'ownedForward' may create an opportunity to sink its
522
- // operand. This handles chained forwarding instructions that were
523
- // pushed onto the list out-of-order.
524
- if (SILInstruction *forwardDef =
525
- CanonicalizeOSSALifetime::getCanonicalCopiedDef (
526
- ownedForward->getOperand (0 ))
527
- ->getDefiningInstruction ()) {
528
- if (CanonicalizeBorrowScope::isRewritableOSSAForward (forwardDef)) {
529
- defWorklist.ownedForwards .insert (forwardDef);
530
- }
497
+ }
498
+ // borrowCanonicalizer performs all modifications through deleter's
499
+ // callbacks, so we don't need to explicitly check for changes.
500
+ CanonicalizeBorrowScope borrowCanonicalizer (deleter);
501
+ // The utilities in this loop cannot delete borrows before they are popped
502
+ // from the worklist.
503
+ while (true ) {
504
+ while (!defWorklist.ownedForwards .empty ()) {
505
+ assert (canonicalizeBorrows);
506
+
507
+ SILInstruction *ownedForward = defWorklist.ownedForwards .pop_back_val ();
508
+ // Delete a dead forwarded value before sinking to avoid this pattern:
509
+ // %outerVal = destructure_struct %def
510
+ // destroy %outerVal <= delete this destroy now
511
+ // destroy %def <= so we don't delete this one later
512
+ if (deleter.deleteIfDead (ownedForward)) {
513
+ LLVM_DEBUG (llvm::dbgs () << " Deleted " << *ownedForward);
514
+ continue ;
515
+ }
516
+ // Canonicalize a forwarded owned value before sinking the forwarding
517
+ // instruction, and sink the instruction before canonicalizing the owned
518
+ // value being forwarded. Process 'ownedForwards' in reverse since
519
+ // they may be chained, and CanonicalizeBorrowScopes pushes them
520
+ // top-down.
521
+ for (auto result : ownedForward->getResults ()) {
522
+ canonicalizer.canonicalizeValueLifetime (result);
523
+ }
524
+ if (sinkOwnedForward (ownedForward, postOrderAnalysis, domTree)) {
525
+ changed = true ;
526
+ // Sinking 'ownedForward' may create an opportunity to sink its
527
+ // operand. This handles chained forwarding instructions that were
528
+ // pushed onto the list out-of-order.
529
+ if (SILInstruction *forwardDef =
530
+ CanonicalizeOSSALifetime::getCanonicalCopiedDef (
531
+ ownedForward->getOperand (0 ))
532
+ ->getDefiningInstruction ()) {
533
+ if (CanonicalizeBorrowScope::isRewritableOSSAForward (forwardDef)) {
534
+ defWorklist.ownedForwards .insert (forwardDef);
531
535
}
532
536
}
533
537
}
534
- if (defWorklist.borrowedValues .empty ())
535
- break ;
538
+ }
539
+ if (defWorklist.borrowedValues .empty ())
540
+ break ;
536
541
537
- BorrowedValue borrow (defWorklist.borrowedValues .pop_back_val ());
538
- borrowCanonicalizer.canonicalizeBorrowScope (borrow);
539
- for (CopyValueInst *copy : borrowCanonicalizer.getUpdatedCopies ()) {
540
- defWorklist.updateForCopy (copy);
541
- }
542
- // Dead borrow scopes must be removed as uses before canonicalizing the
543
- // outer copy.
544
- if (auto *beginBorrow = dyn_cast<BeginBorrowInst>(borrow.value )) {
545
- if (hasOnlyEndOfScopeOrEndOfLifetimeUses (beginBorrow)) {
546
- deleter.recursivelyDeleteUsersIfDead (beginBorrow);
547
- }
542
+ BorrowedValue borrow (defWorklist.borrowedValues .pop_back_val ());
543
+ assert (canonicalizeBorrows || !borrow.isLocalScope ());
544
+
545
+ borrowCanonicalizer.canonicalizeBorrowScope (borrow);
546
+ for (CopyValueInst *copy : borrowCanonicalizer.getUpdatedCopies ()) {
547
+ defWorklist.updateForCopy (copy);
548
+ }
549
+ // Dead borrow scopes must be removed as uses before canonicalizing the
550
+ // outer copy.
551
+ if (auto *beginBorrow = dyn_cast<BeginBorrowInst>(borrow.value )) {
552
+ if (hasOnlyEndOfScopeOrEndOfLifetimeUses (beginBorrow)) {
553
+ deleter.recursivelyDeleteUsersIfDead (beginBorrow);
548
554
}
549
555
}
550
556
deleter.cleanupDeadInstructions ();
0 commit comments