xref: /minix3/external/bsd/llvm/dist/llvm/lib/CodeGen/UnreachableBlockElim.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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