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
@@ -728,9 +729,23 @@ bool DCE::removeDead() {
728729 endLifetimeOfLiveValue (predOp, insertPt);
729730 }
730731 }
731- erasePhiArgument (&BB, i, /* cleanupDeadPhiOps=*/ true ,
732- InstModCallbacks ().onCreateNewInst (
733- [&](auto *inst) { markInstructionLive (inst); }));
732+ erasePhiArgument (
733+ &BB, i, /* cleanupDeadPhiOps=*/ true ,
734+ InstModCallbacks ()
735+ .onCreateNewInst ([&](auto *inst) { markInstructionLive (inst); })
736+ .onDelete ([&](auto *inst) {
737+ for (auto result : inst->getResults ()) {
738+ result = lookThroughBorrowedFromDef (result);
739+ if (valuesToComplete.count (result)) {
740+ valuesToComplete.erase (result);
741+ }
742+ }
743+ inst->replaceAllUsesOfAllResultsWithUndef ();
744+ if (isa<ApplyInst>(inst))
745+ CallsChanged = true ;
746+ ++NumDeletedInsts;
747+ inst->eraseFromParent ();
748+ }));
734749 Changed = true ;
735750 BranchesChanged = true ;
736751 }
@@ -744,7 +759,8 @@ bool DCE::removeDead() {
744759 // We want to replace dead terminators with unconditional branches to
745760 // the nearest post-dominator that has useful instructions.
746761 if (auto *termInst = dyn_cast<TermInst>(Inst)) {
747- SILBasicBlock *postDom = nearestUsefulPostDominator (Inst->getParent ());
762+ SILBasicBlock *postDom =
763+ nearestUsefulPostDominator (termInst->getParent ());
748764 if (!postDom)
749765 continue ;
750766
@@ -754,12 +770,13 @@ bool DCE::removeDead() {
754770 }
755771 }
756772 LLVM_DEBUG (llvm::dbgs () << " Replacing branch: " );
757- LLVM_DEBUG (Inst ->dump ());
773+ LLVM_DEBUG (termInst ->dump ());
758774 LLVM_DEBUG (llvm::dbgs ()
759775 << " with jump to: BB" << postDom->getDebugID () << " \n " );
760776
761- replaceBranchWithJump (Inst, postDom);
762- Inst->eraseFromParent ();
777+ replaceBranchWithJump (termInst, postDom);
778+ ++NumDeletedInsts;
779+ termInst->eraseFromParent ();
763780 BranchesChanged = true ;
764781 Changed = true ;
765782 continue ;
@@ -777,6 +794,12 @@ bool DCE::removeDead() {
777794 }
778795 }
779796 }
797+ for (auto result : Inst->getResults ()) {
798+ result = lookThroughBorrowedFromDef (result);
799+ if (valuesToComplete.count (result)) {
800+ valuesToComplete.erase (result);
801+ }
802+ }
780803 Inst->replaceAllUsesOfAllResultsWithUndef ();
781804
782805 if (isa<ApplyInst>(Inst))
@@ -789,7 +812,9 @@ bool DCE::removeDead() {
789812
790813 OSSALifetimeCompletion completion (F, DT, *deadEndBlocks);
791814 for (auto value : valuesToComplete) {
792- completion.completeOSSALifetime (value,
815+ if (!value.has_value ())
816+ continue ;
817+ completion.completeOSSALifetime (*value,
793818 OSSALifetimeCompletion::Boundary::Liveness);
794819 }
795820
@@ -846,9 +871,9 @@ void DCE::computeLevelNumbers(PostDomTreeNode *root) {
846871 auto entry = workList.pop_back_val ();
847872 PostDomTreeNode *node = entry.first ;
848873 unsigned level = entry.second ;
849-
874+
850875 insertControllingInfo (node->getBlock (), level);
851-
876+
852877 for (PostDomTreeNode *child : *node) {
853878 workList.push_back ({child, level + 1 });
854879 }
0 commit comments