Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Transforms/IPO/BlockExtractor.cpp
Line
Count
Source (jump to first uncovered line)
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
14
#include "llvm/ADT/STLExtras.h"
15
#include "llvm/ADT/Statistic.h"
16
#include "llvm/IR/Instructions.h"
17
#include "llvm/IR/Module.h"
18
#include "llvm/Pass.h"
19
#include "llvm/Support/CommandLine.h"
20
#include "llvm/Support/Debug.h"
21
#include "llvm/Support/MemoryBuffer.h"
22
#include "llvm/Transforms/IPO.h"
23
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
24
#include "llvm/Transforms/Utils/CodeExtractor.h"
25
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
namespace {
40
class BlockExtractor : public ModulePass {
41
  SmallVector<SmallVector<BasicBlock *, 16>, 4> GroupsOfBlocks;
42
  bool EraseFunctions;
43
  /// Map a function name to groups of blocks.
44
  SmallVector<std::pair<std::string, SmallVector<std::string, 4>>, 4>
45
      BlocksByName;
46
47
  void init(const SmallVectorImpl<SmallVector<BasicBlock *, 16>>
48
10
                &GroupsOfBlocksToExtract) {
49
10
    for (const SmallVectorImpl<BasicBlock *> &GroupOfBlocks :
50
10
         GroupsOfBlocksToExtract) {
51
5
      SmallVector<BasicBlock *, 16> NewGroup;
52
5
      NewGroup.append(GroupOfBlocks.begin(), GroupOfBlocks.end());
53
5
      GroupsOfBlocks.emplace_back(NewGroup);
54
5
    }
55
10
    if (!BlockExtractorFile.empty())
56
5
      loadFile();
57
10
  }
58
59
public:
60
  static char ID;
61
  BlockExtractor(const SmallVectorImpl<BasicBlock *> &BlocksToExtract,
62
                 bool EraseFunctions)
63
7
      : ModulePass(ID), EraseFunctions(EraseFunctions) {
64
7
    // We want one group per element of the input list.
65
7
    SmallVector<SmallVector<BasicBlock *, 16>, 4> MassagedGroupsOfBlocks;
66
7
    for (BasicBlock *BB : BlocksToExtract) {
67
0
      SmallVector<BasicBlock *, 16> NewGroup;
68
0
      NewGroup.push_back(BB);
69
0
      MassagedGroupsOfBlocks.push_back(NewGroup);
70
0
    }
71
7
    init(MassagedGroupsOfBlocks);
72
7
  }
73
74
  BlockExtractor(const SmallVectorImpl<SmallVector<BasicBlock *, 16>>
75
                     &GroupsOfBlocksToExtract,
76
                 bool EraseFunctions)
77
3
      : ModulePass(ID), EraseFunctions(EraseFunctions) {
78
3
    init(GroupsOfBlocksToExtract);
79
3
  }
80
81
7
  BlockExtractor() : BlockExtractor(SmallVector<BasicBlock *, 0>(), false) {}
82
  bool runOnModule(Module &M) override;
83
84
private:
85
  void loadFile();
86
  void splitLandingPadPreds(Function &F);
87
};
88
} // end anonymous namespace
89
90
char BlockExtractor::ID = 0;
91
INITIALIZE_PASS(BlockExtractor, "extract-blocks",
92
                "Extract basic blocks from module", false, false)
93
94
0
ModulePass *llvm::createBlockExtractorPass() { return new BlockExtractor(); }
95
ModulePass *llvm::createBlockExtractorPass(
96
0
    const SmallVectorImpl<BasicBlock *> &BlocksToExtract, bool EraseFunctions) {
97
0
  return new BlockExtractor(BlocksToExtract, EraseFunctions);
98
0
}
99
ModulePass *llvm::createBlockExtractorPass(
100
    const SmallVectorImpl<SmallVector<BasicBlock *, 16>>
101
        &GroupsOfBlocksToExtract,
102
3
    bool EraseFunctions) {
103
3
  return new BlockExtractor(GroupsOfBlocksToExtract, EraseFunctions);
104
3
}
105
106
/// Gets all of the blocks specified in the input file.
107
5
void BlockExtractor::loadFile() {
108
5
  auto ErrOrBuf = MemoryBuffer::getFile(BlockExtractorFile);
109
5
  if (ErrOrBuf.getError())
110
0
    report_fatal_error("BlockExtractor couldn't load the file.");
111
5
  // Read the file.
112
5
  auto &Buf = *ErrOrBuf;
113
5
  SmallVector<StringRef, 16> Lines;
114
5
  Buf->getBuffer().split(Lines, '\n', /*MaxSplit=*/-1,
115
5
                         /*KeepEmpty=*/false);
116
9
  for (const auto &Line : Lines) {
117
9
    SmallVector<StringRef, 4> LineSplit;
118
9
    Line.split(LineSplit, ' ', /*MaxSplit=*/-1,
119
9
               /*KeepEmpty=*/false);
120
9
    if (LineSplit.empty())
121
0
      continue;
122
9
    SmallVector<StringRef, 4> BBNames;
123
9
    LineSplit[1].split(BBNames, ';', /*MaxSplit=*/-1,
124
9
                       /*KeepEmpty=*/false);
125
9
    if (BBNames.empty())
126
0
      report_fatal_error("Missing bbs name");
127
9
    BlocksByName.push_back({LineSplit[0], {BBNames.begin(), BBNames.end()}});
128
9
  }
129
5
}
130
131
/// Extracts the landing pads to make sure all of them have only one
132
/// predecessor.
133
16
void BlockExtractor::splitLandingPadPreds(Function &F) {
134
55
  for (BasicBlock &BB : F) {
135
151
    for (Instruction &I : BB) {
136
151
      if (!isa<InvokeInst>(&I))
137
150
        continue;
138
1
      InvokeInst *II = cast<InvokeInst>(&I);
139
1
      BasicBlock *Parent = II->getParent();
140
1
      BasicBlock *LPad = II->getUnwindDest();
141
1
142
1
      // Look through the landing pad's predecessors. If one of them ends in an
143
1
      // 'invoke', then we want to split the landing pad.
144
1
      bool Split = false;
145
1
      for (auto PredBB : predecessors(LPad)) {
146
1
        if (PredBB->isLandingPad() && 
PredBB != Parent0
&&
147
1
            
isa<InvokeInst>(Parent->getTerminator())0
) {
148
0
          Split = true;
149
0
          break;
150
0
        }
151
1
      }
152
1
153
1
      if (!Split)
154
1
        continue;
155
0
156
0
      SmallVector<BasicBlock *, 2> NewBBs;
157
0
      SplitLandingPadPredecessors(LPad, Parent, ".1", ".2", NewBBs);
158
0
    }
159
55
  }
160
16
}
161
162
10
bool BlockExtractor::runOnModule(Module &M) {
163
10
164
10
  bool Changed = false;
165
10
166
10
  // Get all the functions.
167
10
  SmallVector<Function *, 4> Functions;
168
16
  for (Function &F : M) {
169
16
    splitLandingPadPreds(F);
170
16
    Functions.push_back(&F);
171
16
  }
172
10
173
10
  // Get all the blocks specified in the input file.
174
10
  unsigned NextGroupIdx = GroupsOfBlocks.size();
175
10
  GroupsOfBlocks.resize(NextGroupIdx + BlocksByName.size());
176
10
  for (const auto &BInfo : BlocksByName) {
177
9
    Function *F = M.getFunction(BInfo.first);
178
9
    if (!F)
179
1
      report_fatal_error("Invalid function name specified in the input file");
180
11
    
for (const auto &BBInfo : BInfo.second)8
{
181
30
      auto Res = llvm::find_if(*F, [&](const BasicBlock &BB) {
182
30
        return BB.getName().equals(BBInfo);
183
30
      });
184
11
      if (Res == F->end())
185
1
        report_fatal_error("Invalid block name specified in the input file");
186
10
      GroupsOfBlocks[NextGroupIdx].push_back(&*Res);
187
10
    }
188
8
    ++NextGroupIdx;
189
7
  }
190
10
191
10
  // Extract each group of basic blocks.
192
12
  
for (auto &BBs : GroupsOfBlocks)8
{
193
12
    SmallVector<BasicBlock *, 32> BlocksToExtractVec;
194
18
    for (BasicBlock *BB : BBs) {
195
18
      // Check if the module contains BB.
196
18
      if (BB->getParent()->getParent() != &M)
197
0
        report_fatal_error("Invalid basic block");
198
18
      LLVM_DEBUG(dbgs() << "BlockExtractor: Extracting "
199
18
                        << BB->getParent()->getName() << ":" << BB->getName()
200
18
                        << "\n");
201
18
      BlocksToExtractVec.push_back(BB);
202
18
      if (const InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator()))
203
0
        BlocksToExtractVec.push_back(II->getUnwindDest());
204
18
      ++NumExtracted;
205
18
      Changed = true;
206
18
    }
207
12
    Function *F = CodeExtractor(BlocksToExtractVec).extractCodeRegion();
208
12
    if (F)
209
12
      LLVM_DEBUG(dbgs() << "Extracted group '" << (*BBs.begin())->getName()
210
12
                        << "' in: " << F->getName() << '\n');
211
12
    else
212
12
      LLVM_DEBUG(dbgs() << "Failed to extract for group '"
213
12
                        << (*BBs.begin())->getName() << "'\n");
214
12
  }
215
8
216
8
  // Erase the functions.
217
8
  if (EraseFunctions || 
BlockExtractorEraseFuncs5
) {
218
7
    for (Function *F : Functions) {
219
7
      LLVM_DEBUG(dbgs() << "BlockExtractor: Trying to delete " << F->getName()
220
7
                        << "\n");
221
7
      F->deleteBody();
222
7
    }
223
4
    // Set linkage as ExternalLinkage to avoid erasing unreachable functions.
224
4
    for (Function &F : M)
225
18
      F.setLinkage(GlobalValue::ExternalLinkage);
226
4
    Changed = true;
227
4
  }
228
8
229
8
  return Changed;
230
8
}