Skip to content

Commit dc40be7

Browse files
author
Volkan Keles
committed
[llvm-extract] Support extracting basic blocks
Summary: Currently, there is no way to extract a basic block from a function easily. This patch extends llvm-extract to extract the specified basic block(s). Reviewers: loladiro, rafael, bogner Reviewed By: bogner Subscribers: hintonda, mgorny, qcolombet, llvm-commits Differential Revision: https://reviews.llvm.org/D41638 llvm-svn: 323266
1 parent bf3c398 commit dc40be7

File tree

14 files changed

+378
-159
lines changed

14 files changed

+378
-159
lines changed

llvm/include/llvm/InitializePasses.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ void initializeAtomicExpandPass(PassRegistry&);
7373
void initializeBDCELegacyPassPass(PassRegistry&);
7474
void initializeBarrierNoopPass(PassRegistry&);
7575
void initializeBasicAAWrapperPassPass(PassRegistry&);
76-
void initializeBlockExtractorPassPass(PassRegistry&);
76+
void initializeBlockExtractorPass(PassRegistry &);
7777
void initializeBlockFrequencyInfoWrapperPassPass(PassRegistry&);
7878
void initializeBoundsCheckingLegacyPassPass(PassRegistry&);
7979
void initializeBranchFolderPassPass(PassRegistry&);

llvm/include/llvm/Transforms/IPO.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,10 +179,13 @@ Pass *createLoopExtractorPass();
179179
///
180180
Pass *createSingleLoopExtractorPass();
181181

182-
/// createBlockExtractorPass - This pass extracts all blocks (except those
183-
/// specified in the argument list) from the functions in the module.
182+
/// createBlockExtractorPass - This pass extracts all the specified blocks
183+
/// from the functions in the module.
184184
///
185185
ModulePass *createBlockExtractorPass();
186+
ModulePass *
187+
createBlockExtractorPass(const SmallVectorImpl<BasicBlock *> &BlocksToExtract,
188+
bool EraseFunctions);
186189

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

llvm/lib/Transforms/IPO/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ add_llvm_library(LLVMipo
22
AlwaysInliner.cpp
33
ArgumentPromotion.cpp
44
BarrierNoopPass.cpp
5+
BlockExtractor.cpp
56
CalledValuePropagation.cpp
67
ConstantMerge.cpp
78
CrossDSOCFI.cpp

llvm/lib/Transforms/IPO/IPO.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ void llvm::initializeIPO(PassRegistry &Registry) {
4040
initializeInferFunctionAttrsLegacyPassPass(Registry);
4141
initializeInternalizeLegacyPassPass(Registry);
4242
initializeLoopExtractorPass(Registry);
43-
initializeBlockExtractorPassPass(Registry);
43+
initializeBlockExtractorPass(Registry);
4444
initializeSingleLoopExtractorPass(Registry);
4545
initializeLowerTypeTestsPass(Registry);
4646
initializeMergeFunctionsPass(Registry);

llvm/lib/Transforms/IPO/LoopExtractor.cpp

Lines changed: 0 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -158,155 +158,3 @@ bool LoopExtractor::runOnLoop(Loop *L, LPPassManager &LPM) {
158158
Pass *llvm::createSingleLoopExtractorPass() {
159159
return new SingleLoopExtractor();
160160
}
161-
162-
163-
// BlockFile - A file which contains a list of blocks that should not be
164-
// extracted.
165-
static cl::opt<std::string>
166-
BlockFile("extract-blocks-file", cl::value_desc("filename"),
167-
cl::desc("A file containing list of basic blocks to not extract"),
168-
cl::Hidden);
169-
170-
namespace {
171-
/// BlockExtractorPass - This pass is used by bugpoint to extract all blocks
172-
/// from the module into their own functions except for those specified by the
173-
/// BlocksToNotExtract list.
174-
class BlockExtractorPass : public ModulePass {
175-
void LoadFile(const char *Filename);
176-
void SplitLandingPadPreds(Function *F);
177-
178-
std::vector<BasicBlock*> BlocksToNotExtract;
179-
std::vector<std::pair<std::string, std::string> > BlocksToNotExtractByName;
180-
public:
181-
static char ID; // Pass identification, replacement for typeid
182-
BlockExtractorPass() : ModulePass(ID) {
183-
if (!BlockFile.empty())
184-
LoadFile(BlockFile.c_str());
185-
}
186-
187-
bool runOnModule(Module &M) override;
188-
};
189-
}
190-
191-
char BlockExtractorPass::ID = 0;
192-
INITIALIZE_PASS(BlockExtractorPass, "extract-blocks",
193-
"Extract Basic Blocks From Module (for bugpoint use)",
194-
false, false)
195-
196-
// createBlockExtractorPass - This pass extracts all blocks (except those
197-
// specified in the argument list) from the functions in the module.
198-
//
199-
ModulePass *llvm::createBlockExtractorPass() {
200-
return new BlockExtractorPass();
201-
}
202-
203-
void BlockExtractorPass::LoadFile(const char *Filename) {
204-
// Load the BlockFile...
205-
std::ifstream In(Filename);
206-
if (!In.good()) {
207-
errs() << "WARNING: BlockExtractor couldn't load file '" << Filename
208-
<< "'!\n";
209-
return;
210-
}
211-
while (In) {
212-
std::string FunctionName, BlockName;
213-
In >> FunctionName;
214-
In >> BlockName;
215-
if (!BlockName.empty())
216-
BlocksToNotExtractByName.push_back(
217-
std::make_pair(FunctionName, BlockName));
218-
}
219-
}
220-
221-
/// SplitLandingPadPreds - The landing pad needs to be extracted with the invoke
222-
/// instruction. The critical edge breaker will refuse to break critical edges
223-
/// to a landing pad. So do them here. After this method runs, all landing pads
224-
/// should have only one predecessor.
225-
void BlockExtractorPass::SplitLandingPadPreds(Function *F) {
226-
for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
227-
InvokeInst *II = dyn_cast<InvokeInst>(I);
228-
if (!II) continue;
229-
BasicBlock *Parent = II->getParent();
230-
BasicBlock *LPad = II->getUnwindDest();
231-
232-
// Look through the landing pad's predecessors. If one of them ends in an
233-
// 'invoke', then we want to split the landing pad.
234-
bool Split = false;
235-
for (pred_iterator
236-
PI = pred_begin(LPad), PE = pred_end(LPad); PI != PE; ++PI) {
237-
BasicBlock *BB = *PI;
238-
if (BB->isLandingPad() && BB != Parent &&
239-
isa<InvokeInst>(Parent->getTerminator())) {
240-
Split = true;
241-
break;
242-
}
243-
}
244-
245-
if (!Split) continue;
246-
247-
SmallVector<BasicBlock*, 2> NewBBs;
248-
SplitLandingPadPredecessors(LPad, Parent, ".1", ".2", NewBBs);
249-
}
250-
}
251-
252-
bool BlockExtractorPass::runOnModule(Module &M) {
253-
if (skipModule(M))
254-
return false;
255-
256-
std::set<BasicBlock*> TranslatedBlocksToNotExtract;
257-
for (unsigned i = 0, e = BlocksToNotExtract.size(); i != e; ++i) {
258-
BasicBlock *BB = BlocksToNotExtract[i];
259-
Function *F = BB->getParent();
260-
261-
// Map the corresponding function in this module.
262-
Function *MF = M.getFunction(F->getName());
263-
assert(MF->getFunctionType() == F->getFunctionType() && "Wrong function?");
264-
265-
// Figure out which index the basic block is in its function.
266-
Function::iterator BBI = MF->begin();
267-
std::advance(BBI, std::distance(F->begin(), Function::iterator(BB)));
268-
TranslatedBlocksToNotExtract.insert(&*BBI);
269-
}
270-
271-
while (!BlocksToNotExtractByName.empty()) {
272-
// There's no way to find BBs by name without looking at every BB inside
273-
// every Function. Fortunately, this is always empty except when used by
274-
// bugpoint in which case correctness is more important than performance.
275-
276-
std::string &FuncName = BlocksToNotExtractByName.back().first;
277-
std::string &BlockName = BlocksToNotExtractByName.back().second;
278-
279-
for (Function &F : M) {
280-
if (F.getName() != FuncName) continue;
281-
282-
for (BasicBlock &BB : F) {
283-
if (BB.getName() != BlockName) continue;
284-
285-
TranslatedBlocksToNotExtract.insert(&BB);
286-
}
287-
}
288-
289-
BlocksToNotExtractByName.pop_back();
290-
}
291-
292-
// Now that we know which blocks to not extract, figure out which ones we WANT
293-
// to extract.
294-
std::vector<BasicBlock*> BlocksToExtract;
295-
for (Function &F : M) {
296-
SplitLandingPadPreds(&F);
297-
for (BasicBlock &BB : F)
298-
if (!TranslatedBlocksToNotExtract.count(&BB))
299-
BlocksToExtract.push_back(&BB);
300-
}
301-
302-
for (BasicBlock *BlockToExtract : BlocksToExtract) {
303-
SmallVector<BasicBlock*, 2> BlocksToExtractVec;
304-
BlocksToExtractVec.push_back(BlockToExtract);
305-
if (const InvokeInst *II =
306-
dyn_cast<InvokeInst>(BlockToExtract->getTerminator()))
307-
BlocksToExtractVec.push_back(II->getUnwindDest());
308-
CodeExtractor(BlocksToExtractVec).extractCodeRegion();
309-
}
310-
311-
return !BlocksToExtract.empty();
312-
}

0 commit comments

Comments
 (0)