17
17
#include " swift/SIL/SILBuilder.h"
18
18
#include " swift/SIL/SILFunction.h"
19
19
#include " swift/SIL/SILUndef.h"
20
+ #include " swift/SIL/SILBitfield.h"
20
21
#include " swift/SILOptimizer/Analysis/DominanceAnalysis.h"
21
22
#include " swift/SILOptimizer/PassManager/Passes.h"
22
23
#include " swift/SILOptimizer/PassManager/Transforms.h"
@@ -92,11 +93,12 @@ struct ControllingInfo {
92
93
unsigned MinTreePredLevel;
93
94
};
94
95
95
- class DCE : public SILFunctionTransform {
96
+ class DCE {
96
97
typedef llvm::DomTreeNodeBase<SILBasicBlock> PostDomTreeNode;
97
98
99
+ SILFunction *F;
98
100
llvm::SmallPtrSet<SILNode *, 16 > LiveValues;
99
- llvm::SmallPtrSet<SILBasicBlock *, 16 > LiveBlocks;
101
+ BasicBlockSet LiveBlocks;
100
102
llvm::SmallVector<SILInstruction *, 64 > Worklist;
101
103
PostDominanceInfo *PDT;
102
104
llvm::DenseMap<SILBasicBlock *, ControllingInfo> ControllingInfoMap;
@@ -119,72 +121,20 @@ class DCE : public SILFunctionTransform {
119
121
ReverseDependencies;
120
122
121
123
// / Tracks if the pass changed branches.
122
- bool BranchesChanged;
124
+ bool BranchesChanged = false ;
123
125
// / Tracks if the pass changed ApplyInsts.
124
- bool CallsChanged;
126
+ bool CallsChanged = false ;
125
127
126
- // / The entry point to the transformation.
127
- void run () override {
128
- BranchesChanged = false ;
129
- CallsChanged = false ;
130
-
131
- SILFunction *F = getFunction ();
132
- auto *DA = PM->getAnalysis <PostDominanceAnalysis>();
133
- PDT = DA->get (F);
134
-
135
- // If we have a function that consists of nothing but a
136
- // structurally infinite loop like:
137
- // while true {}
138
- // we'll have an empty post dominator tree.
139
- if (!PDT->getRootNode ())
140
- return ;
141
-
142
- LLVM_DEBUG (F->dump ());
143
- LLVM_DEBUG (PDT->print (llvm::dbgs ()));
144
-
145
- assert (Worklist.empty () && LiveValues.empty () && LiveBlocks.empty () &&
146
- ControllingInfoMap.empty () && ReverseDependencies.empty () &&
147
- " Expected to start with empty data structures!" );
148
-
149
- if (!precomputeControlInfo (*F)) {
150
- LiveValues.clear ();
151
- LiveBlocks.clear ();
152
- ControllingInfoMap.clear ();
153
- ReverseDependencies.clear ();
154
- return ;
155
- }
156
-
157
- markLive (*F);
158
- if (removeDead (*F)) {
159
- using InvalidationKind = SILAnalysis::InvalidationKind;
160
-
161
- unsigned Inv = InvalidationKind::Instructions;
162
- if (CallsChanged)
163
- Inv |= (unsigned )InvalidationKind::Calls;
164
- if (BranchesChanged) {
165
- removeUnreachableBlocks (*F);
166
- Inv |= (unsigned )InvalidationKind::Branches;
167
- }
168
-
169
- invalidateAnalysis (SILAnalysis::InvalidationKind (Inv));
170
- }
171
-
172
- LiveValues.clear ();
173
- LiveBlocks.clear ();
174
- ControllingInfoMap.clear ();
175
- ReverseDependencies.clear ();
176
- }
177
-
178
- bool precomputeControlInfo (SILFunction &F);
179
- void markLive (SILFunction &F);
128
+ bool precomputeControlInfo ();
129
+ void markLive ();
180
130
// / Record a reverse dependency from \p from to \p to meaning \p to is live
181
131
// / if \p from is also live.
182
132
void addReverseDependency (SILValue from, SILInstruction *to);
183
- bool removeDead (SILFunction &F );
133
+ bool removeDead ();
184
134
185
135
void computeLevelNumbers (PostDomTreeNode *root);
186
- bool hasInfiniteLoops (SILFunction &F );
187
- void computePredecessorDependence (SILFunction &F );
136
+ bool hasInfiniteLoops ();
137
+ void computePredecessorDependence ();
188
138
void computeMinPredecessorLevels (PostDomTreeNode *root);
189
139
void insertControllingInfo (SILBasicBlock *Block, unsigned Level);
190
140
@@ -204,6 +154,21 @@ class DCE : public SILFunctionTransform {
204
154
// / If \p value is live, insert a lifetime ending operation in ossa.
205
155
// / destroy_value for @owned value and end_borrow for a @guaranteed value.
206
156
void endLifetimeOfLiveValue (SILValue value, SILInstruction *insertPt);
157
+
158
+ public:
159
+ DCE (SILFunction *F, PostDominanceInfo *PDT) : F(F), LiveBlocks(F), PDT(PDT) {}
160
+
161
+ // / The entry point to the transformation.
162
+ bool run () {
163
+ if (!precomputeControlInfo ())
164
+ return false ;
165
+
166
+ markLive ();
167
+ return removeDead ();
168
+ }
169
+
170
+ bool mustInvalidateCalls () const { return CallsChanged; }
171
+ bool mustInvalidateBranches () const { return BranchesChanged; }
207
172
};
208
173
209
174
// Keep track of the fact that V is live and add it to our worklist
@@ -252,11 +217,11 @@ static BuiltinInst *getProducer(CondFailInst *CFI) {
252
217
}
253
218
254
219
// Determine which instructions from this function we need to keep.
255
- void DCE::markLive (SILFunction &F ) {
220
+ void DCE::markLive () {
256
221
// Find the initial set of instructions in this function that appear
257
222
// to be live in the sense that they are not trivially something we
258
223
// can delete by examining only that instruction.
259
- for (auto &BB : F) {
224
+ for (auto &BB : * F) {
260
225
for (auto &I : BB) {
261
226
switch (I.getKind ()) {
262
227
case SILInstructionKind::CondFailInst: {
@@ -451,7 +416,11 @@ void DCE::propagateLiveness(SILInstruction *I) {
451
416
SILBasicBlock *DCE::nearestUsefulPostDominator (SILBasicBlock *Block) {
452
417
// Find the nearest post-dominator that has useful instructions.
453
418
auto *PostDomNode = PDT->getNode (Block)->getIDom ();
454
- while (PostDomNode && !LiveBlocks.count (PostDomNode->getBlock ()))
419
+ while (PostDomNode &&
420
+ // In case the PostDomNode's block is null, it means it's not contained
421
+ // in LiveBlocks.
422
+ (!PostDomNode->getBlock () ||
423
+ !LiveBlocks.contains (PostDomNode->getBlock ())))
455
424
PostDomNode = PostDomNode->getIDom ();
456
425
457
426
if (PostDomNode)
@@ -508,10 +477,10 @@ void DCE::endLifetimeOfLiveValue(SILValue value, SILInstruction *insertPt) {
508
477
}
509
478
510
479
// Remove the instructions that are not potentially useful.
511
- bool DCE::removeDead (SILFunction &F ) {
480
+ bool DCE::removeDead () {
512
481
bool Changed = false ;
513
482
514
- for (auto &BB : F) {
483
+ for (auto &BB : * F) {
515
484
for (unsigned i = 0 ; i < BB.getArguments ().size ();) {
516
485
auto *arg = BB.getArgument (i);
517
486
if (LiveValues.count (arg)) {
@@ -524,7 +493,7 @@ bool DCE::removeDead(SILFunction &F) {
524
493
525
494
arg->replaceAllUsesWithUndef ();
526
495
527
- if (!F. hasOwnership () || arg->getOwnershipKind () == OwnershipKind::None) {
496
+ if (!F-> hasOwnership () || arg->getOwnershipKind () == OwnershipKind::None) {
528
497
i++;
529
498
Changed = true ;
530
499
BranchesChanged = true ;
@@ -591,7 +560,7 @@ bool DCE::removeDead(SILFunction &F) {
591
560
LLVM_DEBUG (llvm::dbgs () << " Removing dead instruction:\n " );
592
561
LLVM_DEBUG (Inst->dump ());
593
562
594
- if (F. hasOwnership ()) {
563
+ if (F-> hasOwnership ()) {
595
564
for (auto &Op : Inst->getAllOperands ()) {
596
565
if (Op.isLifetimeEnding ()) {
597
566
endLifetimeOfLiveValue (Op.get (), Inst);
@@ -631,11 +600,11 @@ bool DCE::removeDead(SILFunction &F) {
631
600
//
632
601
// Returns true upon success, false if nodes that are not present in the
633
602
// post-dominator tree are detected.
634
- bool DCE::precomputeControlInfo (SILFunction &F ) {
603
+ bool DCE::precomputeControlInfo () {
635
604
computeLevelNumbers (PDT->getRootNode ());
636
- if (hasInfiniteLoops (F ))
605
+ if (hasInfiniteLoops ())
637
606
return false ;
638
- computePredecessorDependence (F );
607
+ computePredecessorDependence ();
639
608
computeMinPredecessorLevels (PDT->getRootNode ());
640
609
return true ;
641
610
}
@@ -680,8 +649,8 @@ void DCE::computeLevelNumbers(PostDomTreeNode *root) {
680
649
// elimination. Note this will also hit for unreachable code, but
681
650
// presumably we'll run DCE at some point after removing unreachable
682
651
// code.
683
- bool DCE::hasInfiniteLoops (SILFunction &F ) {
684
- for (auto &BB : F)
652
+ bool DCE::hasInfiniteLoops () {
653
+ for (auto &BB : * F)
685
654
if (ControllingInfoMap.find (&BB) == ControllingInfoMap.end ())
686
655
return true ;
687
656
@@ -691,8 +660,8 @@ bool DCE::hasInfiniteLoops(SILFunction &F) {
691
660
// For each block, create a list of the direct predecessors that the
692
661
// block is control-dependent on. With each predecessor, also keep the
693
662
// level number of the predecessor in the post-dominator tree.
694
- void DCE::computePredecessorDependence (SILFunction &F ) {
695
- for (auto &BB : F) {
663
+ void DCE::computePredecessorDependence () {
664
+ for (auto &BB : * F) {
696
665
assert (ControllingInfoMap.find (&BB) != ControllingInfoMap.end ()
697
666
&& " Expected to already have a map entry for block!" );
698
667
@@ -792,7 +761,7 @@ void DCE::collectControllingBlocks(SILBasicBlock *Block,
792
761
}
793
762
794
763
void DCE::markControllingTerminatorsLive (SILBasicBlock *Block) {
795
- if (LiveBlocks.count (Block))
764
+ if (LiveBlocks.contains (Block))
796
765
return ;
797
766
798
767
LiveBlocks.insert (Block);
@@ -804,8 +773,42 @@ void DCE::markControllingTerminatorsLive(SILBasicBlock *Block) {
804
773
markValueLive (BB->getTerminator ());
805
774
}
806
775
776
+ class DCEPass : public SILFunctionTransform {
777
+ public:
778
+ // / The entry point to the transformation.
779
+ void run () override {
780
+ SILFunction *F = getFunction ();
781
+
782
+ LLVM_DEBUG (llvm::dbgs () << " *** DCE on function: " << F->getName ()
783
+ << " ***\n " );
784
+
785
+ auto *DA = PM->getAnalysis <PostDominanceAnalysis>();
786
+ PostDominanceInfo *PDT = DA->get (F);
787
+
788
+ // If we have a function that consists of nothing but a
789
+ // structurally infinite loop like:
790
+ // while true {}
791
+ // we'll have an empty post dominator tree.
792
+ if (!PDT->getRootNode ())
793
+ return ;
794
+
795
+ DCE dce (F, PDT);
796
+ if (dce.run ()) {
797
+ using InvalidationKind = SILAnalysis::InvalidationKind;
798
+ unsigned Inv = InvalidationKind::Instructions;
799
+ if (dce.mustInvalidateCalls ())
800
+ Inv |= (unsigned )InvalidationKind::Calls;
801
+ if (dce.mustInvalidateBranches ()) {
802
+ removeUnreachableBlocks (*F);
803
+ Inv |= (unsigned )InvalidationKind::Branches;
804
+ }
805
+ invalidateAnalysis (SILAnalysis::InvalidationKind (Inv));
806
+ }
807
+ }
808
+ };
809
+
807
810
} // end anonymous namespace
808
811
809
812
SILTransform *swift::createDCE () {
810
- return new DCE ();
813
+ return new DCEPass ();
811
814
}
0 commit comments