12
12
13
13
#define DEBUG_TYPE " sil-dce"
14
14
#include " swift/Basic/Assertions.h"
15
+ #include " swift/Basic/BlotSetVector.h"
15
16
#include " swift/SIL/BasicBlockBits.h"
16
17
#include " swift/SIL/DebugUtils.h"
17
18
#include " swift/SIL/MemAccessUtils.h"
18
19
#include " swift/SIL/NodeBits.h"
20
+ #include " swift/SIL/OSSALifetimeCompletion.h"
19
21
#include " swift/SIL/OwnershipUtils.h"
20
22
#include " swift/SIL/SILArgument.h"
21
23
#include " swift/SIL/SILBasicBlock.h"
22
24
#include " swift/SIL/SILBuilder.h"
23
25
#include " swift/SIL/SILFunction.h"
24
26
#include " swift/SIL/SILUndef.h"
25
- #include " swift/SIL/OSSALifetimeCompletion.h"
26
- #include " swift/SILOptimizer/Analysis/DominanceAnalysis.h"
27
27
#include " swift/SILOptimizer/Analysis/DeadEndBlocksAnalysis.h"
28
+ #include " swift/SILOptimizer/Analysis/DominanceAnalysis.h"
28
29
#include " swift/SILOptimizer/PassManager/Passes.h"
29
30
#include " swift/SILOptimizer/PassManager/Transforms.h"
30
31
#include " swift/SILOptimizer/Utils/BasicBlockOptUtils.h"
@@ -94,7 +95,7 @@ static bool seemsUseful(SILInstruction *I) {
94
95
if (isa<DebugValueInst>(I))
95
96
return isa<SILFunctionArgument>(I->getOperand (0 ))
96
97
|| isa<SILUndef>(I->getOperand (0 ));
97
-
98
+
98
99
99
100
// Don't delete allocation instructions in DCE.
100
101
if (isa<AllocRefInst>(I) || isa<AllocRefDynamicInst>(I)) {
@@ -131,7 +132,7 @@ class DCE {
131
132
DominanceInfo *DT;
132
133
DeadEndBlocks *deadEndBlocks;
133
134
llvm::DenseMap<SILBasicBlock *, ControllingInfo> ControllingInfoMap;
134
- llvm::SmallVector <SILValue> valuesToComplete;
135
+ SmallBlotSetVector <SILValue, 8 > valuesToComplete;
135
136
136
137
// Maps instructions which produce a failing condition (like overflow
137
138
// builtins) to the actual cond_fail instructions which handle the failure.
@@ -212,7 +213,7 @@ class DCE {
212
213
markLive ();
213
214
return removeDead ();
214
215
}
215
-
216
+
216
217
bool mustInvalidateCalls () const { return CallsChanged; }
217
218
bool mustInvalidateBranches () const { return BranchesChanged; }
218
219
};
@@ -637,7 +638,7 @@ void DCE::endLifetimeOfLiveValue(Operand *op, SILInstruction *insertPt) {
637
638
// If DCE is going to delete the block in which we have to insert a
638
639
// compensating lifetime end, let complete lifetimes utility handle it.
639
640
if (!LiveBlocks.contains (insertPt->getParent ())) {
640
- valuesToComplete.push_back (lookThroughBorrowedFromDef (value));
641
+ valuesToComplete.insert (lookThroughBorrowedFromDef (value));
641
642
return ;
642
643
}
643
644
@@ -728,9 +729,23 @@ bool DCE::removeDead() {
728
729
endLifetimeOfLiveValue (predOp, insertPt);
729
730
}
730
731
}
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
+ }));
734
749
Changed = true ;
735
750
BranchesChanged = true ;
736
751
}
@@ -744,7 +759,8 @@ bool DCE::removeDead() {
744
759
// We want to replace dead terminators with unconditional branches to
745
760
// the nearest post-dominator that has useful instructions.
746
761
if (auto *termInst = dyn_cast<TermInst>(Inst)) {
747
- SILBasicBlock *postDom = nearestUsefulPostDominator (Inst->getParent ());
762
+ SILBasicBlock *postDom =
763
+ nearestUsefulPostDominator (termInst->getParent ());
748
764
if (!postDom)
749
765
continue ;
750
766
@@ -754,12 +770,13 @@ bool DCE::removeDead() {
754
770
}
755
771
}
756
772
LLVM_DEBUG (llvm::dbgs () << " Replacing branch: " );
757
- LLVM_DEBUG (Inst ->dump ());
773
+ LLVM_DEBUG (termInst ->dump ());
758
774
LLVM_DEBUG (llvm::dbgs ()
759
775
<< " with jump to: BB" << postDom->getDebugID () << " \n " );
760
776
761
- replaceBranchWithJump (Inst, postDom);
762
- Inst->eraseFromParent ();
777
+ replaceBranchWithJump (termInst, postDom);
778
+ ++NumDeletedInsts;
779
+ termInst->eraseFromParent ();
763
780
BranchesChanged = true ;
764
781
Changed = true ;
765
782
continue ;
@@ -777,6 +794,12 @@ bool DCE::removeDead() {
777
794
}
778
795
}
779
796
}
797
+ for (auto result : Inst->getResults ()) {
798
+ result = lookThroughBorrowedFromDef (result);
799
+ if (valuesToComplete.count (result)) {
800
+ valuesToComplete.erase (result);
801
+ }
802
+ }
780
803
Inst->replaceAllUsesOfAllResultsWithUndef ();
781
804
782
805
if (isa<ApplyInst>(Inst))
@@ -789,7 +812,9 @@ bool DCE::removeDead() {
789
812
790
813
OSSALifetimeCompletion completion (F, DT, *deadEndBlocks);
791
814
for (auto value : valuesToComplete) {
792
- completion.completeOSSALifetime (value,
815
+ if (!value.has_value ())
816
+ continue ;
817
+ completion.completeOSSALifetime (*value,
793
818
OSSALifetimeCompletion::Boundary::Liveness);
794
819
}
795
820
@@ -846,9 +871,9 @@ void DCE::computeLevelNumbers(PostDomTreeNode *root) {
846
871
auto entry = workList.pop_back_val ();
847
872
PostDomTreeNode *node = entry.first ;
848
873
unsigned level = entry.second ;
849
-
874
+
850
875
insertControllingInfo (node->getBlock (), level);
851
-
876
+
852
877
for (PostDomTreeNode *child : *node) {
853
878
workList.push_back ({child, level + 1 });
854
879
}
0 commit comments