Skip to content

Commit 4d61dad

Browse files
committed
DeadCodeElimination: Make DCE a separate class, called by DCEPass::run().
Instead of manually managing the internal state of the pass. Also, use BasicBlockSet instead of SmallPtrSet.
1 parent f7f7188 commit 4d61dad

File tree

1 file changed

+80
-77
lines changed

1 file changed

+80
-77
lines changed

lib/SILOptimizer/Transforms/DeadCodeElimination.cpp

Lines changed: 80 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
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) {
451416
SILBasicBlock *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

794763
void 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

809812
SILTransform *swift::createDCE() {
810-
return new DCE();
813+
return new DCEPass();
811814
}

0 commit comments

Comments
 (0)