LLVM 24.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 bool 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.
97bool BlockExtractor::splitLandingPadPreds(Function &F) {
98 bool Changed = false;
99 for (BasicBlock &BB : F) {
100 for (Instruction &I : BB) {
101 if (!isa<InvokeInst>(&I))
102 continue;
103 InvokeInst *II = cast<InvokeInst>(&I);
104 BasicBlock *Parent = II->getParent();
105 BasicBlock *LPad = II->getUnwindDest();
106
107 // Look through the landing pad's predecessors. If one of them ends in an
108 // 'invoke', then we want to split the landing pad.
109 bool Split = false;
110 for (auto *PredBB : predecessors(LPad)) {
111 if (PredBB->isLandingPad() && PredBB != Parent &&
112 isa<InvokeInst>(Parent->getTerminator())) {
113 Split = true;
114 break;
115 }
116 }
117
118 if (!Split)
119 continue;
120
122 SplitLandingPadPredecessors(LPad, Parent, ".1", ".2", NewBBs);
123 Changed = true;
124 }
125 }
126 return Changed;
127}
128
129bool BlockExtractor::runOnModule(Module &M) {
130 bool Changed = false;
131
132 // Get all the functions.
134 for (Function &F : M) {
135 Changed |= splitLandingPadPreds(F);
136 Functions.push_back(&F);
137 }
138
139 // Get all the blocks specified in the input file.
140 unsigned NextGroupIdx = GroupsOfBlocks.size();
141 GroupsOfBlocks.resize(NextGroupIdx + BlocksByName.size());
142 for (const auto &BInfo : BlocksByName) {
143 Function *F = M.getFunction(BInfo.first);
144 if (!F)
146 "Invalid function name specified in the input file");
147 for (const auto &BBInfo : BInfo.second) {
148 auto Res = llvm::find_if(
149 *F, [&](const BasicBlock &BB) { return BB.getName() == BBInfo; });
150 if (Res == F->end())
151 reportFatalUsageError("Invalid block name specified in the input file");
152 GroupsOfBlocks[NextGroupIdx].push_back(&*Res);
153 }
154 ++NextGroupIdx;
155 }
156
157 // Extract each group of basic blocks.
158 for (auto &BBs : GroupsOfBlocks) {
159 SmallVector<BasicBlock *, 32> BlocksToExtractVec;
160 for (BasicBlock *BB : BBs) {
161 // Check if the module contains BB.
162 if (BB->getParent()->getParent() != &M)
163 reportFatalUsageError("Invalid basic block");
164 LLVM_DEBUG(dbgs() << "BlockExtractor: Extracting "
165 << BB->getParent()->getName() << ":" << BB->getName()
166 << "\n");
167 BlocksToExtractVec.push_back(BB);
168 if (const InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator()))
169 BlocksToExtractVec.push_back(II->getUnwindDest());
170 ++NumExtracted;
171 Changed = true;
172 }
173 CodeExtractorAnalysisCache CEAC(*BBs[0]->getParent());
174 Function *F = CodeExtractor(BlocksToExtractVec).extractCodeRegion(CEAC);
175 if (F)
176 LLVM_DEBUG(dbgs() << "Extracted group '" << (*BBs.begin())->getName()
177 << "' in: " << F->getName() << '\n');
178 else
179 LLVM_DEBUG(dbgs() << "Failed to extract for group '"
180 << (*BBs.begin())->getName() << "'\n");
181 }
182
183 // Erase the functions.
184 if (EraseFunctions || BlockExtractorEraseFuncs) {
185 for (Function *F : Functions) {
186 LLVM_DEBUG(dbgs() << "BlockExtractor: Trying to delete " << F->getName()
187 << "\n");
188 F->deleteBody();
189 }
190 // Set linkage as ExternalLinkage to avoid erasing unreachable functions.
191 for (Function &F : M)
193 Changed = true;
194 }
195
196 return Changed;
197}
198
200 std::vector<std::vector<BasicBlock *>> &&GroupsOfBlocks,
201 bool EraseFunctions)
202 : GroupsOfBlocks(std::move(GroupsOfBlocks)),
203 EraseFunctions(EraseFunctions) {}
204
207 BlockExtractor BE(EraseFunctions);
208 BE.init(GroupsOfBlocks);
209 return BE.runOnModule(M) ? PreservedAnalyses::none()
211}
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:54
#define I(x, y, z)
Definition MD5.cpp:57
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:119
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; assumes that the block is well-formed.
Definition BasicBlock.h:237
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:319
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:643
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
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:547
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...
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1917
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
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:1772
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:177
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
LLVM_ABI BlockExtractorPass(std::vector< std::vector< BasicBlock * > > &&GroupsOfBlocks, bool EraseFunctions)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)