@@ -290,7 +290,7 @@ struct BorroweeUsage final {
290290// / %lifetime. In detail, PrunedLiveness::isWithinBoundary relies on
291291// / clients to know that instructions are after the start of liveness. We
292292// / determine this via the dominance tree.
293- bool findBorroweeUsage (Context &, BorroweeUsage &);
293+ bool findBorroweeUsage (Context const &, BorroweeUsage &);
294294
295295// / Sift scope ends of %lifetime for those that CAN be folded.
296296class FilterCandidates final {
@@ -308,9 +308,6 @@ class FilterCandidates final {
308308
309309 // / Determines whether each candidate is viable for folding.
310310 // /
311- // / Requiring findUsers to have been called, this uses the more expensive
312- // / isViableMatch.
313- // /
314311 // / returns true if any candidates were viable
315312 // / false otherwise
316313 bool run (Candidates &candidates);
@@ -334,8 +331,7 @@ class FilterCandidates final {
334331// /
335332// / If there are, we can't fold the apply. Specifically, we can't introduce
336333// / a move_value [lexical] %borrowee because that value still needs to be used
337- // / in those locations. While updateSSA would happily rewrite those uses to
338- // / be uses of the move, that is not a semantically valid transformation.
334+ // / in those locations.
339335// /
340336// / For example, given the following SIL
341337// / %borrowee : @owned
@@ -410,11 +406,7 @@ class Rewriter final {
410406 // / possible)
411407 // / (2) hoist the end_borrow
412408 // / (3) delete the destroy_value
413- void fold (Match, SmallVectorImpl<int > const &rewritableArgumentIndices);
414-
415- // Update SSA to reflect that fact that %move and %borrowee are two
416- // defs for the "same value".
417- void updateSSA ();
409+ void fold (Match, ArrayRef<int > rewritableArgumentIndices);
418410
419411 // The move_value [lexical] instruction that was added during the run.
420412 //
@@ -470,25 +462,31 @@ bool run(Context &context) {
470462void Rewriter::run () {
471463 bool foldedAny = false ;
472464 (void )foldedAny;
473- for ( unsigned index = 0 , count = candidates.vector .size (); index < count ;
474- ++index) {
465+ auto size = candidates.vector .size ();
466+ for ( unsigned index = 0 ; index < size; ++index) {
475467 auto candidate = candidates.vector [index];
476- if (!candidate.viable )
477- continue ;
478468 createMove ();
469+ if (!candidate.viable ) {
470+ // Nonviable candidates still end with the pattern
471+ //
472+ // end_borrow %lifetime
473+ // ...
474+ // destroy_value %borrowee
475+ //
476+ // Now that the new move_value [lexical] dominates all candidates, the
477+ // every candidate's destroy_value %borrowee is dominated by it, so every
478+ // one is dominated by another consuming use which is illegal. Rewrite
479+ // each such destroy_value to be a destroy_value of the move.
480+ candidate.match .dvi ->setOperand (mvi);
481+ continue ;
482+ }
479483
480484 fold (candidate.match , candidate.argumentIndices );
481485#ifndef NDEBUG
482486 foldedAny = true ;
483487#endif
484488 }
485489 assert (foldedAny && " rewriting without anything to rewrite!?" );
486-
487- // There are now "two defs for %borrowee":
488- // - %borrowee
489- // - %move
490- // We need to update SSA.
491- updateSSA ();
492490}
493491
494492bool Rewriter::createMove () {
@@ -505,8 +503,7 @@ bool Rewriter::createMove() {
505503 return true ;
506504}
507505
508- void Rewriter::fold (Match candidate,
509- SmallVectorImpl<int > const &rewritableArgumentIndices) {
506+ void Rewriter::fold (Match candidate, ArrayRef<int > rewritableArgumentIndices) {
510507 // First, rewrite the apply in terms of the move_value.
511508 unsigned argumentNumber = 0 ;
512509 for (auto index : rewritableArgumentIndices) {
@@ -551,26 +548,6 @@ void Rewriter::fold(Match candidate,
551548 context.deleter .forceDelete (candidate.dvi );
552549}
553550
554- void Rewriter::updateSSA () {
555- SILSSAUpdater updater;
556- updater.initialize (context.borrowee ->getType (),
557- context.borrowee .getOwnershipKind ());
558- updater.addAvailableValue (context.borrowee ->getParentBlock (),
559- context.borrowee );
560- updater.addAvailableValue (mvi->getParentBlock (), mvi);
561-
562- SmallVector<Operand *, 16 > uses;
563- for (auto use : context.borrowee ->getUses ()) {
564- if (use->getUser () == mvi)
565- continue ;
566- uses.push_back (use);
567- }
568-
569- for (auto use : uses) {
570- updater.rewriteUse (*use);
571- }
572- }
573-
574551// ===----------------------------------------------------------------------===//
575552// MARK: Lookups
576553// ===----------------------------------------------------------------------===//
@@ -638,8 +615,10 @@ bool FilterCandidates::run(Candidates &candidates) {
638615 return anyViable;
639616}
640617
641- bool findBorroweeUsage (Context &context, BorroweeUsage &usage) {
618+ bool findBorroweeUsage (Context const &context, BorroweeUsage &usage) {
642619 auto recordUse = [&](Operand *use) {
620+ // Ignore uses that aren't dominated by the introducer. PrunedLiveness
621+ // relies on us doing this check.
643622 if (!context.dominanceTree .dominates (context.introducer , use->getUser ()))
644623 return ;
645624 usage.uses .push_back (use);
0 commit comments