LLVM 22.0.0git
BlockExtractor.cpp
Go to the documentation of this file.
1//===- BlockExtractor.cpp - Extracts blocks into their own functions ------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This pass extracts the specified basic blocks from the module into their
10// own functions.
11//
12//===----------------------------------------------------------------------===//
13
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/Statistic.h"
18#include "llvm/IR/Module.h"
19#include "llvm/IR/PassManager.h"
21#include "llvm/Support/Debug.h"
23#include "llvm/Transforms/IPO.h"
26
27using namespace llvm;
28
29#define DEBUG_TYPE "block-extractor"
30
31STATISTIC(NumExtracted, "Number of basic blocks extracted");
32
34 "extract-blocks-file", cl::value_desc("filename"),
35 cl::desc("A file containing list of basic blocks to extract"), cl::Hidden);
36
37static cl::opt<bool>
38 BlockExtractorEraseFuncs("extract-blocks-erase-funcs",
39 cl::desc("Erase the existing functions"),
41namespace {
42class BlockExtractor {
43public:
44 BlockExtractor(bool EraseFunctions) : EraseFunctions(EraseFunctions) {}
45 bool runOnModule(Module &M);
46 void
47 init(const std::vector<std::vector<BasicBlock *>> &GroupsOfBlocksToExtract) {
48 GroupsOfBlocks = GroupsOfBlocksToExtract;
49 if (!BlockExtractorFile.empty())
50 loadFile();
51 }
52
53private:
54 std::vector<std::vector<BasicBlock *>> GroupsOfBlocks;
55 bool EraseFunctions;
56 /// Map a function name to groups of blocks.
58 BlocksByName;
59
60 void loadFile();
61 void splitLandingPadPreds(Function &F);
62};
63
64} // end anonymous namespace
65
66/// Gets all of the blocks specified in the input file.
67void BlockExtractor::loadFile() {
69 if (ErrOrBuf.getError())
70 report_fatal_error("BlockExtractor couldn't load the file.");
71 // Read the file.
72 auto &Buf = *ErrOrBuf;
73 SmallVector<StringRef, 16> Lines;
74 Buf->getBuffer().split(Lines, '\n', /*MaxSplit=*/-1,
75 /*KeepEmpty=*/false);
76 for (const auto &Line : Lines) {
78 Line.split(LineSplit, ' ', /*MaxSplit=*/-1,
79 /*KeepEmpty=*/false);
80 if (LineSplit.empty())
81 continue;
82 if (LineSplit.size()!=2)
84 "Invalid line format, expecting lines like: 'funcname bb1[;bb2..]'");
86 LineSplit[1].split(BBNames, ';', /*MaxSplit=*/-1,
87 /*KeepEmpty=*/false);
88 if (BBNames.empty())
89 report_fatal_error("Missing bbs name");
90 BlocksByName.push_back(
91 {std::string(LineSplit[0]), {BBNames.begin(), BBNames.end()}});
92 }
93}
94
95/// Extracts the landing pads to make sure all of them have only one
96/// predecessor.
97void BlockExtractor::splitLandingPadPreds(Function &F) {
98 for (BasicBlock &BB : F) {
99 for (Instruction &I : BB) {
100 if (!isa<InvokeInst>(&I))
101 continue;
102 InvokeInst *II = cast<InvokeInst>(&I);
103 BasicBlock *Parent = II->getParent();
104 BasicBlock *LPad = II->getUnwindDest();
105
106 // Look through the landing pad's predecessors. If one of them ends in an
107 // 'invoke', then we want to split the landing pad.
108 bool Split = false;
109 for (auto *PredBB : predecessors(LPad)) {
110 if (PredBB->isLandingPad() && PredBB != Parent &&
111 isa<InvokeInst>(Parent->getTerminator())) {
112 Split = true;
113 break;
114 }
115 }
116
117 if (!Split)
118 continue;
119
121 SplitLandingPadPredecessors(LPad, Parent, ".1", ".2", NewBBs);
122 }
123 }
124}
125
126bool BlockExtractor::runOnModule(Module &M) {
127 bool Changed = false;
128
129 // Get all the functions.
131 for (Function &F : M) {
132 splitLandingPadPreds(F);
133 Functions.push_back(&F);
134 }
135
136 // Get all the blocks specified in the input file.
137 unsigned NextGroupIdx = GroupsOfBlocks.size();
138 GroupsOfBlocks.resize(NextGroupIdx + BlocksByName.size());
139 for (const auto &BInfo : BlocksByName) {
140 Function *F = M.getFunction(BInfo.first);
141 if (!F)
143 "Invalid function name specified in the input file");
144 for (const auto &BBInfo : BInfo.second) {
145 auto Res = llvm::find_if(
146 *F, [&](const BasicBlock &BB) { return BB.getName() == BBInfo; });
147 if (Res == F->end())
148 reportFatalUsageError("Invalid block name specified in the input file");
149 GroupsOfBlocks[NextGroupIdx].push_back(&*Res);
150 }
151 ++NextGroupIdx;
152 }
153
154 // Extract each group of basic blocks.
155 for (auto &BBs : GroupsOfBlocks) {
156 SmallVector<BasicBlock *, 32> BlocksToExtractVec;
157 for (BasicBlock *BB : BBs) {
158 // Check if the module contains BB.
159 if (BB->getParent()->getParent() != &M)
160 reportFatalUsageError("Invalid basic block");
161 LLVM_DEBUG(dbgs() << "BlockExtractor: Extracting "
162 << BB->getParent()->getName() << ":" << BB->getName()
163 << "\n");
164 BlocksToExtractVec.push_back(BB);
165 if (const InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator()))
166 BlocksToExtractVec.push_back(II->getUnwindDest());
167 ++NumExtracted;
168 Changed = true;
169 }
170 CodeExtractorAnalysisCache CEAC(*BBs[0]->getParent());
171 Function *F = CodeExtractor(BlocksToExtractVec).extractCodeRegion(CEAC);
172 if (F)
173 LLVM_DEBUG(dbgs() << "Extracted group '" << (*BBs.begin())->getName()
174 << "' in: " << F->getName() << '\n');
175 else
176 LLVM_DEBUG(dbgs() << "Failed to extract for group '"
177 << (*BBs.begin())->getName() << "'\n");
178 }
179
180 // Erase the functions.
181 if (EraseFunctions || BlockExtractorEraseFuncs) {
182 for (Function *F : Functions) {
183 LLVM_DEBUG(dbgs() << "BlockExtractor: Trying to delete " << F->getName()
184 << "\n");
185 F->deleteBody();
186 }
187 // Set linkage as ExternalLinkage to avoid erasing unreachable functions.
188 for (Function &F : M)
190 Changed = true;
191 }
192
193 return Changed;
194}
195
197 std::vector<std::vector<BasicBlock *>> &&GroupsOfBlocks,
198 bool EraseFunctions)
199 : GroupsOfBlocks(GroupsOfBlocks), EraseFunctions(EraseFunctions) {}
200
203 BlockExtractor BE(EraseFunctions);
204 BE.init(GroupsOfBlocks);
205 return BE.runOnModule(M) ? PreservedAnalyses::none()
207}
static const Function * getParent(const Value *V)
static cl::opt< std::string > BlockExtractorFile("extract-blocks-file", cl::value_desc("filename"), cl::desc("A file containing list of basic blocks to extract"), cl::Hidden)
static cl::opt< bool > BlockExtractorEraseFuncs("extract-blocks-erase-funcs", cl::desc("Erase the existing functions"), cl::Hidden)
static std::unique_ptr< Module > loadFile(const std::string &FileName, LLVMContext &Context)
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition MD5.cpp:55
#define I(x, y, z)
Definition MD5.cpp:58
Machine Check Debug Module
uint64_t IntrinsicInst * II
This file contains some templates that are useful if you are working with the STL at all.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:114
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Definition BasicBlock.h:233
Module * getParent()
Get the module that this global value is contained inside of...
@ ExternalLinkage
Externally visible function.
Definition GlobalValue.h:53
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
void push_back(const T &Elt)
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:322
Changed
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:81
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:649
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:548
LLVM_ABI void SplitLandingPadPredecessors(BasicBlock *OrigBB, ArrayRef< BasicBlock * > Preds, const char *Suffix, const char *Suffix2, SmallVectorImpl< BasicBlock * > &NewBBs, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool PreserveLCSSA=false)
This method transforms the landing pad, OrigBB, by introducing two new basic blocks into the function...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:565
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1738
auto predecessors(const MachineBasicBlock *BB)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:180
LLVM_ABI BlockExtractorPass(std::vector< std::vector< BasicBlock * > > &&GroupsOfBlocks, bool EraseFunctions)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)