10b57cec5SDimitry Andric //===-- UnreachableBlockElim.cpp - Remove unreachable blocks for codegen --===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This pass is an extremely simple version of the SimplifyCFG pass. Its sole 100b57cec5SDimitry Andric // job is to delete LLVM basic blocks that are not reachable from the entry 110b57cec5SDimitry Andric // node. To do this, it performs a simple depth first traversal of the CFG, 120b57cec5SDimitry Andric // then deletes any unvisited nodes. 130b57cec5SDimitry Andric // 140b57cec5SDimitry Andric // Note that this pass is really a hack. In particular, the instruction 150b57cec5SDimitry Andric // selectors for various targets should just not generate code for unreachable 160b57cec5SDimitry Andric // blocks. Until LLVM has a more systematic way of defining instruction 170b57cec5SDimitry Andric // selectors, however, we cannot really expect them to handle additional 180b57cec5SDimitry Andric // complexity. 190b57cec5SDimitry Andric // 200b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric #include "llvm/CodeGen/UnreachableBlockElim.h" 230b57cec5SDimitry Andric #include "llvm/ADT/DepthFirstIterator.h" 240b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 280b57cec5SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h" 290b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 300b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h" 310b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 320b57cec5SDimitry Andric #include "llvm/IR/Dominators.h" 33480093f4SDimitry Andric #include "llvm/InitializePasses.h" 340b57cec5SDimitry Andric #include "llvm/Pass.h" 350b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h" 360b57cec5SDimitry Andric using namespace llvm; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric namespace { 390b57cec5SDimitry Andric class UnreachableBlockElimLegacyPass : public FunctionPass { 400b57cec5SDimitry Andric bool runOnFunction(Function &F) override { 410b57cec5SDimitry Andric return llvm::EliminateUnreachableBlocks(F); 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric public: 450b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid 460b57cec5SDimitry Andric UnreachableBlockElimLegacyPass() : FunctionPass(ID) { 470b57cec5SDimitry Andric initializeUnreachableBlockElimLegacyPassPass( 480b57cec5SDimitry Andric *PassRegistry::getPassRegistry()); 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 520b57cec5SDimitry Andric AU.addPreserved<DominatorTreeWrapperPass>(); 530b57cec5SDimitry Andric } 540b57cec5SDimitry Andric }; 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric char UnreachableBlockElimLegacyPass::ID = 0; 570b57cec5SDimitry Andric INITIALIZE_PASS(UnreachableBlockElimLegacyPass, "unreachableblockelim", 580b57cec5SDimitry Andric "Remove unreachable blocks from the CFG", false, false) 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric FunctionPass *llvm::createUnreachableBlockEliminationPass() { 610b57cec5SDimitry Andric return new UnreachableBlockElimLegacyPass(); 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric PreservedAnalyses UnreachableBlockElimPass::run(Function &F, 650b57cec5SDimitry Andric FunctionAnalysisManager &AM) { 660b57cec5SDimitry Andric bool Changed = llvm::EliminateUnreachableBlocks(F); 670b57cec5SDimitry Andric if (!Changed) 680b57cec5SDimitry Andric return PreservedAnalyses::all(); 690b57cec5SDimitry Andric PreservedAnalyses PA; 700b57cec5SDimitry Andric PA.preserve<DominatorTreeAnalysis>(); 710b57cec5SDimitry Andric return PA; 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric namespace { 750b57cec5SDimitry Andric class UnreachableMachineBlockElim : public MachineFunctionPass { 760b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &F) override; 770b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 785ffd83dbSDimitry Andric 790b57cec5SDimitry Andric public: 800b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid 810b57cec5SDimitry Andric UnreachableMachineBlockElim() : MachineFunctionPass(ID) {} 820b57cec5SDimitry Andric }; 830b57cec5SDimitry Andric } 840b57cec5SDimitry Andric char UnreachableMachineBlockElim::ID = 0; 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric INITIALIZE_PASS(UnreachableMachineBlockElim, "unreachable-mbb-elimination", 870b57cec5SDimitry Andric "Remove unreachable machine basic blocks", false, false) 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric char &llvm::UnreachableMachineBlockElimID = UnreachableMachineBlockElim::ID; 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric void UnreachableMachineBlockElim::getAnalysisUsage(AnalysisUsage &AU) const { 92*0fca6ea1SDimitry Andric AU.addPreserved<MachineLoopInfoWrapperPass>(); 93*0fca6ea1SDimitry Andric AU.addPreserved<MachineDominatorTreeWrapperPass>(); 940b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric bool UnreachableMachineBlockElim::runOnMachineFunction(MachineFunction &F) { 980b57cec5SDimitry Andric df_iterator_default_set<MachineBasicBlock*> Reachable; 990b57cec5SDimitry Andric bool ModifiedPHI = false; 1000b57cec5SDimitry Andric 101*0fca6ea1SDimitry Andric MachineDominatorTreeWrapperPass *MDTWrapper = 102*0fca6ea1SDimitry Andric getAnalysisIfAvailable<MachineDominatorTreeWrapperPass>(); 103*0fca6ea1SDimitry Andric MachineDominatorTree *MDT = MDTWrapper ? &MDTWrapper->getDomTree() : nullptr; 104*0fca6ea1SDimitry Andric MachineLoopInfoWrapperPass *MLIWrapper = 105*0fca6ea1SDimitry Andric getAnalysisIfAvailable<MachineLoopInfoWrapperPass>(); 106*0fca6ea1SDimitry Andric MachineLoopInfo *MLI = MLIWrapper ? &MLIWrapper->getLI() : nullptr; 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric // Mark all reachable blocks. 1090b57cec5SDimitry Andric for (MachineBasicBlock *BB : depth_first_ext(&F, Reachable)) 1100b57cec5SDimitry Andric (void)BB/* Mark all reachable blocks */; 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric // Loop over all dead blocks, remembering them and deleting all instructions 1130b57cec5SDimitry Andric // in them. 1140b57cec5SDimitry Andric std::vector<MachineBasicBlock*> DeadBlocks; 115fe6060f1SDimitry Andric for (MachineBasicBlock &BB : F) { 1160b57cec5SDimitry Andric // Test for deadness. 117fe6060f1SDimitry Andric if (!Reachable.count(&BB)) { 118fe6060f1SDimitry Andric DeadBlocks.push_back(&BB); 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric // Update dominator and loop info. 121fe6060f1SDimitry Andric if (MLI) MLI->removeBlock(&BB); 122fe6060f1SDimitry Andric if (MDT && MDT->getNode(&BB)) MDT->eraseNode(&BB); 1230b57cec5SDimitry Andric 1247a6dacacSDimitry Andric while (!BB.succ_empty()) { 125fe6060f1SDimitry Andric MachineBasicBlock* succ = *BB.succ_begin(); 1260b57cec5SDimitry Andric 12706c3fb27SDimitry Andric for (MachineInstr &Phi : succ->phis()) { 12806c3fb27SDimitry Andric for (unsigned i = Phi.getNumOperands() - 1; i >= 2; i -= 2) { 12906c3fb27SDimitry Andric if (Phi.getOperand(i).isMBB() && 13006c3fb27SDimitry Andric Phi.getOperand(i).getMBB() == &BB) { 13106c3fb27SDimitry Andric Phi.removeOperand(i); 13206c3fb27SDimitry Andric Phi.removeOperand(i - 1); 1330b57cec5SDimitry Andric } 13406c3fb27SDimitry Andric } 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 137fe6060f1SDimitry Andric BB.removeSuccessor(BB.succ_begin()); 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric // Actually remove the blocks now. 1430eae32dcSDimitry Andric for (MachineBasicBlock *BB : DeadBlocks) { 1448bcb0991SDimitry Andric // Remove any call site information for calls in the block. 1450eae32dcSDimitry Andric for (auto &I : BB->instrs()) 1465ffd83dbSDimitry Andric if (I.shouldUpdateCallSiteInfo()) 1470eae32dcSDimitry Andric BB->getParent()->eraseCallSiteInfo(&I); 1488bcb0991SDimitry Andric 1490eae32dcSDimitry Andric BB->eraseFromParent(); 1508bcb0991SDimitry Andric } 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric // Cleanup PHI nodes. 1530eae32dcSDimitry Andric for (MachineBasicBlock &BB : F) { 1540b57cec5SDimitry Andric // Prune unneeded PHI entries. 1550eae32dcSDimitry Andric SmallPtrSet<MachineBasicBlock*, 8> preds(BB.pred_begin(), 1560eae32dcSDimitry Andric BB.pred_end()); 15706c3fb27SDimitry Andric for (MachineInstr &Phi : make_early_inc_range(BB.phis())) { 15806c3fb27SDimitry Andric for (unsigned i = Phi.getNumOperands() - 1; i >= 2; i -= 2) { 15906c3fb27SDimitry Andric if (!preds.count(Phi.getOperand(i).getMBB())) { 16006c3fb27SDimitry Andric Phi.removeOperand(i); 16106c3fb27SDimitry Andric Phi.removeOperand(i - 1); 1620b57cec5SDimitry Andric ModifiedPHI = true; 1630b57cec5SDimitry Andric } 16406c3fb27SDimitry Andric } 1650b57cec5SDimitry Andric 16606c3fb27SDimitry Andric if (Phi.getNumOperands() == 3) { 16706c3fb27SDimitry Andric const MachineOperand &Input = Phi.getOperand(1); 16806c3fb27SDimitry Andric const MachineOperand &Output = Phi.getOperand(0); 1698bcb0991SDimitry Andric Register InputReg = Input.getReg(); 1708bcb0991SDimitry Andric Register OutputReg = Output.getReg(); 1710b57cec5SDimitry Andric assert(Output.getSubReg() == 0 && "Cannot have output subregister"); 1720b57cec5SDimitry Andric ModifiedPHI = true; 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric if (InputReg != OutputReg) { 1750b57cec5SDimitry Andric MachineRegisterInfo &MRI = F.getRegInfo(); 1760b57cec5SDimitry Andric unsigned InputSub = Input.getSubReg(); 1770b57cec5SDimitry Andric if (InputSub == 0 && 1780b57cec5SDimitry Andric MRI.constrainRegClass(InputReg, MRI.getRegClass(OutputReg)) && 1790b57cec5SDimitry Andric !Input.isUndef()) { 1800b57cec5SDimitry Andric MRI.replaceRegWith(OutputReg, InputReg); 1810b57cec5SDimitry Andric } else { 1820b57cec5SDimitry Andric // The input register to the PHI has a subregister or it can't be 1830b57cec5SDimitry Andric // constrained to the proper register class or it is undef: 1840b57cec5SDimitry Andric // insert a COPY instead of simply replacing the output 1850b57cec5SDimitry Andric // with the input. 1860b57cec5SDimitry Andric const TargetInstrInfo *TII = F.getSubtarget().getInstrInfo(); 18706c3fb27SDimitry Andric BuildMI(BB, BB.getFirstNonPHI(), Phi.getDebugLoc(), 1880b57cec5SDimitry Andric TII->get(TargetOpcode::COPY), OutputReg) 1890b57cec5SDimitry Andric .addReg(InputReg, getRegState(Input), InputSub); 1900b57cec5SDimitry Andric } 19106c3fb27SDimitry Andric Phi.eraseFromParent(); 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric F.RenumberBlocks(); 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric return (!DeadBlocks.empty() || ModifiedPHI); 2000b57cec5SDimitry Andric } 201