[llvm] r323266 - [llvm-extract] Support extracting basic blocks

Volkan Keles via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 23 13:51:34 PST 2018


Author: volkan
Date: Tue Jan 23 13:51:34 2018
New Revision: 323266

URL: http://llvm.org/viewvc/llvm-project?rev=323266&view=rev
Log:
[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

Added:
    llvm/trunk/lib/Transforms/IPO/BlockExtractor.cpp
    llvm/trunk/test/Transforms/BlockExtractor/
    llvm/trunk/test/Transforms/BlockExtractor/extract-blocks.ll
    llvm/trunk/test/Transforms/BlockExtractor/invalid-block.ll
    llvm/trunk/test/Transforms/BlockExtractor/invalid-function.ll
    llvm/trunk/test/tools/llvm-extract/extract-block.ll
    llvm/trunk/test/tools/llvm-extract/extract-invalid-block.ll
    llvm/trunk/test/tools/llvm-extract/extract-multiple-blocks.ll
Modified:
    llvm/trunk/include/llvm/InitializePasses.h
    llvm/trunk/include/llvm/Transforms/IPO.h
    llvm/trunk/lib/Transforms/IPO/CMakeLists.txt
    llvm/trunk/lib/Transforms/IPO/IPO.cpp
    llvm/trunk/lib/Transforms/IPO/LoopExtractor.cpp
    llvm/trunk/tools/bugpoint/ExtractFunction.cpp
    llvm/trunk/tools/llvm-extract/llvm-extract.cpp

Modified: llvm/trunk/include/llvm/InitializePasses.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=323266&r1=323265&r2=323266&view=diff
==============================================================================
--- llvm/trunk/include/llvm/InitializePasses.h (original)
+++ llvm/trunk/include/llvm/InitializePasses.h Tue Jan 23 13:51:34 2018
@@ -73,7 +73,7 @@ void initializeAtomicExpandPass(PassRegi
 void initializeBDCELegacyPassPass(PassRegistry&);
 void initializeBarrierNoopPass(PassRegistry&);
 void initializeBasicAAWrapperPassPass(PassRegistry&);
-void initializeBlockExtractorPassPass(PassRegistry&);
+void initializeBlockExtractorPass(PassRegistry &);
 void initializeBlockFrequencyInfoWrapperPassPass(PassRegistry&);
 void initializeBoundsCheckingLegacyPassPass(PassRegistry&);
 void initializeBranchFolderPassPass(PassRegistry&);

Modified: llvm/trunk/include/llvm/Transforms/IPO.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO.h?rev=323266&r1=323265&r2=323266&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/IPO.h (original)
+++ llvm/trunk/include/llvm/Transforms/IPO.h Tue Jan 23 13:51:34 2018
@@ -179,10 +179,13 @@ Pass *createLoopExtractorPass();
 ///
 Pass *createSingleLoopExtractorPass();
 
-/// createBlockExtractorPass - This pass extracts all blocks (except those
-/// specified in the argument list) from the functions in the module.
+/// createBlockExtractorPass - This pass extracts all the specified blocks
+/// from the functions in the module.
 ///
 ModulePass *createBlockExtractorPass();
+ModulePass *
+createBlockExtractorPass(const SmallVectorImpl<BasicBlock *> &BlocksToExtract,
+                         bool EraseFunctions);
 
 /// createStripDeadPrototypesPass - This pass removes any function declarations
 /// (prototypes) that are not used.

Added: llvm/trunk/lib/Transforms/IPO/BlockExtractor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/BlockExtractor.cpp?rev=323266&view=auto
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/BlockExtractor.cpp (added)
+++ llvm/trunk/lib/Transforms/IPO/BlockExtractor.cpp Tue Jan 23 13:51:34 2018
@@ -0,0 +1,174 @@
+//===- BlockExtractor.cpp - Extracts blocks into their own functions ------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass extracts the specified basic blocks from the module into their
+// own functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/CodeExtractor.h"
+using namespace llvm;
+
+#define DEBUG_TYPE "block-extractor"
+
+STATISTIC(NumExtracted, "Number of basic blocks extracted");
+
+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);
+
+cl::opt<bool> BlockExtractorEraseFuncs("extract-blocks-erase-funcs",
+                                       cl::desc("Erase the existing functions"),
+                                       cl::Hidden);
+
+namespace {
+class BlockExtractor : public ModulePass {
+  SmallVector<BasicBlock *, 16> Blocks;
+  bool EraseFunctions;
+  SmallVector<std::pair<std::string, std::string>, 32> BlocksByName;
+
+public:
+  static char ID;
+  BlockExtractor(const SmallVectorImpl<BasicBlock *> &BlocksToExtract,
+                 bool EraseFunctions)
+      : ModulePass(ID), Blocks(BlocksToExtract.begin(), BlocksToExtract.end()),
+        EraseFunctions(EraseFunctions) {
+    if (!BlockExtractorFile.empty())
+      loadFile();
+  }
+  BlockExtractor() : BlockExtractor(SmallVector<BasicBlock *, 0>(), false) {}
+  bool runOnModule(Module &M) override;
+
+private:
+  void loadFile();
+  void splitLandingPadPreds(Function &F);
+};
+} // end anonymous namespace
+
+char BlockExtractor::ID = 0;
+INITIALIZE_PASS(BlockExtractor, "extract-blocks",
+                "Extract basic blocks from module", false, false)
+
+ModulePass *llvm::createBlockExtractorPass() { return new BlockExtractor(); }
+ModulePass *llvm::createBlockExtractorPass(
+    const SmallVectorImpl<BasicBlock *> &BlocksToExtract, bool EraseFunctions) {
+  return new BlockExtractor(BlocksToExtract, EraseFunctions);
+}
+
+/// Gets all of the blocks specified in the input file.
+void BlockExtractor::loadFile() {
+  auto ErrOrBuf = MemoryBuffer::getFile(BlockExtractorFile);
+  if (std::error_code EC = ErrOrBuf.getError())
+    report_fatal_error("BlockExtractor couldn't load the file.");
+  // Read the file.
+  auto &Buf = *ErrOrBuf;
+  SmallVector<StringRef, 16> Lines;
+  Buf->getBuffer().split(Lines, '\n', /*MaxSplit=*/-1,
+                         /*KeepEmpty=*/false);
+  for (const auto &Line : Lines) {
+    auto FBPair = Line.split(' ');
+    BlocksByName.push_back({FBPair.first, FBPair.second});
+  }
+}
+
+/// Extracts the landing pads to make sure all of them have only one
+/// predecessor.
+void BlockExtractor::splitLandingPadPreds(Function &F) {
+  for (BasicBlock &BB : F) {
+    for (Instruction &I : BB) {
+      if (!isa<InvokeInst>(&I))
+        continue;
+      InvokeInst *II = cast<InvokeInst>(&I);
+      BasicBlock *Parent = II->getParent();
+      BasicBlock *LPad = II->getUnwindDest();
+
+      // Look through the landing pad's predecessors. If one of them ends in an
+      // 'invoke', then we want to split the landing pad.
+      bool Split = false;
+      for (auto PredBB : predecessors(LPad)) {
+        if (PredBB->isLandingPad() && PredBB != Parent &&
+            isa<InvokeInst>(Parent->getTerminator())) {
+          Split = true;
+          break;
+        }
+      }
+
+      if (!Split)
+        continue;
+
+      SmallVector<BasicBlock *, 2> NewBBs;
+      SplitLandingPadPredecessors(LPad, Parent, ".1", ".2", NewBBs);
+    }
+  }
+}
+
+bool BlockExtractor::runOnModule(Module &M) {
+
+  bool Changed = false;
+
+  // Get all the functions.
+  SmallVector<Function *, 4> Functions;
+  for (Function &F : M) {
+    splitLandingPadPreds(F);
+    Functions.push_back(&F);
+  }
+
+  // Get all the blocks specified in the input file.
+  for (const auto &BInfo : BlocksByName) {
+    Function *F = M.getFunction(BInfo.first);
+    if (!F)
+      report_fatal_error("Invalid function name specified in the input file");
+    auto Res = llvm::find_if(*F, [&](const BasicBlock &BB) {
+      return BB.getName().equals(BInfo.second);
+    });
+    if (Res == F->end())
+      report_fatal_error("Invalid block name specified in the input file");
+    Blocks.push_back(&*Res);
+  }
+
+  // Extract basic blocks.
+  for (BasicBlock *BB : Blocks) {
+    // Check if the module contains BB.
+    if (BB->getParent()->getParent() != &M)
+      report_fatal_error("Invalid basic block");
+    DEBUG(dbgs() << "BlockExtractor: Extracting " << BB->getParent()->getName()
+                 << ":" << BB->getName() << "\n");
+    SmallVector<BasicBlock *, 2> BlocksToExtractVec;
+    BlocksToExtractVec.push_back(BB);
+    if (const InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator()))
+      BlocksToExtractVec.push_back(II->getUnwindDest());
+    CodeExtractor(BlocksToExtractVec).extractCodeRegion();
+    ++NumExtracted;
+    Changed = true;
+  }
+
+  // Erase the functions.
+  if (EraseFunctions || BlockExtractorEraseFuncs) {
+    for (Function *F : Functions) {
+      DEBUG(dbgs() << "BlockExtractor: Deleting " << F->getName() << "\n");
+      F->eraseFromParent();
+    }
+    // Set linkage as ExternalLinkage to avoid erasing unreachable functions.
+    for (Function &F : M)
+      F.setLinkage(GlobalValue::ExternalLinkage);
+    Changed = true;
+  }
+
+  return Changed;
+}

Modified: llvm/trunk/lib/Transforms/IPO/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/CMakeLists.txt?rev=323266&r1=323265&r2=323266&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/CMakeLists.txt (original)
+++ llvm/trunk/lib/Transforms/IPO/CMakeLists.txt Tue Jan 23 13:51:34 2018
@@ -2,6 +2,7 @@ add_llvm_library(LLVMipo
   AlwaysInliner.cpp
   ArgumentPromotion.cpp
   BarrierNoopPass.cpp
+  BlockExtractor.cpp
   CalledValuePropagation.cpp
   ConstantMerge.cpp
   CrossDSOCFI.cpp

Modified: llvm/trunk/lib/Transforms/IPO/IPO.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/IPO.cpp?rev=323266&r1=323265&r2=323266&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/IPO.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/IPO.cpp Tue Jan 23 13:51:34 2018
@@ -40,7 +40,7 @@ void llvm::initializeIPO(PassRegistry &R
   initializeInferFunctionAttrsLegacyPassPass(Registry);
   initializeInternalizeLegacyPassPass(Registry);
   initializeLoopExtractorPass(Registry);
-  initializeBlockExtractorPassPass(Registry);
+  initializeBlockExtractorPass(Registry);
   initializeSingleLoopExtractorPass(Registry);
   initializeLowerTypeTestsPass(Registry);
   initializeMergeFunctionsPass(Registry);

Modified: llvm/trunk/lib/Transforms/IPO/LoopExtractor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/LoopExtractor.cpp?rev=323266&r1=323265&r2=323266&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/LoopExtractor.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/LoopExtractor.cpp Tue Jan 23 13:51:34 2018
@@ -158,155 +158,3 @@ bool LoopExtractor::runOnLoop(Loop *L, L
 Pass *llvm::createSingleLoopExtractorPass() {
   return new SingleLoopExtractor();
 }
-
-
-// BlockFile - A file which contains a list of blocks that should not be
-// extracted.
-static cl::opt<std::string>
-BlockFile("extract-blocks-file", cl::value_desc("filename"),
-          cl::desc("A file containing list of basic blocks to not extract"),
-          cl::Hidden);
-
-namespace {
-  /// BlockExtractorPass - This pass is used by bugpoint to extract all blocks
-  /// from the module into their own functions except for those specified by the
-  /// BlocksToNotExtract list.
-  class BlockExtractorPass : public ModulePass {
-    void LoadFile(const char *Filename);
-    void SplitLandingPadPreds(Function *F);
-
-    std::vector<BasicBlock*> BlocksToNotExtract;
-    std::vector<std::pair<std::string, std::string> > BlocksToNotExtractByName;
-  public:
-    static char ID; // Pass identification, replacement for typeid
-    BlockExtractorPass() : ModulePass(ID) {
-      if (!BlockFile.empty())
-        LoadFile(BlockFile.c_str());
-    }
-
-    bool runOnModule(Module &M) override;
-  };
-}
-
-char BlockExtractorPass::ID = 0;
-INITIALIZE_PASS(BlockExtractorPass, "extract-blocks",
-                "Extract Basic Blocks From Module (for bugpoint use)",
-                false, false)
-
-// createBlockExtractorPass - This pass extracts all blocks (except those
-// specified in the argument list) from the functions in the module.
-//
-ModulePass *llvm::createBlockExtractorPass() {
-  return new BlockExtractorPass();
-}
-
-void BlockExtractorPass::LoadFile(const char *Filename) {
-  // Load the BlockFile...
-  std::ifstream In(Filename);
-  if (!In.good()) {
-    errs() << "WARNING: BlockExtractor couldn't load file '" << Filename
-           << "'!\n";
-    return;
-  }
-  while (In) {
-    std::string FunctionName, BlockName;
-    In >> FunctionName;
-    In >> BlockName;
-    if (!BlockName.empty())
-      BlocksToNotExtractByName.push_back(
-          std::make_pair(FunctionName, BlockName));
-  }
-}
-
-/// SplitLandingPadPreds - The landing pad needs to be extracted with the invoke
-/// instruction. The critical edge breaker will refuse to break critical edges
-/// to a landing pad. So do them here. After this method runs, all landing pads
-/// should have only one predecessor.
-void BlockExtractorPass::SplitLandingPadPreds(Function *F) {
-  for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
-    InvokeInst *II = dyn_cast<InvokeInst>(I);
-    if (!II) continue;
-    BasicBlock *Parent = II->getParent();
-    BasicBlock *LPad = II->getUnwindDest();
-
-    // Look through the landing pad's predecessors. If one of them ends in an
-    // 'invoke', then we want to split the landing pad.
-    bool Split = false;
-    for (pred_iterator
-           PI = pred_begin(LPad), PE = pred_end(LPad); PI != PE; ++PI) {
-      BasicBlock *BB = *PI;
-      if (BB->isLandingPad() && BB != Parent &&
-          isa<InvokeInst>(Parent->getTerminator())) {
-        Split = true;
-        break;
-      }
-    }
-
-    if (!Split) continue;
-
-    SmallVector<BasicBlock*, 2> NewBBs;
-    SplitLandingPadPredecessors(LPad, Parent, ".1", ".2", NewBBs);
-  }
-}
-
-bool BlockExtractorPass::runOnModule(Module &M) {
-  if (skipModule(M))
-    return false;
-
-  std::set<BasicBlock*> TranslatedBlocksToNotExtract;
-  for (unsigned i = 0, e = BlocksToNotExtract.size(); i != e; ++i) {
-    BasicBlock *BB = BlocksToNotExtract[i];
-    Function *F = BB->getParent();
-
-    // Map the corresponding function in this module.
-    Function *MF = M.getFunction(F->getName());
-    assert(MF->getFunctionType() == F->getFunctionType() && "Wrong function?");
-
-    // Figure out which index the basic block is in its function.
-    Function::iterator BBI = MF->begin();
-    std::advance(BBI, std::distance(F->begin(), Function::iterator(BB)));
-    TranslatedBlocksToNotExtract.insert(&*BBI);
-  }
-
-  while (!BlocksToNotExtractByName.empty()) {
-    // There's no way to find BBs by name without looking at every BB inside
-    // every Function. Fortunately, this is always empty except when used by
-    // bugpoint in which case correctness is more important than performance.
-
-    std::string &FuncName  = BlocksToNotExtractByName.back().first;
-    std::string &BlockName = BlocksToNotExtractByName.back().second;
-
-    for (Function &F : M) {
-      if (F.getName() != FuncName) continue;
-
-      for (BasicBlock &BB : F) {
-        if (BB.getName() != BlockName) continue;
-
-        TranslatedBlocksToNotExtract.insert(&BB);
-      }
-    }
-
-    BlocksToNotExtractByName.pop_back();
-  }
-
-  // Now that we know which blocks to not extract, figure out which ones we WANT
-  // to extract.
-  std::vector<BasicBlock*> BlocksToExtract;
-  for (Function &F : M) {
-    SplitLandingPadPreds(&F);
-    for (BasicBlock &BB : F)
-      if (!TranslatedBlocksToNotExtract.count(&BB))
-        BlocksToExtract.push_back(&BB);
-  }
-
-  for (BasicBlock *BlockToExtract : BlocksToExtract) {
-    SmallVector<BasicBlock*, 2> BlocksToExtractVec;
-    BlocksToExtractVec.push_back(BlockToExtract);
-    if (const InvokeInst *II =
-            dyn_cast<InvokeInst>(BlockToExtract->getTerminator()))
-      BlocksToExtractVec.push_back(II->getUnwindDest());
-    CodeExtractor(BlocksToExtractVec).extractCodeRegion();
-  }
-
-  return !BlocksToExtract.empty();
-}

Added: llvm/trunk/test/Transforms/BlockExtractor/extract-blocks.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/BlockExtractor/extract-blocks.ll?rev=323266&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/BlockExtractor/extract-blocks.ll (added)
+++ llvm/trunk/test/Transforms/BlockExtractor/extract-blocks.ll Tue Jan 23 13:51:34 2018
@@ -0,0 +1,43 @@
+; RUN: echo 'foo bb9' > %t
+; RUN: echo 'foo bb20' >> %t
+; RUN: opt -S -extract-blocks -extract-blocks-file=%t %s | FileCheck %s --check-prefix=CHECK-NO-ERASE
+; RUN: opt -S -extract-blocks -extract-blocks-file=%t -extract-blocks-erase-funcs %s | FileCheck %s --check-prefix=CHECK-ERASE
+
+; CHECK-NO-ERASE: @foo(
+; CHECK-NO-ERASE: @foo_bb9(
+; CHECK-NO-ERASE: @foo_bb20(
+; CHECK-ERASE-NOT: @foo(
+; CHECK-ERASE: @foo_bb9(
+; CHECK-ERASE: @foo_bb20(
+define i32 @foo(i32 %arg, i32 %arg1) {
+bb:
+  %tmp5 = icmp sgt i32 %arg, 0
+  %tmp8 = icmp sgt i32 %arg1, 0
+  %or.cond = and i1 %tmp5, %tmp8
+  br i1 %or.cond, label %bb9, label %bb14
+
+bb9:                                              ; preds = %bb
+  %tmp12 = shl i32 %arg1, 2
+  %tmp13 = add nsw i32 %tmp12, %arg
+  br label %bb30
+
+bb14:                                             ; preds = %bb
+  %0 = and i32 %arg1, %arg
+  %1 = icmp slt i32 %0, 0
+  br i1 %1, label %bb20, label %bb26
+
+bb20:                                             ; preds = %bb14
+  %tmp22 = mul nsw i32 %arg, 3
+  %tmp24 = sdiv i32 %arg1, 6
+  %tmp25 = add nsw i32 %tmp24, %tmp22
+  br label %bb30
+
+bb26:                                             ; preds = %bb14
+  %tmp29 = sub nsw i32 %arg, %arg1
+  br label %bb30
+
+bb30:                                             ; preds = %bb26, %bb20, %bb9
+  %tmp.0 = phi i32 [ %tmp13, %bb9 ], [ %tmp25, %bb20 ], [ %tmp29, %bb26 ]
+  ret i32 %tmp.0
+}
+

Added: llvm/trunk/test/Transforms/BlockExtractor/invalid-block.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/BlockExtractor/invalid-block.ll?rev=323266&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/BlockExtractor/invalid-block.ll (added)
+++ llvm/trunk/test/Transforms/BlockExtractor/invalid-block.ll Tue Jan 23 13:51:34 2018
@@ -0,0 +1,9 @@
+; RUN: echo 'bar invalidbb' > %t
+; RUN: not opt -S -extract-blocks -extract-blocks-file=%t %s 2>&1 | FileCheck %s
+
+; CHECK: Invalid block
+define void @bar() {
+bb:
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/BlockExtractor/invalid-function.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/BlockExtractor/invalid-function.ll?rev=323266&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/BlockExtractor/invalid-function.ll (added)
+++ llvm/trunk/test/Transforms/BlockExtractor/invalid-function.ll Tue Jan 23 13:51:34 2018
@@ -0,0 +1,9 @@
+; RUN: echo 'foo bb' > %t
+; RUN: not opt -S -extract-blocks -extract-blocks-file=%t %s 2>&1 | FileCheck %s
+
+; CHECK: Invalid function
+define void @bar() {
+bb:
+  ret void
+}
+

Added: llvm/trunk/test/tools/llvm-extract/extract-block.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-extract/extract-block.ll?rev=323266&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-extract/extract-block.ll (added)
+++ llvm/trunk/test/tools/llvm-extract/extract-block.ll Tue Jan 23 13:51:34 2018
@@ -0,0 +1,29 @@
+; RUN: llvm-extract -S -bb foo:bb4 %s | FileCheck %s
+
+; CHECK: @foo_bb4
+; CHECK: %tmp5
+define i32 @foo(i32 %arg) {
+bb:
+  %tmp = alloca i32, align 4
+  %tmp1 = alloca i32, align 4
+  store i32 %arg, i32* %tmp1, align 4
+  %tmp2 = load i32, i32* %tmp1, align 4
+  %tmp3 = icmp sgt i32 %tmp2, 0
+  br i1 %tmp3, label %bb4, label %bb7
+
+bb4:                                              ; preds = %bb
+  %tmp5 = load i32, i32* %tmp1, align 4
+  %tmp6 = add nsw i32 %tmp5, 1
+  store i32 %tmp6, i32* %tmp1, align 4
+  store i32 %tmp6, i32* %tmp, align 4
+  br label %bb8
+
+bb7:                                              ; preds = %bb
+  store i32 0, i32* %tmp, align 4
+  br label %bb8
+
+bb8:                                              ; preds = %bb7, %bb4
+  %tmp9 = load i32, i32* %tmp, align 4
+  ret i32 %tmp9
+}
+

Added: llvm/trunk/test/tools/llvm-extract/extract-invalid-block.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-extract/extract-invalid-block.ll?rev=323266&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-extract/extract-invalid-block.ll (added)
+++ llvm/trunk/test/tools/llvm-extract/extract-invalid-block.ll Tue Jan 23 13:51:34 2018
@@ -0,0 +1,28 @@
+; RUN: not llvm-extract -S -bb foo:invalidbb %s 2>&1 | FileCheck %s
+
+; CHECK: function foo doesn't contain a basic block named 'invalidbb'!
+define i32 @foo(i32 %arg) {
+bb:
+  %tmp = alloca i32, align 4
+  %tmp1 = alloca i32, align 4
+  store i32 %arg, i32* %tmp1, align 4
+  %tmp2 = load i32, i32* %tmp1, align 4
+  %tmp3 = icmp sgt i32 %tmp2, 0
+  br i1 %tmp3, label %bb4, label %bb7
+
+bb4:                                              ; preds = %bb
+  %tmp5 = load i32, i32* %tmp1, align 4
+  %tmp6 = add nsw i32 %tmp5, 1
+  store i32 %tmp6, i32* %tmp1, align 4
+  store i32 %tmp6, i32* %tmp, align 4
+  br label %bb8
+
+bb7:                                              ; preds = %bb
+  store i32 0, i32* %tmp, align 4
+  br label %bb8
+
+bb8:                                              ; preds = %bb7, %bb4
+  %tmp9 = load i32, i32* %tmp, align 4
+  ret i32 %tmp9
+}
+

Added: llvm/trunk/test/tools/llvm-extract/extract-multiple-blocks.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-extract/extract-multiple-blocks.ll?rev=323266&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-extract/extract-multiple-blocks.ll (added)
+++ llvm/trunk/test/tools/llvm-extract/extract-multiple-blocks.ll Tue Jan 23 13:51:34 2018
@@ -0,0 +1,29 @@
+; RUN: llvm-extract -S -bb foo:bb4 -bb foo:bb7 %s | FileCheck %s
+
+; CHECK: @foo_bb4
+; CHECK: @foo_bb7
+define i32 @foo(i32 %arg) {
+bb:
+  %tmp = alloca i32, align 4
+  %tmp1 = alloca i32, align 4
+  store i32 %arg, i32* %tmp1, align 4
+  %tmp2 = load i32, i32* %tmp1, align 4
+  %tmp3 = icmp sgt i32 %tmp2, 0
+  br i1 %tmp3, label %bb4, label %bb7
+
+bb4:                                              ; preds = %bb
+  %tmp5 = load i32, i32* %tmp1, align 4
+  %tmp6 = add nsw i32 %tmp5, 1
+  store i32 %tmp6, i32* %tmp1, align 4
+  store i32 %tmp6, i32* %tmp, align 4
+  br label %bb8
+
+bb7:                                              ; preds = %bb
+  store i32 0, i32* %tmp, align 4
+  br label %bb8
+
+bb8:                                              ; preds = %bb7, %bb4
+  %tmp9 = load i32, i32* %tmp, align 4
+  ret i32 %tmp9
+}
+

Modified: llvm/trunk/tools/bugpoint/ExtractFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/bugpoint/ExtractFunction.cpp?rev=323266&r1=323265&r2=323266&view=diff
==============================================================================
--- llvm/trunk/tools/bugpoint/ExtractFunction.cpp (original)
+++ llvm/trunk/tools/bugpoint/ExtractFunction.cpp Tue Jan 23 13:51:34 2018
@@ -383,10 +383,16 @@ BugDriver::extractMappedBlocksFromModule
   }
   DiscardTemp Discard{*Temp};
 
+  // Extract all of the blocks except the ones in BBs.
+  SmallVector<BasicBlock *, 32> BlocksToExtract;
+  for (Function &F : *M)
+    for (BasicBlock &BB : F)
+      // Check if this block is going to be extracted.
+      if (std::find(BBs.begin(), BBs.end(), &BB) == BBs.end())
+        BlocksToExtract.push_back(&BB);
+
   raw_fd_ostream OS(Temp->FD, /*shouldClose*/ false);
-  for (std::vector<BasicBlock *>::const_iterator I = BBs.begin(), E = BBs.end();
-       I != E; ++I) {
-    BasicBlock *BB = *I;
+  for (BasicBlock *BB : BBs) {
     // If the BB doesn't have a name, give it one so we have something to key
     // off of.
     if (!BB->hasName())

Modified: llvm/trunk/tools/llvm-extract/llvm-extract.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-extract/llvm-extract.cpp?rev=323266&r1=323265&r2=323266&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-extract/llvm-extract.cpp (original)
+++ llvm/trunk/tools/llvm-extract/llvm-extract.cpp Tue Jan 23 13:51:34 2018
@@ -67,6 +67,12 @@ ExtractRegExpFuncs("rfunc", cl::desc("Sp
                                      "regular expression"),
                    cl::ZeroOrMore, cl::value_desc("rfunction"));
 
+// ExtractBlocks - The blocks to extract from the module.
+static cl::list<std::string>
+    ExtractBlocks("bb",
+                  cl::desc("Specify <function, basic block> pairs to extract"),
+                  cl::ZeroOrMore, cl::value_desc("function:bb"));
+
 // ExtractAlias - The alias to extract from the module.
 static cl::list<std::string>
 ExtractAliases("alias", cl::desc("Specify alias to extract"),
@@ -228,6 +234,32 @@ int main(int argc, char **argv) {
     }
   }
 
+  // Figure out which BasicBlocks we should extract.
+  SmallVector<BasicBlock *, 4> BBs;
+  for (StringRef StrPair : ExtractBlocks) {
+    auto BBInfo = StrPair.split(':');
+    // Get the function.
+    Function *F = M->getFunction(BBInfo.first);
+    if (!F) {
+      errs() << argv[0] << ": program doesn't contain a function named '"
+             << BBInfo.first << "'!\n";
+      return 1;
+    }
+    // Do not materialize this function.
+    GVs.insert(F);
+    // Get the basic block.
+    auto Res = llvm::find_if(*F, [&](const BasicBlock &BB) {
+      return BB.getName().equals(BBInfo.second);
+    });
+    if (Res == F->end()) {
+      errs() << argv[0] << ": function " << F->getName()
+             << " doesn't contain a basic block named '" << BBInfo.second
+             << "'!\n";
+      return 1;
+    }
+    BBs.push_back(&*Res);
+  }
+
   // Use *argv instead of argv[0] to work around a wrong GCC warning.
   ExitOnError ExitOnErr(std::string(*argv) + ": error reading input: ");
 
@@ -286,6 +318,14 @@ int main(int argc, char **argv) {
     ExitOnErr(M->materializeAll());
   }
 
+  // Extract the specified basic blocks from the module and erase the existing
+  // functions.
+  if (!ExtractBlocks.empty()) {
+    legacy::PassManager PM;
+    PM.add(createBlockExtractorPass(BBs, true));
+    PM.run(*M);
+  }
+
   // In addition to deleting all other functions, we also want to spiff it
   // up a little bit.  Do this now.
   legacy::PassManager Passes;




More information about the llvm-commits mailing list