1f4a2713aSLionel Sambuc //===-- UnreachableBlockElim.cpp - Remove unreachable blocks for codegen --===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This pass is an extremely simple version of the SimplifyCFG pass. Its sole
11f4a2713aSLionel Sambuc // job is to delete LLVM basic blocks that are not reachable from the entry
12f4a2713aSLionel Sambuc // node. To do this, it performs a simple depth first traversal of the CFG,
13f4a2713aSLionel Sambuc // then deletes any unvisited nodes.
14f4a2713aSLionel Sambuc //
15f4a2713aSLionel Sambuc // Note that this pass is really a hack. In particular, the instruction
16f4a2713aSLionel Sambuc // selectors for various targets should just not generate code for unreachable
17f4a2713aSLionel Sambuc // blocks. Until LLVM has a more systematic way of defining instruction
18f4a2713aSLionel Sambuc // selectors, however, we cannot really expect them to handle additional
19f4a2713aSLionel Sambuc // complexity.
20f4a2713aSLionel Sambuc //
21f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
22f4a2713aSLionel Sambuc
23f4a2713aSLionel Sambuc #include "llvm/CodeGen/Passes.h"
24f4a2713aSLionel Sambuc #include "llvm/ADT/DepthFirstIterator.h"
25f4a2713aSLionel Sambuc #include "llvm/ADT/SmallPtrSet.h"
26f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineDominators.h"
27f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineFunctionPass.h"
28f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineLoopInfo.h"
29f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineModuleInfo.h"
30f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineRegisterInfo.h"
31*0a6a1f1dSLionel Sambuc #include "llvm/IR/CFG.h"
32f4a2713aSLionel Sambuc #include "llvm/IR/Constant.h"
33*0a6a1f1dSLionel Sambuc #include "llvm/IR/Dominators.h"
34f4a2713aSLionel Sambuc #include "llvm/IR/Function.h"
35f4a2713aSLionel Sambuc #include "llvm/IR/Instructions.h"
36f4a2713aSLionel Sambuc #include "llvm/IR/Type.h"
37f4a2713aSLionel Sambuc #include "llvm/Pass.h"
38f4a2713aSLionel Sambuc #include "llvm/Target/TargetInstrInfo.h"
39f4a2713aSLionel Sambuc using namespace llvm;
40f4a2713aSLionel Sambuc
41f4a2713aSLionel Sambuc namespace {
42f4a2713aSLionel Sambuc class UnreachableBlockElim : public FunctionPass {
43*0a6a1f1dSLionel Sambuc bool runOnFunction(Function &F) override;
44f4a2713aSLionel Sambuc public:
45f4a2713aSLionel Sambuc static char ID; // Pass identification, replacement for typeid
UnreachableBlockElim()46f4a2713aSLionel Sambuc UnreachableBlockElim() : FunctionPass(ID) {
47f4a2713aSLionel Sambuc initializeUnreachableBlockElimPass(*PassRegistry::getPassRegistry());
48f4a2713aSLionel Sambuc }
49f4a2713aSLionel Sambuc
getAnalysisUsage(AnalysisUsage & AU) const50*0a6a1f1dSLionel Sambuc void getAnalysisUsage(AnalysisUsage &AU) const override {
51*0a6a1f1dSLionel Sambuc AU.addPreserved<DominatorTreeWrapperPass>();
52f4a2713aSLionel Sambuc }
53f4a2713aSLionel Sambuc };
54f4a2713aSLionel Sambuc }
55f4a2713aSLionel Sambuc char UnreachableBlockElim::ID = 0;
56f4a2713aSLionel Sambuc INITIALIZE_PASS(UnreachableBlockElim, "unreachableblockelim",
57f4a2713aSLionel Sambuc "Remove unreachable blocks from the CFG", false, false)
58f4a2713aSLionel Sambuc
createUnreachableBlockEliminationPass()59f4a2713aSLionel Sambuc FunctionPass *llvm::createUnreachableBlockEliminationPass() {
60f4a2713aSLionel Sambuc return new UnreachableBlockElim();
61f4a2713aSLionel Sambuc }
62f4a2713aSLionel Sambuc
runOnFunction(Function & F)63f4a2713aSLionel Sambuc bool UnreachableBlockElim::runOnFunction(Function &F) {
64f4a2713aSLionel Sambuc SmallPtrSet<BasicBlock*, 8> Reachable;
65f4a2713aSLionel Sambuc
66f4a2713aSLionel Sambuc // Mark all reachable blocks.
67*0a6a1f1dSLionel Sambuc for (BasicBlock *BB : depth_first_ext(&F, Reachable))
68*0a6a1f1dSLionel Sambuc (void)BB/* Mark all reachable blocks */;
69f4a2713aSLionel Sambuc
70f4a2713aSLionel Sambuc // Loop over all dead blocks, remembering them and deleting all instructions
71f4a2713aSLionel Sambuc // in them.
72f4a2713aSLionel Sambuc std::vector<BasicBlock*> DeadBlocks;
73f4a2713aSLionel Sambuc for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
74f4a2713aSLionel Sambuc if (!Reachable.count(I)) {
75f4a2713aSLionel Sambuc BasicBlock *BB = I;
76f4a2713aSLionel Sambuc DeadBlocks.push_back(BB);
77f4a2713aSLionel Sambuc while (PHINode *PN = dyn_cast<PHINode>(BB->begin())) {
78f4a2713aSLionel Sambuc PN->replaceAllUsesWith(Constant::getNullValue(PN->getType()));
79f4a2713aSLionel Sambuc BB->getInstList().pop_front();
80f4a2713aSLionel Sambuc }
81f4a2713aSLionel Sambuc for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI)
82f4a2713aSLionel Sambuc (*SI)->removePredecessor(BB);
83f4a2713aSLionel Sambuc BB->dropAllReferences();
84f4a2713aSLionel Sambuc }
85f4a2713aSLionel Sambuc
86f4a2713aSLionel Sambuc // Actually remove the blocks now.
87f4a2713aSLionel Sambuc for (unsigned i = 0, e = DeadBlocks.size(); i != e; ++i) {
88f4a2713aSLionel Sambuc DeadBlocks[i]->eraseFromParent();
89f4a2713aSLionel Sambuc }
90f4a2713aSLionel Sambuc
91f4a2713aSLionel Sambuc return DeadBlocks.size();
92f4a2713aSLionel Sambuc }
93f4a2713aSLionel Sambuc
94f4a2713aSLionel Sambuc
95f4a2713aSLionel Sambuc namespace {
96f4a2713aSLionel Sambuc class UnreachableMachineBlockElim : public MachineFunctionPass {
97*0a6a1f1dSLionel Sambuc bool runOnMachineFunction(MachineFunction &F) override;
98*0a6a1f1dSLionel Sambuc void getAnalysisUsage(AnalysisUsage &AU) const override;
99f4a2713aSLionel Sambuc MachineModuleInfo *MMI;
100f4a2713aSLionel Sambuc public:
101f4a2713aSLionel Sambuc static char ID; // Pass identification, replacement for typeid
UnreachableMachineBlockElim()102f4a2713aSLionel Sambuc UnreachableMachineBlockElim() : MachineFunctionPass(ID) {}
103f4a2713aSLionel Sambuc };
104f4a2713aSLionel Sambuc }
105f4a2713aSLionel Sambuc char UnreachableMachineBlockElim::ID = 0;
106f4a2713aSLionel Sambuc
107f4a2713aSLionel Sambuc INITIALIZE_PASS(UnreachableMachineBlockElim, "unreachable-mbb-elimination",
108f4a2713aSLionel Sambuc "Remove unreachable machine basic blocks", false, false)
109f4a2713aSLionel Sambuc
110f4a2713aSLionel Sambuc char &llvm::UnreachableMachineBlockElimID = UnreachableMachineBlockElim::ID;
111f4a2713aSLionel Sambuc
getAnalysisUsage(AnalysisUsage & AU) const112f4a2713aSLionel Sambuc void UnreachableMachineBlockElim::getAnalysisUsage(AnalysisUsage &AU) const {
113f4a2713aSLionel Sambuc AU.addPreserved<MachineLoopInfo>();
114f4a2713aSLionel Sambuc AU.addPreserved<MachineDominatorTree>();
115f4a2713aSLionel Sambuc MachineFunctionPass::getAnalysisUsage(AU);
116f4a2713aSLionel Sambuc }
117f4a2713aSLionel Sambuc
runOnMachineFunction(MachineFunction & F)118f4a2713aSLionel Sambuc bool UnreachableMachineBlockElim::runOnMachineFunction(MachineFunction &F) {
119f4a2713aSLionel Sambuc SmallPtrSet<MachineBasicBlock*, 8> Reachable;
120f4a2713aSLionel Sambuc bool ModifiedPHI = false;
121f4a2713aSLionel Sambuc
122f4a2713aSLionel Sambuc MMI = getAnalysisIfAvailable<MachineModuleInfo>();
123f4a2713aSLionel Sambuc MachineDominatorTree *MDT = getAnalysisIfAvailable<MachineDominatorTree>();
124f4a2713aSLionel Sambuc MachineLoopInfo *MLI = getAnalysisIfAvailable<MachineLoopInfo>();
125f4a2713aSLionel Sambuc
126f4a2713aSLionel Sambuc // Mark all reachable blocks.
127*0a6a1f1dSLionel Sambuc for (MachineBasicBlock *BB : depth_first_ext(&F, Reachable))
128*0a6a1f1dSLionel Sambuc (void)BB/* Mark all reachable blocks */;
129f4a2713aSLionel Sambuc
130f4a2713aSLionel Sambuc // Loop over all dead blocks, remembering them and deleting all instructions
131f4a2713aSLionel Sambuc // in them.
132f4a2713aSLionel Sambuc std::vector<MachineBasicBlock*> DeadBlocks;
133f4a2713aSLionel Sambuc for (MachineFunction::iterator I = F.begin(), E = F.end(); I != E; ++I) {
134f4a2713aSLionel Sambuc MachineBasicBlock *BB = I;
135f4a2713aSLionel Sambuc
136f4a2713aSLionel Sambuc // Test for deadness.
137f4a2713aSLionel Sambuc if (!Reachable.count(BB)) {
138f4a2713aSLionel Sambuc DeadBlocks.push_back(BB);
139f4a2713aSLionel Sambuc
140f4a2713aSLionel Sambuc // Update dominator and loop info.
141f4a2713aSLionel Sambuc if (MLI) MLI->removeBlock(BB);
142f4a2713aSLionel Sambuc if (MDT && MDT->getNode(BB)) MDT->eraseNode(BB);
143f4a2713aSLionel Sambuc
144f4a2713aSLionel Sambuc while (BB->succ_begin() != BB->succ_end()) {
145f4a2713aSLionel Sambuc MachineBasicBlock* succ = *BB->succ_begin();
146f4a2713aSLionel Sambuc
147f4a2713aSLionel Sambuc MachineBasicBlock::iterator start = succ->begin();
148f4a2713aSLionel Sambuc while (start != succ->end() && start->isPHI()) {
149f4a2713aSLionel Sambuc for (unsigned i = start->getNumOperands() - 1; i >= 2; i-=2)
150f4a2713aSLionel Sambuc if (start->getOperand(i).isMBB() &&
151f4a2713aSLionel Sambuc start->getOperand(i).getMBB() == BB) {
152f4a2713aSLionel Sambuc start->RemoveOperand(i);
153f4a2713aSLionel Sambuc start->RemoveOperand(i-1);
154f4a2713aSLionel Sambuc }
155f4a2713aSLionel Sambuc
156f4a2713aSLionel Sambuc start++;
157f4a2713aSLionel Sambuc }
158f4a2713aSLionel Sambuc
159f4a2713aSLionel Sambuc BB->removeSuccessor(BB->succ_begin());
160f4a2713aSLionel Sambuc }
161f4a2713aSLionel Sambuc }
162f4a2713aSLionel Sambuc }
163f4a2713aSLionel Sambuc
164f4a2713aSLionel Sambuc // Actually remove the blocks now.
165f4a2713aSLionel Sambuc for (unsigned i = 0, e = DeadBlocks.size(); i != e; ++i)
166f4a2713aSLionel Sambuc DeadBlocks[i]->eraseFromParent();
167f4a2713aSLionel Sambuc
168f4a2713aSLionel Sambuc // Cleanup PHI nodes.
169f4a2713aSLionel Sambuc for (MachineFunction::iterator I = F.begin(), E = F.end(); I != E; ++I) {
170f4a2713aSLionel Sambuc MachineBasicBlock *BB = I;
171f4a2713aSLionel Sambuc // Prune unneeded PHI entries.
172f4a2713aSLionel Sambuc SmallPtrSet<MachineBasicBlock*, 8> preds(BB->pred_begin(),
173f4a2713aSLionel Sambuc BB->pred_end());
174f4a2713aSLionel Sambuc MachineBasicBlock::iterator phi = BB->begin();
175f4a2713aSLionel Sambuc while (phi != BB->end() && phi->isPHI()) {
176f4a2713aSLionel Sambuc for (unsigned i = phi->getNumOperands() - 1; i >= 2; i-=2)
177f4a2713aSLionel Sambuc if (!preds.count(phi->getOperand(i).getMBB())) {
178f4a2713aSLionel Sambuc phi->RemoveOperand(i);
179f4a2713aSLionel Sambuc phi->RemoveOperand(i-1);
180f4a2713aSLionel Sambuc ModifiedPHI = true;
181f4a2713aSLionel Sambuc }
182f4a2713aSLionel Sambuc
183f4a2713aSLionel Sambuc if (phi->getNumOperands() == 3) {
184f4a2713aSLionel Sambuc unsigned Input = phi->getOperand(1).getReg();
185f4a2713aSLionel Sambuc unsigned Output = phi->getOperand(0).getReg();
186f4a2713aSLionel Sambuc
187f4a2713aSLionel Sambuc MachineInstr* temp = phi;
188f4a2713aSLionel Sambuc ++phi;
189f4a2713aSLionel Sambuc temp->eraseFromParent();
190f4a2713aSLionel Sambuc ModifiedPHI = true;
191f4a2713aSLionel Sambuc
192f4a2713aSLionel Sambuc if (Input != Output) {
193f4a2713aSLionel Sambuc MachineRegisterInfo &MRI = F.getRegInfo();
194f4a2713aSLionel Sambuc MRI.constrainRegClass(Input, MRI.getRegClass(Output));
195f4a2713aSLionel Sambuc MRI.replaceRegWith(Output, Input);
196f4a2713aSLionel Sambuc }
197f4a2713aSLionel Sambuc
198f4a2713aSLionel Sambuc continue;
199f4a2713aSLionel Sambuc }
200f4a2713aSLionel Sambuc
201f4a2713aSLionel Sambuc ++phi;
202f4a2713aSLionel Sambuc }
203f4a2713aSLionel Sambuc }
204f4a2713aSLionel Sambuc
205f4a2713aSLionel Sambuc F.RenumberBlocks();
206f4a2713aSLionel Sambuc
207f4a2713aSLionel Sambuc return (DeadBlocks.size() || ModifiedPHI);
208f4a2713aSLionel Sambuc }
209