1dc40be75SVolkan Keles //===- BlockExtractor.cpp - Extracts blocks into their own functions ------===// 2dc40be75SVolkan Keles // 3dc40be75SVolkan Keles // The LLVM Compiler Infrastructure 4dc40be75SVolkan Keles // 5dc40be75SVolkan Keles // This file is distributed under the University of Illinois Open Source 6dc40be75SVolkan Keles // License. See LICENSE.TXT for details. 7dc40be75SVolkan Keles // 8dc40be75SVolkan Keles //===----------------------------------------------------------------------===// 9dc40be75SVolkan Keles // 10dc40be75SVolkan Keles // This pass extracts the specified basic blocks from the module into their 11dc40be75SVolkan Keles // own functions. 12dc40be75SVolkan Keles // 13dc40be75SVolkan Keles //===----------------------------------------------------------------------===// 14dc40be75SVolkan Keles 15dc40be75SVolkan Keles #include "llvm/ADT/STLExtras.h" 16dc40be75SVolkan Keles #include "llvm/ADT/Statistic.h" 17dc40be75SVolkan Keles #include "llvm/IR/Instructions.h" 18dc40be75SVolkan Keles #include "llvm/IR/Module.h" 19dc40be75SVolkan Keles #include "llvm/Pass.h" 20dc40be75SVolkan Keles #include "llvm/Support/CommandLine.h" 21dc40be75SVolkan Keles #include "llvm/Support/Debug.h" 22dc40be75SVolkan Keles #include "llvm/Support/MemoryBuffer.h" 23dc40be75SVolkan Keles #include "llvm/Transforms/IPO.h" 24dc40be75SVolkan Keles #include "llvm/Transforms/Utils/BasicBlockUtils.h" 25dc40be75SVolkan Keles #include "llvm/Transforms/Utils/CodeExtractor.h" 26dc40be75SVolkan Keles using namespace llvm; 27dc40be75SVolkan Keles 28dc40be75SVolkan Keles #define DEBUG_TYPE "block-extractor" 29dc40be75SVolkan Keles 30dc40be75SVolkan Keles STATISTIC(NumExtracted, "Number of basic blocks extracted"); 31dc40be75SVolkan Keles 32dc40be75SVolkan Keles static cl::opt<std::string> BlockExtractorFile( 33dc40be75SVolkan Keles "extract-blocks-file", cl::value_desc("filename"), 34dc40be75SVolkan Keles cl::desc("A file containing list of basic blocks to extract"), cl::Hidden); 35dc40be75SVolkan Keles 36dc40be75SVolkan Keles cl::opt<bool> BlockExtractorEraseFuncs("extract-blocks-erase-funcs", 37dc40be75SVolkan Keles cl::desc("Erase the existing functions"), 38dc40be75SVolkan Keles cl::Hidden); 39dc40be75SVolkan Keles 40dc40be75SVolkan Keles namespace { 41dc40be75SVolkan Keles class BlockExtractor : public ModulePass { 42dc40be75SVolkan Keles SmallVector<BasicBlock *, 16> Blocks; 43dc40be75SVolkan Keles bool EraseFunctions; 44dc40be75SVolkan Keles SmallVector<std::pair<std::string, std::string>, 32> BlocksByName; 45dc40be75SVolkan Keles 46dc40be75SVolkan Keles public: 47dc40be75SVolkan Keles static char ID; 48dc40be75SVolkan Keles BlockExtractor(const SmallVectorImpl<BasicBlock *> &BlocksToExtract, 49dc40be75SVolkan Keles bool EraseFunctions) 50dc40be75SVolkan Keles : ModulePass(ID), Blocks(BlocksToExtract.begin(), BlocksToExtract.end()), 51dc40be75SVolkan Keles EraseFunctions(EraseFunctions) { 52dc40be75SVolkan Keles if (!BlockExtractorFile.empty()) 53dc40be75SVolkan Keles loadFile(); 54dc40be75SVolkan Keles } 55dc40be75SVolkan Keles BlockExtractor() : BlockExtractor(SmallVector<BasicBlock *, 0>(), false) {} 56dc40be75SVolkan Keles bool runOnModule(Module &M) override; 57dc40be75SVolkan Keles 58dc40be75SVolkan Keles private: 59dc40be75SVolkan Keles void loadFile(); 60dc40be75SVolkan Keles void splitLandingPadPreds(Function &F); 61dc40be75SVolkan Keles }; 62dc40be75SVolkan Keles } // end anonymous namespace 63dc40be75SVolkan Keles 64dc40be75SVolkan Keles char BlockExtractor::ID = 0; 65dc40be75SVolkan Keles INITIALIZE_PASS(BlockExtractor, "extract-blocks", 66dc40be75SVolkan Keles "Extract basic blocks from module", false, false) 67dc40be75SVolkan Keles 68dc40be75SVolkan Keles ModulePass *llvm::createBlockExtractorPass() { return new BlockExtractor(); } 69dc40be75SVolkan Keles ModulePass *llvm::createBlockExtractorPass( 70dc40be75SVolkan Keles const SmallVectorImpl<BasicBlock *> &BlocksToExtract, bool EraseFunctions) { 71dc40be75SVolkan Keles return new BlockExtractor(BlocksToExtract, EraseFunctions); 72dc40be75SVolkan Keles } 73dc40be75SVolkan Keles 74dc40be75SVolkan Keles /// Gets all of the blocks specified in the input file. 75dc40be75SVolkan Keles void BlockExtractor::loadFile() { 76dc40be75SVolkan Keles auto ErrOrBuf = MemoryBuffer::getFile(BlockExtractorFile); 77*ebf34ea3SVolkan Keles if (ErrOrBuf.getError()) 78dc40be75SVolkan Keles report_fatal_error("BlockExtractor couldn't load the file."); 79dc40be75SVolkan Keles // Read the file. 80dc40be75SVolkan Keles auto &Buf = *ErrOrBuf; 81dc40be75SVolkan Keles SmallVector<StringRef, 16> Lines; 82dc40be75SVolkan Keles Buf->getBuffer().split(Lines, '\n', /*MaxSplit=*/-1, 83dc40be75SVolkan Keles /*KeepEmpty=*/false); 84dc40be75SVolkan Keles for (const auto &Line : Lines) { 85dc40be75SVolkan Keles auto FBPair = Line.split(' '); 86dc40be75SVolkan Keles BlocksByName.push_back({FBPair.first, FBPair.second}); 87dc40be75SVolkan Keles } 88dc40be75SVolkan Keles } 89dc40be75SVolkan Keles 90dc40be75SVolkan Keles /// Extracts the landing pads to make sure all of them have only one 91dc40be75SVolkan Keles /// predecessor. 92dc40be75SVolkan Keles void BlockExtractor::splitLandingPadPreds(Function &F) { 93dc40be75SVolkan Keles for (BasicBlock &BB : F) { 94dc40be75SVolkan Keles for (Instruction &I : BB) { 95dc40be75SVolkan Keles if (!isa<InvokeInst>(&I)) 96dc40be75SVolkan Keles continue; 97dc40be75SVolkan Keles InvokeInst *II = cast<InvokeInst>(&I); 98dc40be75SVolkan Keles BasicBlock *Parent = II->getParent(); 99dc40be75SVolkan Keles BasicBlock *LPad = II->getUnwindDest(); 100dc40be75SVolkan Keles 101dc40be75SVolkan Keles // Look through the landing pad's predecessors. If one of them ends in an 102dc40be75SVolkan Keles // 'invoke', then we want to split the landing pad. 103dc40be75SVolkan Keles bool Split = false; 104dc40be75SVolkan Keles for (auto PredBB : predecessors(LPad)) { 105dc40be75SVolkan Keles if (PredBB->isLandingPad() && PredBB != Parent && 106dc40be75SVolkan Keles isa<InvokeInst>(Parent->getTerminator())) { 107dc40be75SVolkan Keles Split = true; 108dc40be75SVolkan Keles break; 109dc40be75SVolkan Keles } 110dc40be75SVolkan Keles } 111dc40be75SVolkan Keles 112dc40be75SVolkan Keles if (!Split) 113dc40be75SVolkan Keles continue; 114dc40be75SVolkan Keles 115dc40be75SVolkan Keles SmallVector<BasicBlock *, 2> NewBBs; 116dc40be75SVolkan Keles SplitLandingPadPredecessors(LPad, Parent, ".1", ".2", NewBBs); 117dc40be75SVolkan Keles } 118dc40be75SVolkan Keles } 119dc40be75SVolkan Keles } 120dc40be75SVolkan Keles 121dc40be75SVolkan Keles bool BlockExtractor::runOnModule(Module &M) { 122dc40be75SVolkan Keles 123dc40be75SVolkan Keles bool Changed = false; 124dc40be75SVolkan Keles 125dc40be75SVolkan Keles // Get all the functions. 126dc40be75SVolkan Keles SmallVector<Function *, 4> Functions; 127dc40be75SVolkan Keles for (Function &F : M) { 128dc40be75SVolkan Keles splitLandingPadPreds(F); 129dc40be75SVolkan Keles Functions.push_back(&F); 130dc40be75SVolkan Keles } 131dc40be75SVolkan Keles 132dc40be75SVolkan Keles // Get all the blocks specified in the input file. 133dc40be75SVolkan Keles for (const auto &BInfo : BlocksByName) { 134dc40be75SVolkan Keles Function *F = M.getFunction(BInfo.first); 135dc40be75SVolkan Keles if (!F) 136dc40be75SVolkan Keles report_fatal_error("Invalid function name specified in the input file"); 137dc40be75SVolkan Keles auto Res = llvm::find_if(*F, [&](const BasicBlock &BB) { 138dc40be75SVolkan Keles return BB.getName().equals(BInfo.second); 139dc40be75SVolkan Keles }); 140dc40be75SVolkan Keles if (Res == F->end()) 141dc40be75SVolkan Keles report_fatal_error("Invalid block name specified in the input file"); 142dc40be75SVolkan Keles Blocks.push_back(&*Res); 143dc40be75SVolkan Keles } 144dc40be75SVolkan Keles 145dc40be75SVolkan Keles // Extract basic blocks. 146dc40be75SVolkan Keles for (BasicBlock *BB : Blocks) { 147dc40be75SVolkan Keles // Check if the module contains BB. 148dc40be75SVolkan Keles if (BB->getParent()->getParent() != &M) 149dc40be75SVolkan Keles report_fatal_error("Invalid basic block"); 150dc40be75SVolkan Keles DEBUG(dbgs() << "BlockExtractor: Extracting " << BB->getParent()->getName() 151dc40be75SVolkan Keles << ":" << BB->getName() << "\n"); 152dc40be75SVolkan Keles SmallVector<BasicBlock *, 2> BlocksToExtractVec; 153dc40be75SVolkan Keles BlocksToExtractVec.push_back(BB); 154dc40be75SVolkan Keles if (const InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) 155dc40be75SVolkan Keles BlocksToExtractVec.push_back(II->getUnwindDest()); 156dc40be75SVolkan Keles CodeExtractor(BlocksToExtractVec).extractCodeRegion(); 157dc40be75SVolkan Keles ++NumExtracted; 158dc40be75SVolkan Keles Changed = true; 159dc40be75SVolkan Keles } 160dc40be75SVolkan Keles 161dc40be75SVolkan Keles // Erase the functions. 162dc40be75SVolkan Keles if (EraseFunctions || BlockExtractorEraseFuncs) { 163dc40be75SVolkan Keles for (Function *F : Functions) { 164dc40be75SVolkan Keles DEBUG(dbgs() << "BlockExtractor: Deleting " << F->getName() << "\n"); 165dc40be75SVolkan Keles F->eraseFromParent(); 166dc40be75SVolkan Keles } 167dc40be75SVolkan Keles // Set linkage as ExternalLinkage to avoid erasing unreachable functions. 168dc40be75SVolkan Keles for (Function &F : M) 169dc40be75SVolkan Keles F.setLinkage(GlobalValue::ExternalLinkage); 170dc40be75SVolkan Keles Changed = true; 171dc40be75SVolkan Keles } 172dc40be75SVolkan Keles 173dc40be75SVolkan Keles return Changed; 174dc40be75SVolkan Keles } 175