@@ -511,7 +511,7 @@ void CanonicalizeOSSALifetime::extendUnconsumedLiveness(
511511 // destroys.
512512 BasicBlockWorklist worklist (currentDef->getFunction ());
513513 for (auto *instruction : boundary.lastUsers ) {
514- if (dynCastToDestroyOf (instruction, getCurrentDef () ))
514+ if (destroys. contains (instruction))
515515 continue ;
516516 if (liveness->isInterestingUser (instruction)
517517 != PrunedLiveness::IsInterestingUser::LifetimeEndingUse)
@@ -576,17 +576,20 @@ namespace {
576576// / values with overlapping live ranges and failing to find a fixed point
577577// / because their destroys are repeatedly hoisted over one another.
578578class ExtendBoundaryToDestroys final {
579+ using InstructionPredicate = llvm::function_ref<bool (SILInstruction *)>;
579580 SSAPrunedLiveness &liveness;
580581 PrunedLivenessBoundary const &originalBoundary;
581582 SILValue currentDef;
582583 BasicBlockSet seenMergePoints;
584+ InstructionPredicate isDestroy;
583585
584586public:
585587 ExtendBoundaryToDestroys (SSAPrunedLiveness &liveness,
586588 PrunedLivenessBoundary const &originalBoundary,
587- SILValue currentDef)
589+ SILValue currentDef, InstructionPredicate isDestroy )
588590 : liveness(liveness), originalBoundary(originalBoundary),
589- currentDef (currentDef), seenMergePoints(currentDef->getFunction ()){};
591+ currentDef (currentDef), seenMergePoints(currentDef->getFunction ()),
592+ isDestroy(isDestroy){};
590593 ExtendBoundaryToDestroys (ExtendBoundaryToDestroys const &) = delete;
591594 ExtendBoundaryToDestroys &
592595 operator =(ExtendBoundaryToDestroys const &) = delete;
@@ -610,34 +613,37 @@ class ExtendBoundaryToDestroys final {
610613 // / Look past ignoreable instructions to find the _last_ destroy after the
611614 // / specified instruction that destroys \p def.
612615 static DestroyValueInst *findDestroyAfter (SILInstruction *previous,
613- SILValue def) {
616+ SILValue def,
617+ InstructionPredicate isDestroy) {
614618 DestroyValueInst *retval = nullptr ;
615619 for (auto *instruction = previous->getNextInstruction (); instruction;
616620 instruction = instruction->getNextInstruction ()) {
617621 if (!CanonicalizeOSSALifetime::ignoredByDestroyHoisting (
618622 instruction->getKind ()))
619623 break ;
620- if (auto destroy = dynCastToDestroyOf (instruction, def ))
621- retval = destroy ;
624+ if (isDestroy (instruction))
625+ retval = cast<DestroyValueInst>(instruction) ;
622626 }
623627 return retval;
624628 }
625629
626630 // / Look past ignoreable instructions to find the _last_ destroy at or after
627631 // / the specified instruction that destroys \p def.
628- static DestroyValueInst *findDestroyAtOrAfter (SILInstruction *start,
629- SILValue def) {
630- if (auto *dvi = dynCastToDestroyOf (start, def))
631- return dvi;
632- return findDestroyAfter (start, def);
632+ static DestroyValueInst *
633+ findDestroyAtOrAfter (SILInstruction *start, SILValue def,
634+ InstructionPredicate isDestroy) {
635+ if (isDestroy (start))
636+ return cast<DestroyValueInst>(start);
637+ return findDestroyAfter (start, def, isDestroy);
633638 }
634639
635640 // / Look past ignoreable instructions to find the _first_ destroy in \p
636641 // / destination that destroys \p def and isn't separated from the beginning
637642 // / by "interesting" instructions.
638- static DestroyValueInst *findDestroyFromBlockBegin (SILBasicBlock *destination,
639- SILValue def) {
640- return findDestroyAtOrAfter (&*destination->begin (), def);
643+ static DestroyValueInst *
644+ findDestroyFromBlockBegin (SILBasicBlock *destination, SILValue def,
645+ InstructionPredicate isDestroy) {
646+ return findDestroyAtOrAfter (&*destination->begin (), def, isDestroy);
641647 }
642648
643649private:
@@ -651,12 +657,14 @@ class ExtendBoundaryToDestroys final {
651657 // / stays in place and \p def remains a dead def.
652658 void extendBoundaryFromDef (SILNode *def, PrunedLivenessBoundary &boundary) {
653659 if (auto *arg = dyn_cast<SILArgument>(def)) {
654- if (auto *dvi = findDestroyFromBlockBegin (arg->getParent (), currentDef)) {
660+ if (auto *dvi = findDestroyFromBlockBegin (arg->getParent (), currentDef,
661+ isDestroy)) {
655662 boundary.lastUsers .push_back (dvi);
656663 return ;
657664 }
658665 } else {
659- if (auto *dvi = findDestroyAfter (cast<SILInstruction>(def), currentDef)) {
666+ if (auto *dvi = findDestroyAfter (cast<SILInstruction>(def), currentDef,
667+ isDestroy)) {
660668 boundary.lastUsers .push_back (dvi);
661669 return ;
662670 }
@@ -673,7 +681,8 @@ class ExtendBoundaryToDestroys final {
673681 // / stays in place and \p destination remains a boundary edge.
674682 void extendBoundaryFromBoundaryEdge (SILBasicBlock *destination,
675683 PrunedLivenessBoundary &boundary) {
676- if (auto *dvi = findDestroyFromBlockBegin (destination, currentDef)) {
684+ if (auto *dvi =
685+ findDestroyFromBlockBegin (destination, currentDef, isDestroy)) {
677686 boundary.lastUsers .push_back (dvi);
678687 } else {
679688 boundary.boundaryEdges .push_back (destination);
@@ -694,8 +703,9 @@ class ExtendBoundaryToDestroys final {
694703 // / user remains a last user.
695704 void extendBoundaryFromUser (SILInstruction *user,
696705 PrunedLivenessBoundary &boundary) {
697- if (auto *dvi = dynCastToDestroyOf (user, currentDef)) {
698- auto *existingDestroy = findDestroyAtOrAfter (dvi, currentDef);
706+ if (isDestroy (user)) {
707+ auto *dvi = cast<DestroyValueInst>(user);
708+ auto *existingDestroy = findDestroyAtOrAfter (dvi, currentDef, isDestroy);
699709 assert (existingDestroy && " couldn't find a destroy at or after one!?" );
700710 boundary.lastUsers .push_back (existingDestroy);
701711 return ;
@@ -713,7 +723,8 @@ class ExtendBoundaryToDestroys final {
713723 extendBoundaryFromTerminator (terminator, boundary);
714724 return ;
715725 }
716- if (auto *existingDestroy = findDestroyAfter (user, currentDef)) {
726+ if (auto *existingDestroy =
727+ findDestroyAfter (user, currentDef, isDestroy)) {
717728 boundary.lastUsers .push_back (existingDestroy);
718729 return ;
719730 }
@@ -745,7 +756,8 @@ class ExtendBoundaryToDestroys final {
745756 assert (block->getSingleSuccessorBlock () == successor);
746757 continue ;
747758 }
748- if (auto *dvi = findDestroyFromBlockBegin (successor, currentDef)) {
759+ if (auto *dvi =
760+ findDestroyFromBlockBegin (successor, currentDef, isDestroy)) {
749761 boundary.lastUsers .push_back (dvi);
750762 foundDestroy = true ;
751763 } else {
@@ -770,8 +782,9 @@ void CanonicalizeOSSALifetime::findExtendedBoundary(
770782 PrunedLivenessBoundary &boundary) {
771783 assert (boundary.lastUsers .size () == 0 && boundary.boundaryEdges .size () == 0 &&
772784 boundary.deadDefs .size () == 0 );
785+ auto isDestroy = [&](auto *inst) { return destroys.contains (inst); };
773786 ExtendBoundaryToDestroys extender (*liveness, originalBoundary,
774- getCurrentDef ());
787+ getCurrentDef (), isDestroy );
775788 extender.extend (boundary);
776789}
777790
@@ -806,8 +819,8 @@ void CanonicalizeOSSALifetime::insertDestroysOnBoundary(
806819 PrunedLivenessBoundary const &boundary) {
807820 BasicBlockSet seenMergePoints (getCurrentDef ()->getFunction ());
808821 for (auto *instruction : boundary.lastUsers ) {
809- if (auto *dvi = dynCastToDestroyOf (instruction, getCurrentDef () )) {
810- consumes.recordFinalConsume (dvi );
822+ if (destroys. contains (instruction)) {
823+ consumes.recordFinalConsume (instruction );
811824 continue ;
812825 }
813826 switch (liveness->isInterestingUser (instruction)) {
@@ -905,7 +918,8 @@ void CanonicalizeOSSALifetime::rewriteCopies() {
905918 defUseWorklist.insert (copy);
906919 return true ;
907920 }
908- if (auto *destroy = dynCastToDestroyOf (user, getCurrentDef ())) {
921+ if (destroys.contains (user)) {
922+ auto *destroy = cast<DestroyValueInst>(user);
909923 // If this destroy was marked as a final destroy, ignore it; otherwise,
910924 // delete it.
911925 if (!consumes.claimConsume (destroy)) {
0 commit comments