diff options
| -rwxr-xr-x | llvm/test/Reduce/Inputs/remove-global-vars.sh | 9 | ||||
| -rw-r--r-- | llvm/test/Reduce/remove-global-vars.ll | 38 | ||||
| -rw-r--r-- | llvm/tools/llvm-reduce/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | llvm/tools/llvm-reduce/DeltaManager.h | 14 | ||||
| -rw-r--r-- | llvm/tools/llvm-reduce/TestRunner.cpp | 8 | ||||
| -rw-r--r-- | llvm/tools/llvm-reduce/TestRunner.h | 2 | ||||
| -rw-r--r-- | llvm/tools/llvm-reduce/deltas/Delta.cpp | 171 | ||||
| -rw-r--r-- | llvm/tools/llvm-reduce/deltas/Delta.h | 193 | ||||
| -rw-r--r-- | llvm/tools/llvm-reduce/deltas/RemoveFunctions.cpp | 32 | ||||
| -rw-r--r-- | llvm/tools/llvm-reduce/deltas/RemoveFunctions.h | 18 | ||||
| -rw-r--r-- | llvm/tools/llvm-reduce/deltas/RemoveGlobalVars.cpp | 79 | ||||
| -rw-r--r-- | llvm/tools/llvm-reduce/deltas/RemoveGlobalVars.h | 20 | ||||
| -rw-r--r-- | llvm/tools/llvm-reduce/llvm-reduce.cpp | 5 | 
13 files changed, 385 insertions, 206 deletions
diff --git a/llvm/test/Reduce/Inputs/remove-global-vars.sh b/llvm/test/Reduce/Inputs/remove-global-vars.sh new file mode 100755 index 00000000000..cb656878cd9 --- /dev/null +++ b/llvm/test/Reduce/Inputs/remove-global-vars.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +matches=$(cat $1 | grep "@interesting = global" | wc -l) + +if [[ $matches > 0 ]]; then +  exit 0 +else +  exit 1 +fi diff --git a/llvm/test/Reduce/remove-global-vars.ll b/llvm/test/Reduce/remove-global-vars.ll new file mode 100644 index 00000000000..7acd35fd612 --- /dev/null +++ b/llvm/test/Reduce/remove-global-vars.ll @@ -0,0 +1,38 @@ +; Test that llvm-reduce can remove uninteresting Global Variables as well as +; their direct uses. +; +; RUN: llvm-reduce --test %p/Inputs/remove-global-vars.sh %s +; RUN: cat reduced.ll | FileCheck %s +; REQUIRES: plugins, shell + +@uninteresting1 = global i32 0, align 4 +; CHECK: @interesting = global +@interesting = global i32 5, align 4 +; CHECK-NOT: global +@uninteresting2 = global i32 25, align 4 +@uninteresting3 = global i32 50, align 4 + +define i32 @main() { +entry: +  %retval = alloca i32, align 4 +  store i32 0, i32* %retval, align 4 +  ; CHECK-NOT: load i32, i32* @uninteresting2, align 4 +  %0 = load i32, i32* @uninteresting2, align 4 +  store i32 %0, i32* @interesting, align 4 +  ; CHECK-NOT: load i32, i32* @uninteresting3, align 4 +  %1 = load i32, i32* @uninteresting3, align 4 +  %dec = add nsw i32 %1, -1 +  ; CHECK-NOT: store i32 %dec, i32* @uninteresting3, align 4 +  store i32 %dec, i32* @uninteresting3, align 4 +  ; CHECK: load i32, i32* @interesting, align 4 +  %2 = load i32, i32* @interesting, align 4 +  ; CHECK-NOT: load i32, i32* @uninteresting2, align 4 +  %3 = load i32, i32* @uninteresting2, align 4 +  %add = add nsw i32 %2, %3 +  ; CHECK-NOT: store i32 %add, i32* @uninteresting1, align 4 +  store i32 %add, i32* @uninteresting1, align 4 +  store i32 10, i32* @interesting, align 4 +  ; CHECK: load i32, i32* @interesting, align 4 +  %4 = load i32, i32* @interesting, align 4 +  ret i32 0 +} diff --git a/llvm/tools/llvm-reduce/CMakeLists.txt b/llvm/tools/llvm-reduce/CMakeLists.txt index b466e1f332b..da58b6fc9ba 100644 --- a/llvm/tools/llvm-reduce/CMakeLists.txt +++ b/llvm/tools/llvm-reduce/CMakeLists.txt @@ -15,7 +15,9 @@ set(LLVM_NO_DEAD_STRIP 1)  add_llvm_tool(llvm-reduce    llvm-reduce.cpp    TestRunner.cpp +  deltas/Delta.cpp    deltas/RemoveFunctions.cpp +  deltas/RemoveGlobalVars.cpp    DEPENDS    intrinsics_gen diff --git a/llvm/tools/llvm-reduce/DeltaManager.h b/llvm/tools/llvm-reduce/DeltaManager.h index 027685e4120..5a8204de45b 100644 --- a/llvm/tools/llvm-reduce/DeltaManager.h +++ b/llvm/tools/llvm-reduce/DeltaManager.h @@ -1,4 +1,4 @@ -//===- llvm-reduce.cpp - The LLVM Delta Reduction utility -----------------===// +//===- DeltaManager.h - Runs Delta Passes to reduce Input -----------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -6,21 +6,25 @@  //  //===----------------------------------------------------------------------===//  // -// This class calls each specialized Delta pass by passing it as a template to -// the generic Delta Pass. +// This file calls each specialized Delta pass in order to reduce the input IR +// file.  //  //===----------------------------------------------------------------------===//  #include "TestRunner.h"  #include "deltas/Delta.h"  #include "deltas/RemoveFunctions.h" +#include "deltas/RemoveGlobalVars.h"  namespace llvm {  inline void runDeltaPasses(TestRunner &Tester) { +  // TODO: Add option to only call certain delta passes    outs() << "Reducing functions...\n"; -  Delta<RemoveFunctions>::run(Tester); -  // TODO: Implement the rest of the Delta Passes +  removeFunctionsDeltaPass(Tester); +  outs() << "Reducing GVs...\n"; +  removeGlobalsDeltaPass(Tester); +  // TODO: Implement the remaining Delta Passes  }  } // namespace llvm diff --git a/llvm/tools/llvm-reduce/TestRunner.cpp b/llvm/tools/llvm-reduce/TestRunner.cpp index 479b9497bf6..59dc78418f8 100644 --- a/llvm/tools/llvm-reduce/TestRunner.cpp +++ b/llvm/tools/llvm-reduce/TestRunner.cpp @@ -1,3 +1,11 @@ +//===-- TestRunner.cpp ----------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +  #include "TestRunner.h"  using namespace llvm; diff --git a/llvm/tools/llvm-reduce/TestRunner.h b/llvm/tools/llvm-reduce/TestRunner.h index 9fe104ffef4..8bfab9e3997 100644 --- a/llvm/tools/llvm-reduce/TestRunner.h +++ b/llvm/tools/llvm-reduce/TestRunner.h @@ -1,4 +1,4 @@ -//===- llvm-reduce.cpp - The LLVM Delta Reduction utility -----------------===// +//===-- tools/llvm-reduce/TestRunner.h ---------------------------*- C++ -*-===/  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. diff --git a/llvm/tools/llvm-reduce/deltas/Delta.cpp b/llvm/tools/llvm-reduce/deltas/Delta.cpp new file mode 100644 index 00000000000..203b70ef333 --- /dev/null +++ b/llvm/tools/llvm-reduce/deltas/Delta.cpp @@ -0,0 +1,171 @@ +//===- Delta.cpp - Delta Debugging Algorithm Implementation ---------------===// +// +// 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 contains the implementation for the Delta Debugging Algorithm: +// it splits a given set of Targets (i.e. Functions, Instructions, BBs, etc.) +// into chunks and tries to reduce the number chunks that are interesting. +// +//===----------------------------------------------------------------------===// + +#include "Delta.h" + +/// Writes IR code to the given Filepath +static bool writeProgramToFile(StringRef Filepath, int FD, const Module &M) { +  ToolOutputFile Out(Filepath, FD); +  M.print(Out.os(), /*AnnotationWriter=*/nullptr); +  Out.os().close(); + +  if (!Out.os().has_error()) { +    Out.keep(); +    return false; +  } +  return true; +} + +/// Creates a temporary (and unique) file inside the tmp folder and writes +/// the given module IR. +static SmallString<128> createTmpFile(Module *M, StringRef TmpDir) { +  SmallString<128> UniqueFilepath; +  int UniqueFD; + +  std::error_code EC = sys::fs::createUniqueFile(TmpDir + "/tmp-%%%.ll", +                                                 UniqueFD, UniqueFilepath); +  if (EC) { +    errs() << "Error making unique filename: " << EC.message() << "!\n"; +    exit(1); +  } + +  if (writeProgramToFile(UniqueFilepath, UniqueFD, *M)) { +    errs() << "Error emitting bitcode to file '" << UniqueFilepath << "'!\n"; +    exit(1); +  } +  return UniqueFilepath; +} + +/// Prints the Chunk Indexes with the following format: [start, end], if +/// chunk is at minimum size (1), then it just displays [start]. +static void printChunks(std::vector<Chunk> Chunks, bool Oneline = false) { +  for (auto C : Chunks) { +    if (!Oneline) +      outs() << '\t'; +    outs() << "[" << C.begin; +    if (C.end - C.begin != 0) +      outs() << "," << C.end; +    outs() << "]"; +    if (!Oneline) +      outs() << '\n'; +  } +} + +/// Counts the amount of lines for a given file +static unsigned getLines(StringRef Filepath) { +  unsigned Lines = 0; +  std::string CurrLine; +  std::ifstream FileStream(Filepath); + +  while (std::getline(FileStream, CurrLine)) +    ++Lines; + +  return Lines; +} + +/// Splits Chunks in half and prints them. +/// If unable to split (when chunk size is 1) returns false. +static bool increaseGranularity(std::vector<Chunk> &Chunks) { +  outs() << "Increasing granularity..."; +  std::vector<Chunk> NewChunks; +  bool SplitOne = false; + +  for (auto &C : Chunks) { +    if (C.end - C.begin == 0) +      NewChunks.push_back(C); +    else { +      int Half = (C.begin + C.end) / 2; +      NewChunks.push_back({C.begin, Half}); +      NewChunks.push_back({Half + 1, C.end}); +      SplitOne = true; +    } +  } +  if (SplitOne) { +    Chunks = NewChunks; +    outs() << "Success! New Chunks:\n"; +    printChunks(Chunks); +  } +  return SplitOne; +} + +void llvm::runDeltaPass( +    TestRunner &Test, int Targets, +    std::function<std::unique_ptr<Module>(std::vector<Chunk>, Module *)> +        ExtractChunksFromModule) { +  if (!Targets) +    return; + +  std::vector<Chunk> Chunks = {{1, Targets}}; +  std::set<Chunk> UninterestingChunks; +  std::unique_ptr<Module> ReducedProgram; + +  if (!Test.run(Test.getReducedFilepath()) || !increaseGranularity(Chunks)) { +    outs() << "\nCouldn't reduce\n"; +    outs() << "----------------------------\n"; +    return; +  } + +  do { +    UninterestingChunks = {}; +    for (int I = Chunks.size() - 1; I >= 0; --I) { +      std::vector<Chunk> CurrentChunks; + +      for (auto C : Chunks) +        if (!UninterestingChunks.count(C) && C != Chunks[I]) +          CurrentChunks.push_back(C); + +      if (CurrentChunks.empty()) +        break; + +      // Generate Module with only Targets inside Current Chunks +      std::unique_ptr<Module> CurrentProgram = +          ExtractChunksFromModule(CurrentChunks, Test.getProgram()); +      // Write Module to tmp file +      SmallString<128> CurrentFilepath = +          createTmpFile(CurrentProgram.get(), Test.getTmpDir()); + +      outs() << "Testing with: "; +      printChunks(CurrentChunks, /*Oneline=*/true); +      outs() << " | " << sys::path::filename(CurrentFilepath); + +      // Current Chunks aren't interesting +      if (!Test.run(CurrentFilepath)) { +        outs() << "\n"; +        continue; +      } +      // We only care about interesting chunks if they reduce the testcase +      if (getLines(CurrentFilepath) < getLines(Test.getReducedFilepath())) { +        UninterestingChunks.insert(Chunks[I]); +        Test.setReducedFilepath(CurrentFilepath); +        ReducedProgram = std::move(CurrentProgram); +        outs() << " **** SUCCESS | lines: " << getLines(CurrentFilepath); +      } +      outs() << "\n"; +    } +    // Delete uninteresting chunks +    auto UnwantedChunks = Chunks.end(); +    UnwantedChunks = std::remove_if(Chunks.begin(), Chunks.end(), +                                    [UninterestingChunks](const Chunk &C) { +                                      return UninterestingChunks.count(C); +                                    }); +    Chunks.erase(UnwantedChunks, Chunks.end()); + +  } while (!UninterestingChunks.empty() || increaseGranularity(Chunks)); + +  // If we reduced the testcase replace it +  if (ReducedProgram) +    Test.setProgram(std::move(ReducedProgram)); +  outs() << "Couldn't increase anymore.\n"; +  outs() << "----------------------------\n"; +}
\ No newline at end of file diff --git a/llvm/tools/llvm-reduce/deltas/Delta.h b/llvm/tools/llvm-reduce/deltas/Delta.h index 60b212832c2..9c2b61b0a4b 100644 --- a/llvm/tools/llvm-reduce/deltas/Delta.h +++ b/llvm/tools/llvm-reduce/deltas/Delta.h @@ -1,4 +1,4 @@ -//===- llvm-reduce.cpp - The LLVM Delta Reduction utility -----------------===// +//===- Delta.h - Delta Debugging Algorithm Implementation -----------------===//  //  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.  // See https://llvm.org/LICENSE.txt for license information. @@ -42,180 +42,33 @@ struct Chunk {    }  }; -/// Writes IR code to the given Filepath -inline bool writeProgramToFile(StringRef Filepath, int FD, const Module &M) { -  ToolOutputFile Out(Filepath, FD); -  M.print(Out.os(), /*AnnotationWriter=*/nullptr); -  Out.os().close(); - -  if (!Out.os().has_error()) { -    Out.keep(); -    return false; -  } -  return true; -} - -/// Creates a temporary (and unique) file inside the tmp folder and outputs -/// the module inside it. -inline SmallString<128> createTmpFile(Module *M, StringRef TmpDir) { -  SmallString<128> UniqueFilepath; -  int UniqueFD; - -  std::error_code EC = sys::fs::createUniqueFile(TmpDir + "/tmp-%%%.ll", -                                                 UniqueFD, UniqueFilepath); -  if (EC) { -    errs() << "Error making unique filename: " << EC.message() << "!\n"; -    exit(1); -  } - -  if (writeProgramToFile(UniqueFilepath, UniqueFD, *M)) { -    errs() << "Error emitting bitcode to file '" << UniqueFilepath << "'!\n"; -    exit(1); -  } -  return UniqueFilepath; -} - -/// Prints the Chunk Indexes with the following format: [start, end], if -/// chunk is at minimum size (1), then it just displays [start]. -inline void printChunks(std::vector<Chunk> Chunks, bool Oneline = false) { -  for (auto C : Chunks) { -    if (!Oneline) -      outs() << '\t'; -    outs() << "[" << C.begin; -    if (C.end - C.begin != 0) -      outs() << "," << C.end; -    outs() << "]"; -    if (!Oneline) -      outs() << '\n'; -  } -} - -/// Counts the amount of lines for a given file -inline unsigned getLines(StringRef Filepath) { -  unsigned Lines = 0; -  std::string CurrLine; -  std::ifstream FileStream(Filepath); - -  while (std::getline(FileStream, CurrLine)) -    ++Lines; - -  return Lines; -} - -/// Splits Chunks in half and prints them. -/// If unable to split (when chunk size is 1) returns false. -inline bool increaseGranularity(std::vector<Chunk> &Chunks) { -  outs() << "Increasing granularity..."; -  std::vector<Chunk> NewChunks; -  bool SplitOne = false; - -  for (auto &C : Chunks) { -    if (C.end - C.begin == 0) -      NewChunks.push_back(C); -    else { -      int Half = (C.begin + C.end) / 2; -      NewChunks.push_back({C.begin, Half}); -      NewChunks.push_back({Half + 1, C.end}); -      SplitOne = true; -    } -  } -  if (SplitOne) { -    Chunks = NewChunks; -    outs() << "Success! New Chunks:\n"; -    printChunks(Chunks); -  } -  return SplitOne; -} -  namespace llvm { -/// This class implements the Delta Debugging algorithm, it receives a set of -/// Targets (e.g. Functions, Instructions, Basic Blocks, etc.) and splits them -/// in half; these chunks of targets are then tested while ignoring one chunk, -/// if a chunk is proven to be uninteresting (i.e. fails the test) it is -/// removed from consideration. Otherwise, the algorithm will attempt to split -/// the Chunks in half and start the process again, until it can't split chunks +/// This function implements the Delta Debugging algorithm, it receives a +/// number of Targets (e.g. Functions, Instructions, Basic Blocks, etc.) and +/// splits them in half; these chunks of targets are then tested while ignoring +/// one chunk, if a chunk is proven to be uninteresting (i.e. fails the test) +/// it is removed from consideration. The algorithm will attempt to split the +/// Chunks in half and start the process again until it can't split chunks  /// anymore.  /// -/// The class is intended to be called statically by the DeltaManager class -/// alongside a specialized delta pass (e.g. RemoveFunctions) passed as a -/// template. -/// This specialized pass implements two functions: -///   * getTargetCount, which returns the amount of targets (e.g. Functions) -///     there are in the Module. -///   * extractChunksFromModule, which clones the given Module and modifies it -///     so it only contains Chunk Targets. +/// This function is intended to be called by each specialized delta pass (e.g. +/// RemoveFunctions) and receives three key parameters: +/// * Test: The main TestRunner instance which is used to run the provided +/// interesting-ness test, as well as to store and access the reduced Program. +/// * Targets: The amount of Targets that are going to be reduced by the +/// algorithm, for example, the RemoveGlobalVars pass would send the amount of +/// initialized GVs. +/// * ExtractChunksFromModule: A function used to tailor the main program so it +/// only contains Targets that are inside Chunks of the given iteration. +/// Note: This function is implemented by each specialized Delta pass  /// -/// Other implementations of the Delta Debugging algorithm can be found in the -/// CReduce, Delta, and Lithium projects. -template <class P> class Delta { -public: -  /// Runs the Delta Debugging algorithm, splits the code into chunks and -  /// reduces the amount of chunks that are considered interesting by the -  /// given test. -  static void run(TestRunner &Test) { -    int TargetCount = P::getTargetCount(Test.getProgram()); -    std::vector<Chunk> Chunks = {{1, TargetCount}}; -    std::set<Chunk> UninterestingChunks; -    std::unique_ptr<Module> ReducedProgram; - -    if (Test.run(Test.getReducedFilepath())) -      increaseGranularity(Chunks); -    else { -      outs() << "Error: input file isnt interesting\n"; -      exit(1); -    } - -    do { -      UninterestingChunks = {}; -      for (int I = Chunks.size() - 1; I >= 0; --I) { -        std::vector<Chunk> CurrentChunks; - -        for (auto C : Chunks) -          if (!UninterestingChunks.count(C) && C != Chunks[I]) -            CurrentChunks.push_back(C); - -        // Generate Module with only Targets inside Current Chunks -        std::unique_ptr<Module> CurrentProgram = -            P::extractChunksFromModule(CurrentChunks, Test.getProgram()); -        // Write Module to tmp file -        SmallString<128> CurrentFilepath = -            createTmpFile(CurrentProgram.get(), Test.getTmpDir()); - -        outs() << "Testing with: "; -        printChunks(CurrentChunks, /*Oneline=*/true); -        outs() << " | " << sys::path::filename(CurrentFilepath); - -        // Current Chunks aren't interesting -        if (!Test.run(CurrentFilepath)) { -          outs() << "\n"; -          continue; -        } - -        // We only care about interesting chunks if they reduce the testcase -        if (getLines(CurrentFilepath) < getLines(Test.getReducedFilepath())) { -          UninterestingChunks.insert(Chunks[I]); -          Test.setReducedFilepath(CurrentFilepath); -          ReducedProgram = std::move(CurrentProgram); -          outs() << " **** SUCCESS | lines: " << getLines(CurrentFilepath); -        } -        outs() << "\n"; -      } -      // Delete uninteresting chunks -      auto UnwantedChunks = Chunks.end(); -      UnwantedChunks = std::remove_if(Chunks.begin(), Chunks.end(), -                                      [UninterestingChunks](const Chunk &C) { -                                        return UninterestingChunks.count(C); -                                      }); -      Chunks.erase(UnwantedChunks, Chunks.end()); -    } while (!UninterestingChunks.empty() || increaseGranularity(Chunks)); - -    // If we reduced the testcase replace it -    if (ReducedProgram) -      Test.setProgram(std::move(ReducedProgram)); -    outs() << "Couldn't increase anymore.\n"; -  } -}; +/// Other implementations of the Delta Debugging algorithm can also be found in +/// the CReduce, Delta, and Lithium projects. +void runDeltaPass( +    TestRunner &Test, int Targets, +    std::function<std::unique_ptr<Module>(std::vector<Chunk>, Module *)> +        ExtractChunksFromModule);  } // namespace llvm diff --git a/llvm/tools/llvm-reduce/deltas/RemoveFunctions.cpp b/llvm/tools/llvm-reduce/deltas/RemoveFunctions.cpp index 105838f0689..e08c7b99f38 100644 --- a/llvm/tools/llvm-reduce/deltas/RemoveFunctions.cpp +++ b/llvm/tools/llvm-reduce/deltas/RemoveFunctions.cpp @@ -1,4 +1,4 @@ -//===- llvm-reduce.cpp - The LLVM Delta Reduction utility -----------------===// +//===- RemoveFunctions.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. @@ -6,33 +6,30 @@  //  //===----------------------------------------------------------------------===//  // -// This file is a Specialized Delta Pass, which removes the functions that are -// not in the provided function-chunks. +// This file implements a function which calls the Generic Delta pass in order +// to reduce functions (and any instruction that calls it) in the provided +// Module.  //  //===----------------------------------------------------------------------===//  #include "RemoveFunctions.h" -using namespace llvm; -  /// Removes all the Defined Functions (as well as their calls)  /// that aren't inside any of the desired Chunks.  /// @returns the Module stripped of out-of-chunk functions -std::unique_ptr<Module> -RemoveFunctions::extractChunksFromModule(std::vector<Chunk> ChunksToKeep, -                                         Module *Program) { +static std::unique_ptr<Module> +extractFunctionsFromModule(std::vector<Chunk> ChunksToKeep, Module *Program) {    std::unique_ptr<Module> Clone = CloneModule(*Program);    // Get functions inside desired chunks    std::set<Function *> FuncsToKeep;    int I = 0, FunctionCount = 1;    for (auto &F : *Clone) { -    if (!F.isDeclaration()) { +    if (!F.isDeclaration() && I < ChunksToKeep.size()) {        if (FunctionCount >= ChunksToKeep[I].begin && -          FunctionCount <= ChunksToKeep[I].end) { +          FunctionCount <= ChunksToKeep[I].end)          FuncsToKeep.insert(&F); -      } -      if (FunctionCount >= ChunksToKeep[I].end) +      if (FunctionCount == ChunksToKeep[I].end)          ++I;        ++FunctionCount;      } @@ -68,11 +65,11 @@ RemoveFunctions::extractChunksFromModule(std::vector<Chunk> ChunksToKeep,  }  /// Counts the amount of non-declaration functions and prints their -/// respective index & name -int RemoveFunctions::getTargetCount(Module *Program) { +/// respective name & index +static int countFunctions(Module *Program) {    // TODO: Silence index with --quiet flag    outs() << "----------------------------\n"; -  outs() << "Chunk Index Reference:\n"; +  outs() << "Function Index Reference:\n";    int FunctionCount = 0;    for (auto &F : *Program)      if (!F.isDeclaration()) { @@ -82,3 +79,8 @@ int RemoveFunctions::getTargetCount(Module *Program) {    outs() << "----------------------------\n";    return FunctionCount;  } + +void llvm::removeFunctionsDeltaPass(TestRunner &Test) { +  int FunctionCount = countFunctions(Test.getProgram()); +  runDeltaPass(Test, FunctionCount, extractFunctionsFromModule); +}
\ No newline at end of file diff --git a/llvm/tools/llvm-reduce/deltas/RemoveFunctions.h b/llvm/tools/llvm-reduce/deltas/RemoveFunctions.h index 3a6e501dc93..ca7b55c982f 100644 --- a/llvm/tools/llvm-reduce/deltas/RemoveFunctions.h +++ b/llvm/tools/llvm-reduce/deltas/RemoveFunctions.h @@ -1,4 +1,4 @@ -//===- llvm-reduce.cpp - The LLVM Delta Reduction utility -----------------===// +//===- RemoveFunctions.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. @@ -6,8 +6,9 @@  //  //===----------------------------------------------------------------------===//  // -// This file is a Specialized Delta Pass, which removes the functions that are -// not in the provided function-chunks. +// This file implements a function which calls the Generic Delta pass in order +// to reduce functions (and any instruction that calls it) in the provided +// Module.  //  //===----------------------------------------------------------------------===// @@ -15,14 +16,5 @@  #include "llvm/Transforms/Utils/Cloning.h"  namespace llvm { - -class RemoveFunctions { -public: -  /// Outputs the number of Functions in the given Module -  static int getTargetCount(Module *Program); -  /// Clones module and returns it with chunk functions only -  static std::unique_ptr<Module> -  extractChunksFromModule(std::vector<Chunk> ChunksToKeep, Module *Program); -}; - +void removeFunctionsDeltaPass(TestRunner &Test);  } // namespace llvm diff --git a/llvm/tools/llvm-reduce/deltas/RemoveGlobalVars.cpp b/llvm/tools/llvm-reduce/deltas/RemoveGlobalVars.cpp new file mode 100644 index 00000000000..28d501d4d83 --- /dev/null +++ b/llvm/tools/llvm-reduce/deltas/RemoveGlobalVars.cpp @@ -0,0 +1,79 @@ +//===- RemoveGlobalVars.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 initialized Global Variables in the provided Module. +// +//===----------------------------------------------------------------------===// + +#include "RemoveGlobalVars.h" + +/// Removes all the Initialized GVs that aren't inside the desired Chunks. +/// @returns the Module stripped of out-of-chunk GVs +static std::unique_ptr<Module> +extractGVsFromModule(std::vector<Chunk> ChunksToKeep, Module *Program) { +  std::unique_ptr<Module> Clone = CloneModule(*Program); + +  // Get GVs inside desired chunks +  std::set<GlobalVariable *> GVsToKeep; +  int I = 0, GVCount = 1; +  for (auto &GV : Clone->globals()) { +    if (GV.hasInitializer() && I < ChunksToKeep.size()) { +      if (GVCount >= ChunksToKeep[I].begin && GVCount <= ChunksToKeep[I].end) +        GVsToKeep.insert(&GV); +      if (GVCount == ChunksToKeep[I].end) +        ++I; +      ++GVCount; +    } +  } + +  // Replace out-of-chunk GV uses with undef +  std::vector<GlobalVariable *> ToRemove; +  std::vector<Instruction *> InstToRemove; +  for (auto &GV : Clone->globals()) +    if (GV.hasInitializer() && !GVsToKeep.count(&GV)) { +      for (auto U : GV.users()) +        if (auto *Inst = dyn_cast<Instruction>(U)) +          InstToRemove.push_back(Inst); + +      GV.replaceAllUsesWith(UndefValue::get(GV.getType())); +      ToRemove.push_back(&GV); +    } + +  // Delete Instruction uses of unwanted GVs +  for (auto *Inst : InstToRemove) { +    Inst->replaceAllUsesWith(UndefValue::get(Inst->getType())); +    Inst->eraseFromParent(); +  } + +  for (auto *GV : ToRemove) +    GV->eraseFromParent(); + +  return Clone; +} + +/// Counts the amount of initialized GVs and displays their +/// respective name & index +static int countGVs(Module *Program) { +  // TODO: Silence index with --quiet flag +  outs() << "----------------------------\n"; +  outs() << "GlobalVariable Index Reference:\n"; +  int GVCount = 0; +  for (auto &GV : Program->globals()) +    if (GV.hasInitializer()) { +      ++GVCount; +      outs() << "\t" << GVCount << ": " << GV.getName() << "\n"; +    } +  outs() << "----------------------------\n"; +  return GVCount; +} + +void llvm::removeGlobalsDeltaPass(TestRunner &Test) { +  int GVCount = countGVs(Test.getProgram()); +  runDeltaPass(Test, GVCount, extractGVsFromModule); +} diff --git a/llvm/tools/llvm-reduce/deltas/RemoveGlobalVars.h b/llvm/tools/llvm-reduce/deltas/RemoveGlobalVars.h new file mode 100644 index 00000000000..b53f4e78d4c --- /dev/null +++ b/llvm/tools/llvm-reduce/deltas/RemoveGlobalVars.h @@ -0,0 +1,20 @@ +//===- RemoveGlobalVars.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 initialized Global Variables in the provided Module. +// +//===----------------------------------------------------------------------===// + +#include "Delta.h" +#include "llvm/IR/Value.h" +#include "llvm/Transforms/Utils/Cloning.h" + +namespace llvm { +void removeGlobalsDeltaPass(TestRunner &Test); +} // namespace llvm diff --git a/llvm/tools/llvm-reduce/llvm-reduce.cpp b/llvm/tools/llvm-reduce/llvm-reduce.cpp index 7892abdc38f..d7da0d88eea 100644 --- a/llvm/tools/llvm-reduce/llvm-reduce.cpp +++ b/llvm/tools/llvm-reduce/llvm-reduce.cpp @@ -8,8 +8,9 @@  //  // This program tries to reduce an IR test case for a given interesting-ness  // test. It runs multiple delta debugging passes in order to minimize the input -// file. It's worth noting that this is a *temporary* tool that will eventually -// be integrated into the bugpoint tool itself. +// file. It's worth noting that this is a part of the bugpoint redesign +// proposal, and thus a *temporary* tool that will eventually be integrated +// into the bugpoint tool itself.  //  //===----------------------------------------------------------------------===//  | 

