[llvm] r372264 - llvm-reduce: Add pass to reduce basic blocks

David Blaikie via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 18 14:45:06 PDT 2019


Author: dblaikie
Date: Wed Sep 18 14:45:05 2019
New Revision: 372264

URL: http://llvm.org/viewvc/llvm-project?rev=372264&view=rev
Log:
llvm-reduce: Add pass to reduce basic blocks

Patch by Diego TreviƱo!

Differential Revision: https://reviews.llvm.org/D66320

Added:
    llvm/trunk/test/Reduce/Inputs/remove-bbs.py   (with props)
    llvm/trunk/test/Reduce/remove-bbs.ll
    llvm/trunk/tools/llvm-reduce/deltas/ReduceBasicBlocks.cpp
    llvm/trunk/tools/llvm-reduce/deltas/ReduceBasicBlocks.h
Modified:
    llvm/trunk/tools/llvm-reduce/CMakeLists.txt
    llvm/trunk/tools/llvm-reduce/DeltaManager.h

Added: llvm/trunk/test/Reduce/Inputs/remove-bbs.py
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Reduce/Inputs/remove-bbs.py?rev=372264&view=auto
==============================================================================
--- llvm/trunk/test/Reduce/Inputs/remove-bbs.py (added)
+++ llvm/trunk/test/Reduce/Inputs/remove-bbs.py Wed Sep 18 14:45:05 2019
@@ -0,0 +1,16 @@
+import sys
+import re
+
+InterestingBBs = 0
+input = open(sys.argv[1], "r")
+for line in input:
+  i = line.find(';')
+  if i >= 0:
+    line = line[:i]
+  if line.startswith("interesting") or "%interesting" in line:
+    InterestingBBs += 1
+
+if InterestingBBs == 6:
+  sys.exit(0) # interesting!
+
+sys.exit(1) # IR isn't interesting

Propchange: llvm/trunk/test/Reduce/Inputs/remove-bbs.py
------------------------------------------------------------------------------
    svn:executable = *

Added: llvm/trunk/test/Reduce/remove-bbs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Reduce/remove-bbs.ll?rev=372264&view=auto
==============================================================================
--- llvm/trunk/test/Reduce/remove-bbs.ll (added)
+++ llvm/trunk/test/Reduce/remove-bbs.ll Wed Sep 18 14:45:05 2019
@@ -0,0 +1,29 @@
+; Test that llvm-reduce can remove uninteresting Basic Blocks, and remove them from instructions (i.e. SwitchInst, BranchInst and IndirectBrInst)
+; Note: if an uninteresting BB is the default case for a switch, the instruction is removed altogether (since the default case cannot be replaced)
+;
+; RUN: llvm-reduce --test %python --test-arg %p/Inputs/remove-bbs.py %s -o %t
+; RUN: cat %t | FileCheck -implicit-check-not=uninteresting %s
+
+define void @main() {
+interesting:
+  ; CHECK-NOT: switch i32 0, label %uninteresting
+  switch i32 0, label %uninteresting [
+    i32 0, label %uninteresting
+  ]
+
+uninteresting:
+  ret void
+
+interesting2:
+  ; CHECK: switch i32 1, label %interesting3
+  switch i32 1, label %interesting3 [
+    ; CHECK-NOT: i32 0, label %uninteresting
+    i32 0, label %uninteresting
+    ; CHECK: i32 1, label %interesting3
+    i32 1, label %interesting3
+  ]
+
+interesting3:
+  ; CHECK: br label %interesting2
+  br i1 true, label %interesting2, label %uninteresting
+}

Modified: llvm/trunk/tools/llvm-reduce/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-reduce/CMakeLists.txt?rev=372264&r1=372263&r2=372264&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-reduce/CMakeLists.txt (original)
+++ llvm/trunk/tools/llvm-reduce/CMakeLists.txt Wed Sep 18 14:45:05 2019
@@ -18,6 +18,7 @@ add_llvm_tool(llvm-reduce
   deltas/ReduceGlobalVars.cpp
   deltas/ReduceMetadata.cpp
   deltas/ReduceArguments.cpp
+  deltas/ReduceBasicBlocks.cpp
 
   DEPENDS
   intrinsics_gen

Modified: llvm/trunk/tools/llvm-reduce/DeltaManager.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-reduce/DeltaManager.h?rev=372264&r1=372263&r2=372264&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-reduce/DeltaManager.h (original)
+++ llvm/trunk/tools/llvm-reduce/DeltaManager.h Wed Sep 18 14:45:05 2019
@@ -14,6 +14,7 @@
 #include "TestRunner.h"
 #include "deltas/Delta.h"
 #include "deltas/ReduceArguments.h"
+#include "deltas/ReduceBasicBlocks.h"
 #include "deltas/ReduceFunctions.h"
 #include "deltas/ReduceGlobalVars.h"
 #include "deltas/ReduceMetadata.h"
@@ -23,6 +24,7 @@ namespace llvm {
 // TODO: Add CLI option to run only specified Passes (for unit tests)
 inline void runDeltaPasses(TestRunner &Tester) {
   reduceFunctionsDeltaPass(Tester);
+  reduceBasicBlocksDeltaPass(Tester);
   reduceGlobalsDeltaPass(Tester);
   reduceMetadataDeltaPass(Tester);
   reduceArgumentsDeltaPass(Tester);

Added: llvm/trunk/tools/llvm-reduce/deltas/ReduceBasicBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-reduce/deltas/ReduceBasicBlocks.cpp?rev=372264&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-reduce/deltas/ReduceBasicBlocks.cpp (added)
+++ llvm/trunk/tools/llvm-reduce/deltas/ReduceBasicBlocks.cpp Wed Sep 18 14:45:05 2019
@@ -0,0 +1,142 @@
+//===- ReduceArguments.cpp - Specialized Delta Pass -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a function which calls the Generic Delta pass in order
+// to reduce uninteresting Arguments from defined functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ReduceBasicBlocks.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
+#include <vector>
+
+using namespace llvm;
+
+/// Replaces BB Terminator with one that only contains Chunk BBs
+static void replaceBranchTerminator(BasicBlock &BB,
+                                    std::set<BasicBlock *> BBsToKeep) {
+  auto Term = BB.getTerminator();
+  std::vector<BasicBlock *> ChunkSucessors;
+  for (auto Succ : successors(&BB))
+    if (BBsToKeep.count(Succ))
+      ChunkSucessors.push_back(Succ);
+
+  // BB only references Chunk BBs
+  if (ChunkSucessors.size() == Term->getNumSuccessors())
+    return;
+
+  Term->eraseFromParent();
+
+  if (ChunkSucessors.empty()) {
+    ReturnInst::Create(BB.getContext(), nullptr, &BB);
+    return;
+  }
+
+  if (isa<BranchInst>(Term))
+    BranchInst::Create(ChunkSucessors[0], &BB);
+
+  if (auto IndBI = dyn_cast<IndirectBrInst>(Term)) {
+    auto NewIndBI =
+        IndirectBrInst::Create(IndBI->getAddress(), ChunkSucessors.size(), &BB);
+    for (auto Dest : ChunkSucessors)
+      NewIndBI->addDestination(Dest);
+  }
+}
+
+/// Removes uninteresting BBs from switch, if the default case ends up being
+/// uninteresting, the switch is replaced with a void return (since it has to be
+/// replace with something)
+static void removeUninterestingBBsFromSwitch(SwitchInst &SwInst,
+                                             std::set<BasicBlock *> BBsToKeep) {
+  if (!BBsToKeep.count(SwInst.getDefaultDest())) {
+    ReturnInst::Create(SwInst.getContext(), nullptr, SwInst.getParent());
+    SwInst.eraseFromParent();
+  } else
+    for (int I = 0, E = SwInst.getNumCases(); I != E; ++I) {
+      auto Case = SwInst.case_begin() + I;
+      if (!BBsToKeep.count(Case->getCaseSuccessor())) {
+        SwInst.removeCase(Case);
+        --I;
+        --E;
+      }
+    }
+}
+
+/// Removes out-of-chunk arguments from functions, and modifies their calls
+/// accordingly. It also removes allocations of out-of-chunk arguments.
+/// @returns the Module stripped of out-of-chunk functions
+static void extractBasicBlocksFromModule(std::vector<Chunk> ChunksToKeep,
+                                         Module *Program) {
+  unsigned I = 0, BBCount = 0;
+  std::set<BasicBlock *> BBsToKeep;
+
+  for (auto &F : *Program)
+    for (auto &BB : F)
+      if (I < ChunksToKeep.size()) {
+        if (ChunksToKeep[I].contains(++BBCount))
+          BBsToKeep.insert(&BB);
+        if (ChunksToKeep[I].end == BBCount)
+          ++I;
+      }
+
+  std::vector<BasicBlock *> BBsToDelete;
+  for (auto &F : *Program)
+    for (auto &BB : F) {
+      if (!BBsToKeep.count(&BB)) {
+        BBsToDelete.push_back(&BB);
+        // Remove out-of-chunk BB from successor phi nodes
+        for (auto *Succ : successors(&BB))
+          Succ->removePredecessor(&BB);
+      }
+    }
+
+  // Replace terminators that reference out-of-chunk BBs
+  for (auto &F : *Program)
+    for (auto &BB : F) {
+      if (auto *SwInst = dyn_cast<SwitchInst>(BB.getTerminator()))
+        removeUninterestingBBsFromSwitch(*SwInst, BBsToKeep);
+      else
+        replaceBranchTerminator(BB, BBsToKeep);
+    }
+
+  // Replace out-of-chunk switch uses
+  for (auto &BB : BBsToDelete) {
+    // Instructions might be referenced in other BBs
+    for (auto &I : *BB)
+      I.replaceAllUsesWith(UndefValue::get(I.getType()));
+    BB->eraseFromParent();
+  }
+}
+
+/// Counts the amount of basic blocks and prints their name & respective index
+static unsigned countBasicBlocks(Module *Program) {
+  // TODO: Silence index with --quiet flag
+  outs() << "----------------------------\n";
+  int BBCount = 0;
+  for (auto &F : *Program)
+    for (auto &BB : F) {
+      if (BB.hasName())
+        outs() << "\t" << ++BBCount << ": " << BB.getName() << "\n";
+      else
+        outs() << "\t" << ++BBCount << ": Unnamed\n";
+    }
+
+  return BBCount;
+}
+
+void llvm::reduceBasicBlocksDeltaPass(TestRunner &Test) {
+  outs() << "*** Reducing Basic Blocks...\n";
+  unsigned BBCount = countBasicBlocks(Test.getProgram());
+  runDeltaPass(Test, BBCount, extractBasicBlocksFromModule);
+}

Added: llvm/trunk/tools/llvm-reduce/deltas/ReduceBasicBlocks.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-reduce/deltas/ReduceBasicBlocks.h?rev=372264&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-reduce/deltas/ReduceBasicBlocks.h (added)
+++ llvm/trunk/tools/llvm-reduce/deltas/ReduceBasicBlocks.h Wed Sep 18 14:45:05 2019
@@ -0,0 +1,20 @@
+//===- ReduceArguments.h - Specialized Delta Pass -------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a function which calls the Generic Delta pass in order
+// to reduce uninteresting Arguments from defined functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Delta.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+
+namespace llvm {
+void reduceBasicBlocksDeltaPass(TestRunner &Test);
+} // namespace llvm




More information about the llvm-commits mailing list