1212
1313#define DEBUG_TYPE " sil-dce"
1414#include " swift/Basic/Assertions.h"
15+ #include " swift/Basic/BlotSetVector.h"
1516#include " swift/SIL/BasicBlockBits.h"
1617#include " swift/SIL/DebugUtils.h"
1718#include " swift/SIL/MemAccessUtils.h"
1819#include " swift/SIL/NodeBits.h"
20+ #include " swift/SIL/OSSALifetimeCompletion.h"
1921#include " swift/SIL/OwnershipUtils.h"
2022#include " swift/SIL/SILArgument.h"
2123#include " swift/SIL/SILBasicBlock.h"
2224#include " swift/SIL/SILBuilder.h"
2325#include " swift/SIL/SILFunction.h"
2426#include " swift/SIL/SILUndef.h"
25- #include " swift/SIL/OSSALifetimeCompletion.h"
26- #include " swift/SILOptimizer/Analysis/DominanceAnalysis.h"
2727#include " swift/SILOptimizer/Analysis/DeadEndBlocksAnalysis.h"
28+ #include " swift/SILOptimizer/Analysis/DominanceAnalysis.h"
2829#include " swift/SILOptimizer/PassManager/Passes.h"
2930#include " swift/SILOptimizer/PassManager/Transforms.h"
3031#include " swift/SILOptimizer/Utils/BasicBlockOptUtils.h"
@@ -94,7 +95,7 @@ static bool seemsUseful(SILInstruction *I) {
9495 if (isa<DebugValueInst>(I))
9596 return isa<SILFunctionArgument>(I->getOperand (0 ))
9697 || isa<SILUndef>(I->getOperand (0 ));
97-
98+
9899
99100 // Don't delete allocation instructions in DCE.
100101 if (isa<AllocRefInst>(I) || isa<AllocRefDynamicInst>(I)) {
@@ -131,7 +132,7 @@ class DCE {
131132 DominanceInfo *DT;
132133 DeadEndBlocks *deadEndBlocks;
133134 llvm::DenseMap<SILBasicBlock *, ControllingInfo> ControllingInfoMap;
134- llvm::SmallVector <SILValue> valuesToComplete;
135+ SmallBlotSetVector <SILValue, 8 > valuesToComplete;
135136
136137 // Maps instructions which produce a failing condition (like overflow
137138 // builtins) to the actual cond_fail instructions which handle the failure.
@@ -212,7 +213,7 @@ class DCE {
212213 markLive ();
213214 return removeDead ();
214215 }
215-
216+
216217 bool mustInvalidateCalls () const { return CallsChanged; }
217218 bool mustInvalidateBranches () const { return BranchesChanged; }
218219};
@@ -637,7 +638,7 @@ void DCE::endLifetimeOfLiveValue(Operand *op, SILInstruction *insertPt) {
637638 // If DCE is going to delete the block in which we have to insert a
638639 // compensating lifetime end, let complete lifetimes utility handle it.
639640 if (!LiveBlocks.contains (insertPt->getParent ())) {
640- valuesToComplete.push_back (lookThroughBorrowedFromDef (value));
641+ valuesToComplete.insert (lookThroughBorrowedFromDef (value));
641642 return ;
642643 }
643644
@@ -731,9 +732,23 @@ bool DCE::removeDead() {
731732 endLifetimeOfLiveValue (predOp, insertPt);
732733 }
733734 }
734- erasePhiArgument (&BB, i, /* cleanupDeadPhiOps=*/ true ,
735- InstModCallbacks ().onCreateNewInst (
736- [&](auto *inst) { markInstructionLive (inst); }));
735+ erasePhiArgument (
736+ &BB, i, /* cleanupDeadPhiOps=*/ true ,
737+ InstModCallbacks ()
738+ .onCreateNewInst ([&](auto *inst) { markInstructionLive (inst); })
739+ .onDelete ([&](auto *inst) {
740+ for (auto result : inst->getResults ()) {
741+ result = lookThroughBorrowedFromDef (result);
742+ if (valuesToComplete.count (result)) {
743+ valuesToComplete.erase (result);
744+ }
745+ }
746+ inst->replaceAllUsesOfAllResultsWithUndef ();
747+ if (isa<ApplyInst>(inst))
748+ CallsChanged = true ;
749+ ++NumDeletedInsts;
750+ inst->eraseFromParent ();
751+ }));
737752 Changed = true ;
738753 BranchesChanged = true ;
739754 }
@@ -747,7 +762,8 @@ bool DCE::removeDead() {
747762 // We want to replace dead terminators with unconditional branches to
748763 // the nearest post-dominator that has useful instructions.
749764 if (auto *termInst = dyn_cast<TermInst>(Inst)) {
750- SILBasicBlock *postDom = nearestUsefulPostDominator (Inst->getParent ());
765+ SILBasicBlock *postDom =
766+ nearestUsefulPostDominator (termInst->getParent ());
751767 if (!postDom)
752768 continue ;
753769
@@ -757,12 +773,13 @@ bool DCE::removeDead() {
757773 }
758774 }
759775 LLVM_DEBUG (llvm::dbgs () << " Replacing branch: " );
760- LLVM_DEBUG (Inst ->dump ());
776+ LLVM_DEBUG (termInst ->dump ());
761777 LLVM_DEBUG (llvm::dbgs ()
762778 << " with jump to: BB" << postDom->getDebugID () << " \n " );
763779
764- replaceBranchWithJump (Inst, postDom);
765- Inst->eraseFromParent ();
780+ replaceBranchWithJump (termInst, postDom);
781+ ++NumDeletedInsts;
782+ termInst->eraseFromParent ();
766783 BranchesChanged = true ;
767784 Changed = true ;
768785 continue ;
@@ -780,6 +797,12 @@ bool DCE::removeDead() {
780797 }
781798 }
782799 }
800+ for (auto result : Inst->getResults ()) {
801+ result = lookThroughBorrowedFromDef (result);
802+ if (valuesToComplete.count (result)) {
803+ valuesToComplete.erase (result);
804+ }
805+ }
783806 Inst->replaceAllUsesOfAllResultsWithUndef ();
784807
785808 if (isa<ApplyInst>(Inst))
@@ -792,7 +815,9 @@ bool DCE::removeDead() {
792815
793816 OSSALifetimeCompletion completion (F, DT, *deadEndBlocks);
794817 for (auto value : valuesToComplete) {
795- completion.completeOSSALifetime (value,
818+ if (!value.has_value ())
819+ continue ;
820+ completion.completeOSSALifetime (*value,
796821 OSSALifetimeCompletion::Boundary::Liveness);
797822 }
798823
@@ -849,9 +874,9 @@ void DCE::computeLevelNumbers(PostDomTreeNode *root) {
849874 auto entry = workList.pop_back_val ();
850875 PostDomTreeNode *node = entry.first ;
851876 unsigned level = entry.second ;
852-
877+
853878 insertControllingInfo (node->getBlock (), level);
854-
879+
855880 for (PostDomTreeNode *child : *node) {
856881 workList.push_back ({child, level + 1 });
857882 }
0 commit comments