1717#include " swift/SIL/SILBuilder.h"
1818#include " swift/SIL/SILFunction.h"
1919#include " swift/SIL/SILUndef.h"
20+ #include " swift/SIL/SILBitfield.h"
2021#include " swift/SILOptimizer/Analysis/DominanceAnalysis.h"
2122#include " swift/SILOptimizer/PassManager/Passes.h"
2223#include " swift/SILOptimizer/PassManager/Transforms.h"
@@ -92,11 +93,12 @@ struct ControllingInfo {
9293 unsigned MinTreePredLevel;
9394};
9495
95- class DCE : public SILFunctionTransform {
96+ class DCE {
9697 typedef llvm::DomTreeNodeBase<SILBasicBlock> PostDomTreeNode;
9798
99+ SILFunction *F;
98100 llvm::SmallPtrSet<SILNode *, 16 > LiveValues;
99- llvm::SmallPtrSet<SILBasicBlock *, 16 > LiveBlocks;
101+ BasicBlockSet LiveBlocks;
100102 llvm::SmallVector<SILInstruction *, 64 > Worklist;
101103 PostDominanceInfo *PDT;
102104 llvm::DenseMap<SILBasicBlock *, ControllingInfo> ControllingInfoMap;
@@ -119,72 +121,20 @@ class DCE : public SILFunctionTransform {
119121 ReverseDependencies;
120122
121123 // / Tracks if the pass changed branches.
122- bool BranchesChanged;
124+ bool BranchesChanged = false ;
123125 // / Tracks if the pass changed ApplyInsts.
124- bool CallsChanged;
126+ bool CallsChanged = false ;
125127
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 ();
180130 // / Record a reverse dependency from \p from to \p to meaning \p to is live
181131 // / if \p from is also live.
182132 void addReverseDependency (SILValue from, SILInstruction *to);
183- bool removeDead (SILFunction &F );
133+ bool removeDead ();
184134
185135 void computeLevelNumbers (PostDomTreeNode *root);
186- bool hasInfiniteLoops (SILFunction &F );
187- void computePredecessorDependence (SILFunction &F );
136+ bool hasInfiniteLoops ();
137+ void computePredecessorDependence ();
188138 void computeMinPredecessorLevels (PostDomTreeNode *root);
189139 void insertControllingInfo (SILBasicBlock *Block, unsigned Level);
190140
@@ -204,6 +154,21 @@ class DCE : public SILFunctionTransform {
204154 // / If \p value is live, insert a lifetime ending operation in ossa.
205155 // / destroy_value for @owned value and end_borrow for a @guaranteed value.
206156 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; }
207172};
208173
209174// Keep track of the fact that V is live and add it to our worklist
@@ -252,11 +217,11 @@ static BuiltinInst *getProducer(CondFailInst *CFI) {
252217}
253218
254219// Determine which instructions from this function we need to keep.
255- void DCE::markLive (SILFunction &F ) {
220+ void DCE::markLive () {
256221 // Find the initial set of instructions in this function that appear
257222 // to be live in the sense that they are not trivially something we
258223 // can delete by examining only that instruction.
259- for (auto &BB : F) {
224+ for (auto &BB : * F) {
260225 for (auto &I : BB) {
261226 switch (I.getKind ()) {
262227 case SILInstructionKind::CondFailInst: {
@@ -451,7 +416,11 @@ void DCE::propagateLiveness(SILInstruction *I) {
451416SILBasicBlock *DCE::nearestUsefulPostDominator (SILBasicBlock *Block) {
452417 // Find the nearest post-dominator that has useful instructions.
453418 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 ())))
455424 PostDomNode = PostDomNode->getIDom ();
456425
457426 if (PostDomNode)
@@ -508,10 +477,10 @@ void DCE::endLifetimeOfLiveValue(SILValue value, SILInstruction *insertPt) {
508477}
509478
510479// Remove the instructions that are not potentially useful.
511- bool DCE::removeDead (SILFunction &F ) {
480+ bool DCE::removeDead () {
512481 bool Changed = false ;
513482
514- for (auto &BB : F) {
483+ for (auto &BB : * F) {
515484 for (unsigned i = 0 ; i < BB.getArguments ().size ();) {
516485 auto *arg = BB.getArgument (i);
517486 if (LiveValues.count (arg)) {
@@ -524,7 +493,7 @@ bool DCE::removeDead(SILFunction &F) {
524493
525494 arg->replaceAllUsesWithUndef ();
526495
527- if (!F. hasOwnership () || arg->getOwnershipKind () == OwnershipKind::None) {
496+ if (!F-> hasOwnership () || arg->getOwnershipKind () == OwnershipKind::None) {
528497 i++;
529498 Changed = true ;
530499 BranchesChanged = true ;
@@ -591,7 +560,7 @@ bool DCE::removeDead(SILFunction &F) {
591560 LLVM_DEBUG (llvm::dbgs () << " Removing dead instruction:\n " );
592561 LLVM_DEBUG (Inst->dump ());
593562
594- if (F. hasOwnership ()) {
563+ if (F-> hasOwnership ()) {
595564 for (auto &Op : Inst->getAllOperands ()) {
596565 if (Op.isLifetimeEnding ()) {
597566 endLifetimeOfLiveValue (Op.get (), Inst);
@@ -631,11 +600,11 @@ bool DCE::removeDead(SILFunction &F) {
631600//
632601// Returns true upon success, false if nodes that are not present in the
633602// post-dominator tree are detected.
634- bool DCE::precomputeControlInfo (SILFunction &F ) {
603+ bool DCE::precomputeControlInfo () {
635604 computeLevelNumbers (PDT->getRootNode ());
636- if (hasInfiniteLoops (F ))
605+ if (hasInfiniteLoops ())
637606 return false ;
638- computePredecessorDependence (F );
607+ computePredecessorDependence ();
639608 computeMinPredecessorLevels (PDT->getRootNode ());
640609 return true ;
641610}
@@ -680,8 +649,8 @@ void DCE::computeLevelNumbers(PostDomTreeNode *root) {
680649// elimination. Note this will also hit for unreachable code, but
681650// presumably we'll run DCE at some point after removing unreachable
682651// code.
683- bool DCE::hasInfiniteLoops (SILFunction &F ) {
684- for (auto &BB : F)
652+ bool DCE::hasInfiniteLoops () {
653+ for (auto &BB : * F)
685654 if (ControllingInfoMap.find (&BB) == ControllingInfoMap.end ())
686655 return true ;
687656
@@ -691,8 +660,8 @@ bool DCE::hasInfiniteLoops(SILFunction &F) {
691660// For each block, create a list of the direct predecessors that the
692661// block is control-dependent on. With each predecessor, also keep the
693662// 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) {
696665 assert (ControllingInfoMap.find (&BB) != ControllingInfoMap.end ()
697666 && " Expected to already have a map entry for block!" );
698667
@@ -792,7 +761,7 @@ void DCE::collectControllingBlocks(SILBasicBlock *Block,
792761}
793762
794763void DCE::markControllingTerminatorsLive (SILBasicBlock *Block) {
795- if (LiveBlocks.count (Block))
764+ if (LiveBlocks.contains (Block))
796765 return ;
797766
798767 LiveBlocks.insert (Block);
@@ -804,8 +773,42 @@ void DCE::markControllingTerminatorsLive(SILBasicBlock *Block) {
804773 markValueLive (BB->getTerminator ());
805774}
806775
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+
807810} // end anonymous namespace
808811
809812SILTransform *swift::createDCE () {
810- return new DCE ();
813+ return new DCEPass ();
811814}
0 commit comments