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 "IPOOptions.h"
16#include "llvm/ADT/STLExtras.h"
17#include "llvm/ADT/Statistic.h"
19#include "llvm/IR/Module.h"
20#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
33namespace {
34class BlockExtractor {
35public:
36 BlockExtractor(const IPOOptions &Opts, bool EraseFunctions)
37 : Opts(Opts), EraseFunctions(EraseFunctions) {}
38 bool runOnModule(Module &M);
39 void
40 init(const std::vector<std::vector<BasicBlock *>> &GroupsOfBlocksToExtract) {
41 GroupsOfBlocks = GroupsOfBlocksToExtract;
42 if (!Opts.extract_blocks_file.empty())
43 loadFile();
44 }
45
46private:
47 const IPOOptions &Opts;
48 std::vector<std::vector<BasicBlock *>> GroupsOfBlocks;
49 bool EraseFunctions;
50 /// Map a function name to groups of blocks.
52 BlocksByName;
53
54 void loadFile();
55 bool splitLandingPadPreds(Function &F);
56};
57
58} // end anonymous namespace
59
60/// Gets all of the blocks specified in the input file.
61void BlockExtractor::loadFile() {
62 auto ErrOrBuf = MemoryBuffer::getFile(Opts.extract_blocks_file);
63 if (ErrOrBuf.getError())
64 report_fatal_error("BlockExtractor couldn't load the file.");
65 // Read the file.
66 auto &Buf = *ErrOrBuf;
67 SmallVector<StringRef, 16> Lines;
68 Buf->getBuffer().split(Lines, '\n', /*MaxSplit=*/-1,
69 /*KeepEmpty=*/false);
70 for (const auto &Line : Lines) {
72 Line.split(LineSplit, ' ', /*MaxSplit=*/-1,
73 /*KeepEmpty=*/false);
74 if (LineSplit.empty())
75 continue;
76 if (LineSplit.size()!=2)
78 "Invalid line format, expecting lines like: 'funcname bb1[;bb2..]'");
80 LineSplit[1].split(BBNames, ';', /*MaxSplit=*/-1,
81 /*KeepEmpty=*/false);
82 if (BBNames.empty())
83 report_fatal_error("Missing bbs name");
84 BlocksByName.push_back(
85 {std::string(LineSplit[0]), {BBNames.begin(), BBNames.end()}});
86 }
87}
88
89/// Extracts the landing pads to make sure all of them have only one
90/// predecessor.
91bool BlockExtractor::splitLandingPadPreds(Function &F) {
92 bool Changed = false;
93 for (BasicBlock &BB : F) {
94 for (Instruction &I : BB) {
95 if (!isa<InvokeInst>(&I))
96 continue;
97 InvokeInst *II = cast<InvokeInst>(&I);
98 BasicBlock *Parent = II->getParent();
99 BasicBlock *LPad = II->getUnwindDest();
100
101 // Look through the landing pad's predecessors. If one of them ends in an
102 // 'invoke', then we want to split the landing pad.
103 bool Split = false;
104 for (auto *PredBB : predecessors(LPad)) {
105 if (PredBB->isLandingPad() && PredBB != Parent &&
106 isa<InvokeInst>(Parent->getTerminator())) {
107 Split = true;
108 break;
109 }
110 }
111
112 if (!Split)
113 continue;
114
116 SplitLandingPadPredecessors(LPad, Parent, ".1", ".2", NewBBs);
117 Changed = true;
118 }
119 }
120 return Changed;
121}
122
123bool BlockExtractor::runOnModule(Module &M) {
124 bool Changed = false;
125
126 // Get all the functions.
128 for (Function &F : M) {
129 Changed |= splitLandingPadPreds(F);
130 Functions.push_back(&F);
131 }
132
133 // Get all the blocks specified in the input file.
134 unsigned NextGroupIdx = GroupsOfBlocks.size();
135 GroupsOfBlocks.resize(NextGroupIdx + BlocksByName.size());
136 for (const auto &BInfo : BlocksByName) {
137 Function *F = M.getFunction(BInfo.first);
138 if (!F)
140 "Invalid function name specified in the input file");
141 for (const auto &BBInfo : BInfo.second) {
142 auto Res = llvm::find_if(
143 *F, [&](const BasicBlock &BB) { return BB.getName() == BBInfo; });
144 if (Res == F->end())
145 reportFatalUsageError("Invalid block name specified in the input file");
146 GroupsOfBlocks[NextGroupIdx].push_back(&*Res);
147 }
148 ++NextGroupIdx;
149 }
150
151 // Extract each group of basic blocks.
152 for (auto &BBs : GroupsOfBlocks) {
153 SmallVector<BasicBlock *, 32> BlocksToExtractVec;
154 for (BasicBlock *BB : BBs) {
155 // Check if the module contains BB.
156 if (BB->getParent()->getParent() != &M)
157 reportFatalUsageError("Invalid basic block");
158 LLVM_DEBUG(dbgs() << "BlockExtractor: Extracting "
159 << BB->getParent()->getName() << ":" << BB->getName()
160 << "\n");
161 BlocksToExtractVec.push_back(BB);
162 if (const InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator()))
163 BlocksToExtractVec.push_back(II->getUnwindDest());
164 ++NumExtracted;
165 Changed = true;
166 }
167 CodeExtractorAnalysisCache CEAC(*BBs[0]->getParent());
168 Function *F = CodeExtractor(BlocksToExtractVec).extractCodeRegion(CEAC);
169 if (F)
170 LLVM_DEBUG(dbgs() << "Extracted group '" << (*BBs.begin())->getName()
171 << "' in: " << F->getName() << '\n');
172 else
173 LLVM_DEBUG(dbgs() << "Failed to extract for group '"
174 << (*BBs.begin())->getName() << "'\n");
175 }
176
177 // Erase the functions.
178 if (EraseFunctions || Opts.extract_blocks_erase_funcs) {
179 for (Function *F : Functions) {
180 LLVM_DEBUG(dbgs() << "BlockExtractor: Trying to delete " << F->getName()
181 << "\n");
182 F->deleteBody();
183 }
184 // Set linkage as ExternalLinkage to avoid erasing unreachable functions.
185 for (Function &F : M)
187 Changed = true;
188 }
189
190 return Changed;
191}
192
194 std::vector<std::vector<BasicBlock *>> &&GroupsOfBlocks,
195 bool EraseFunctions)
196 : GroupsOfBlocks(std::move(GroupsOfBlocks)),
197 EraseFunctions(EraseFunctions) {}
198
201 BlockExtractor BE(getIPOOptions(M), EraseFunctions);
202 BE.init(GroupsOfBlocks);
203 return BE.runOnModule(M) ? PreservedAnalyses::none()
205}
static const Function * getParent(const Value *V)
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:68
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:314
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:83
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
const IPOOptions & getIPOOptions(const LLVMContext &C)
Definition IPOOptions.h:33
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:1933
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:1788
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)