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