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
@@ -731,9 +732,23 @@ bool DCE::removeDead() {
731
732
endLifetimeOfLiveValue (predOp, insertPt);
732
733
}
733
734
}
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
+ }));
737
752
Changed = true ;
738
753
BranchesChanged = true ;
739
754
}
@@ -747,7 +762,8 @@ bool DCE::removeDead() {
747
762
// We want to replace dead terminators with unconditional branches to
748
763
// the nearest post-dominator that has useful instructions.
749
764
if (auto *termInst = dyn_cast<TermInst>(Inst)) {
750
- SILBasicBlock *postDom = nearestUsefulPostDominator (Inst->getParent ());
765
+ SILBasicBlock *postDom =
766
+ nearestUsefulPostDominator (termInst->getParent ());
751
767
if (!postDom)
752
768
continue ;
753
769
@@ -757,12 +773,13 @@ bool DCE::removeDead() {
757
773
}
758
774
}
759
775
LLVM_DEBUG (llvm::dbgs () << " Replacing branch: " );
760
- LLVM_DEBUG (Inst ->dump ());
776
+ LLVM_DEBUG (termInst ->dump ());
761
777
LLVM_DEBUG (llvm::dbgs ()
762
778
<< " with jump to: BB" << postDom->getDebugID () << " \n " );
763
779
764
- replaceBranchWithJump (Inst, postDom);
765
- Inst->eraseFromParent ();
780
+ replaceBranchWithJump (termInst, postDom);
781
+ ++NumDeletedInsts;
782
+ termInst->eraseFromParent ();
766
783
BranchesChanged = true ;
767
784
Changed = true ;
768
785
continue ;
@@ -780,6 +797,12 @@ bool DCE::removeDead() {
780
797
}
781
798
}
782
799
}
800
+ for (auto result : Inst->getResults ()) {
801
+ result = lookThroughBorrowedFromDef (result);
802
+ if (valuesToComplete.count (result)) {
803
+ valuesToComplete.erase (result);
804
+ }
805
+ }
783
806
Inst->replaceAllUsesOfAllResultsWithUndef ();
784
807
785
808
if (isa<ApplyInst>(Inst))
@@ -792,7 +815,9 @@ bool DCE::removeDead() {
792
815
793
816
OSSALifetimeCompletion completion (F, DT, *deadEndBlocks);
794
817
for (auto value : valuesToComplete) {
795
- completion.completeOSSALifetime (value,
818
+ if (!value.has_value ())
819
+ continue ;
820
+ completion.completeOSSALifetime (*value,
796
821
OSSALifetimeCompletion::Boundary::Liveness);
797
822
}
798
823
@@ -849,9 +874,9 @@ void DCE::computeLevelNumbers(PostDomTreeNode *root) {
849
874
auto entry = workList.pop_back_val ();
850
875
PostDomTreeNode *node = entry.first ;
851
876
unsigned level = entry.second ;
852
-
877
+
853
878
insertControllingInfo (node->getBlock (), level);
854
-
879
+
855
880
for (PostDomTreeNode *child : *node) {
856
881
workList.push_back ({child, level + 1 });
857
882
}
0 commit comments