llvm.org GIT mirror llvm / 8afd81d
Added Delta IR Reduction Tool Summary: Tool parses input IR file, and runs the delta debugging algorithm to reduce the functions inside the input file. Reviewers: alexshap, chandlerc Subscribers: mgorny, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63672 llvm-svn: 368071 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@368358 91177308-0d34-0410-b5e6-96231b3b80d8 Diego Trevino Ferrer a month ago
15 changed file(s) with 806 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 # Bugpoint Redesign
1 Author: Diego Treviño (diegotf@google.com)
2
3 Date: 2019-06-05
4
5 Status: Draft
6
7
8 ## Introduction
9 As use of bugpoint has grown several areas of improvement have been identified
10 through years of use: confusing to use, slow, it doesn’t always produce high
11 quality test cases, etc. This document proposes a new approach with a narrower
12 focus: minimization of IR test cases.
13
14
15 ## Proposed New Design
16
17
18 ### Narrow focus: test-case reduction
19 The main focus will be a code reduction strategy to obtain much smaller test
20 cases that still have the same property as the original one. This will be done
21 via classic delta debugging and by adding some IR-specific reductions (e.g.
22 replacing globals, removing unused instructions, etc), similar to what
23 already exists, but with more in-depth minimization.
24
25
26 Granted, if the community differs on this proposal, the legacy code could still
27 be present in the tool, but with the caveat of still being documented and
28 designed towards delta reduction.
29
30
31 ### Command-Line Options
32 We are proposing to reduce the plethora of bugpoint’s options to just two: an
33 interesting-ness test and the arguments for said test, similar to other delta
34 reduction tools such as CReduce, Delta, and Lithium; the tool should feel less
35 cluttered, and there should also be no uncertainty about how to operate it.
36
37
38 The interesting-ness test that’s going to be run to reduce the code is given
39 by name:
40 `--test=`
41 If a `--test` option is not given, the program exits; this option is similar
42 to bugpoint’s current `-compile-custom` option, which lets the user run a
43 custom script.
44
45
46 The interesting-ness test would be defined as a script that returns 0 when the
47 IR achieves a user-defined behaviour (e.g. failure to compile on clang) and a
48 nonzero value when otherwise. Leaving the user the freedom to determine what is
49 and isn’t interesting to the tool, and thus, streamlining the process of
50 reducing a test-case.
51
52
53 If the test accepts any arguments (excluding the input ll/bc file), they are
54 given via the following flag:
55 `--test_args=`
56 If unspecified, the test is run as given. It’s worth noting that the input file
57 would be passed as a parameter to the test, similar how `-compile-custom`
58 currently operates.
59
60
61 ### Implementation
62 The tool would behave similar to CReduce’s functionality in that it would have a
63 list of passes that try to minimize the given test-case. We should be able to
64 modularize the tool’s behavior, as well as making it easier to maintain and
65 expand.
66
67
68 The first version of this redesign would try to:
69
70
71 * Discard functions, instructions and metadata that don’t influence the
72 interesting-ness test
73 * Remove unused parameters from functions
74 * Eliminate unvisited conditional paths
75 * Rename variables to more regular ones (such as “a”, “b”, “c”, etc.)
76
77
78 Once these passes are implemented, more meaningful reductions (such as type
79 reduction) would be added to the tool, to even further reduce IR.
80
81
82 ## Background on historical bugpoint issues
83
84
85 ### Root Cause Analysis
86 Presently, bugpoint takes a long time to find the source problem in a given IR
87 file, mainly due to the fact that it tries to debug the input by running
88 various strategies to classify the bug, which in turn run multiple optimizer
89 and compilation passes over the input, taking up a lot of time. Furthermore,
90 when the IR crashes, it tries to reduce it by performing some sub-optimal
91 passes (e.g. a lot of unreachable blocks), and sometimes even fails to minimize
92 at all.
93
94
95 ### "Quirky" Interface
96 Bugpoint’s current interface overwhelms and confuses the user, the help screen
97 alone ends up confusing rather providing guidance, as seen below:
98
99 ![Bugpoint's help option showcase](https://lh6.googleusercontent.com/sbpaSVHzpVVZKKAgHL9gvfzTWdgh3ju0KiDYql6WmWZfDYrdauOJMcuo9PP_V1dq8JQfMHOSKTv3lJcSpVytUyU8r5tJ2KTlGB0b2ve7jsZ3nVX8K8ItAbsA0JWkFKw67VJnq99m)
100
101 And, not only are there numerous features and options, but some of them also
102 work in unexpected ways and most of the time the user ends up using a custom
103 script. Pruning and simplifying the interface will be worth considering in
104 order to make the tool more useful in the general case and easier to maintain.
8888 llvm-rc
8989 llvm-readobj
9090 llvm-readelf
91 llvm-reduce
9192 llvm-rtdyld
9293 llvm-size
9394 llvm-split
0 #!/usr/bin/env python
1
2 import sys
3
4 input = open(sys.argv[1], "r")
5 for line in input:
6 if "@interesting" in line:
7 sys.exit(0)
8
9 sys.exit(1) # IR isn't interesting
0 ; Test that llvm-reduce can remove uninteresting functions as well as
1 ; their InstCalls.
2 ;
3 ; RUN: llvm-reduce --test %p/Inputs/remove-funcs.py %s
4 ; RUN: cat reduced.ll | FileCheck %s
5 ; REQUIRES: plugins, shell
6
7 ; CHECK-NOT: uninteresting1()
8 define i32 @uninteresting1() {
9 entry:
10 ret i32 0
11 }
12
13 ; CHECK: interesting()
14 define i32 @interesting() {
15 entry:
16 ; CHECK: call i32 @interesting()
17 %call2 = call i32 @interesting()
18 ; CHECK-NOT: call i32 @uninteresting1()
19 %call = call i32 @uninteresting1()
20 ret i32 5
21 }
22
23 ; CHECK-NOT: uninteresting2()
24 define i32 @uninteresting2() {
25 entry:
26 ret i32 0
27 }
28
29 ; CHECK-NOT: uninteresting3()
30 define i32 @uninteresting3() {
31 entry:
32 ret i32 10
33 }
4747 llvm-pdbutil
4848 llvm-profdata
4949 llvm-rc
50 llvm-reduce
5051 llvm-rtdyld
5152 llvm-size
5253 llvm-split
0 set(LLVM_LINK_COMPONENTS
1 AllTargetsAsmParsers
2 AllTargetsCodeGens
3 AllTargetsDescs
4 AllTargetsInfos
5 IRReader
6 Support
7 Target
8 TransformUtils
9 )
10
11 # Support plugins.
12 set(LLVM_NO_DEAD_STRIP 1)
13
14 add_llvm_tool(llvm-reduce
15 llvm-reduce.cpp
16 TestRunner.cpp
17 deltas/Delta.cpp
18 deltas/ReduceFunctions.cpp
19
20 DEPENDS
21 intrinsics_gen
22 )
23 export_executable_symbols(llvm-reduce)
0 //===- DeltaManager.h - Runs Delta Passes to reduce Input -----------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file calls each specialized Delta pass in order to reduce the input IR
9 // file.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "TestRunner.h"
14 #include "deltas/Delta.h"
15 #include "deltas/ReduceFunctions.h"
16
17 namespace llvm {
18
19 inline void runDeltaPasses(TestRunner &Tester) {
20 reduceFunctionsDeltaPass(Tester);
21 // TODO: Implement the remaining Delta Passes
22 }
23
24 } // namespace llvm
0 ;===- ./tools/llvm-reduce/LLVMBuild.txt ------------------------*- Conf -*--===;
1 ;
2 ; Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 ; See https://llvm.org/LICENSE.txt for license information.
4 ; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 ;
6 ;===------------------------------------------------------------------------===;
7 ;
8 ; This is an LLVMBuild description file for the components in this subdirectory.
9 ;
10 ; For more information on the LLVMBuild system, please see:
11 ;
12 ; http://llvm.org/docs/LLVMBuild.html
13 ;
14 ;===------------------------------------------------------------------------===;
15
16 [component_0]
17 type = Tool
18 name = llvm-reduce
19 parent = Tools
20 required_libraries =
21 BitReader
22 IRReader
23 all-targets
0 //===-- TestRunner.cpp ----------------------------------------------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7
8 #include "TestRunner.h"
9
10 using namespace llvm;
11
12 /// Gets Current Working Directory and tries to create a Tmp Directory
13 static SmallString<128> initializeTmpDirectory() {
14 SmallString<128> CWD;
15 if (std::error_code EC = sys::fs::current_path(CWD)) {
16 errs() << "Error getting current directory: " << EC.message() << "!\n";
17 exit(1);
18 }
19
20 SmallString<128> TmpDirectory;
21 sys::path::append(TmpDirectory, CWD, "tmp");
22 if (std::error_code EC = sys::fs::create_directory(TmpDirectory))
23 errs() << "Error creating tmp directory: " << EC.message() << "!\n";
24
25 return TmpDirectory;
26 }
27
28 TestRunner::TestRunner(StringRef TestName, std::vector TestArgs,
29 StringRef ReducedFilepath)
30 : TestName(TestName), TestArgs(std::move(TestArgs)),
31 ReducedFilepath(ReducedFilepath) {
32 TmpDirectory = initializeTmpDirectory();
33 }
34
35 /// Runs the interestingness test, passes file to be tested as first argument
36 /// and other specified test arguments after that.
37 int TestRunner::run(StringRef Filename) {
38 std::vector ProgramArgs;
39 ProgramArgs.push_back(TestName);
40 ProgramArgs.push_back(Filename);
41
42 for (auto Arg : TestArgs)
43 ProgramArgs.push_back(Arg.c_str());
44
45 Optional Redirects[3]; // STDIN, STDOUT, STDERR
46 int Result = sys::ExecuteAndWait(TestName, ProgramArgs, None, Redirects);
47
48 if (Result < 0) {
49 Error E = make_error("Error running interesting-ness test\n",
50 inconvertibleErrorCode());
51 outs() << toString(std::move(E));
52 exit(1);
53 }
54
55 return !Result;
56 }
0 //===-- tools/llvm-reduce/TestRunner.h ---------------------------*- C++ -*-===/
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7
8 #ifndef LLVM_TOOLS_LLVMREDUCE_TESTRUNNER_H
9 #define LLVM_TOOLS_LLVMREDUCE_TESTRUNNER_H
10
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/IR/Module.h"
13 #include "llvm/Support/Error.h"
14 #include "llvm/Support/FileSystem.h"
15 #include "llvm/Support/Path.h"
16 #include "llvm/Support/Program.h"
17 #include
18
19 namespace llvm {
20
21 // This class contains all the info necessary for running the provided
22 // interesting-ness test, as well as the most reduced module and its
23 // respective filename.
24 class TestRunner {
25 public:
26 TestRunner(StringRef TestName, std::vector TestArgs,
27 StringRef ReducedFilepath);
28
29 /// Runs the interesting-ness test for the specified file
30 /// @returns 0 if test was successful, 1 if otherwise
31 int run(StringRef Filename);
32
33 /// Filename to the most reduced testcase
34 StringRef getReducedFilepath() const { return ReducedFilepath; }
35 /// Directory where tmp files are created
36 StringRef getTmpDir() const { return TmpDirectory; }
37 /// Returns the most reduced version of the original testcase
38 Module *getProgram() const { return Program.get(); }
39
40 void setReducedFilepath(SmallString<128> F) {
41 ReducedFilepath = std::move(F);
42 }
43 void setProgram(std::unique_ptr P) { Program = std::move(P); }
44
45 private:
46 SmallString<128> TestName;
47 std::vector TestArgs;
48 SmallString<128> ReducedFilepath;
49 SmallString<128> TmpDirectory;
50 std::unique_ptr Program;
51 };
52
53 } // namespace llvm
54
55 #endif
0 //===- Delta.cpp - Delta Debugging Algorithm Implementation ---------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file contains the implementation for the Delta Debugging Algorithm:
9 // it splits a given set of Targets (i.e. Functions, Instructions, BBs, etc.)
10 // into chunks and tries to reduce the number chunks that are interesting.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "Delta.h"
15 #include "llvm/ADT/STLExtras.h"
16
17 /// Writes IR code to the given Filepath
18 static bool writeProgramToFile(StringRef Filepath, int FD, const Module &M) {
19 ToolOutputFile Out(Filepath, FD);
20 M.print(Out.os(), /*AnnotationWriter=*/nullptr);
21 Out.os().close();
22
23 if (!Out.os().has_error()) {
24 Out.keep();
25 return false;
26 }
27 return true;
28 }
29
30 /// Creates a temporary (and unique) file inside the tmp folder and writes
31 /// the given module IR.
32 static SmallString<128> createTmpFile(Module *M, StringRef TmpDir) {
33 SmallString<128> UniqueFilepath;
34 int UniqueFD;
35
36 SmallString<128> TmpFilepath;
37 sys::path::append(TmpFilepath, TmpDir, "tmp-%%%.ll");
38 std::error_code EC =
39 sys::fs::createUniqueFile(TmpFilepath, UniqueFD, UniqueFilepath);
40 if (EC) {
41 errs() << "Error making unique filename: " << EC.message() << "!\n";
42 exit(1);
43 }
44
45 if (writeProgramToFile(UniqueFilepath, UniqueFD, *M)) {
46 errs() << "Error emitting bitcode to file '" << UniqueFilepath << "'!\n";
47 exit(1);
48 }
49 return UniqueFilepath;
50 }
51
52 /// Prints the Chunk Indexes with the following format: [start, end], if
53 /// chunk is at minimum size (1), then it just displays [start].
54 static void printChunks(std::vector Chunks, bool Oneline = false) {
55 if (Chunks.empty()) {
56 outs() << "No Chunks";
57 return;
58 }
59
60 for (auto C : Chunks) {
61 if (!Oneline)
62 outs() << '\t';
63 C.print();
64 if (!Oneline)
65 outs() << '\n';
66 }
67 }
68
69 /// Counts the amount of lines for a given file
70 static unsigned getLines(StringRef Filepath) {
71 unsigned Lines = 0;
72 std::string CurrLine;
73 std::ifstream FileStream(Filepath);
74
75 while (std::getline(FileStream, CurrLine))
76 ++Lines;
77
78 return Lines;
79 }
80
81 /// Splits Chunks in half and prints them.
82 /// If unable to split (when chunk size is 1) returns false.
83 static bool increaseGranularity(std::vector &Chunks) {
84 outs() << "Increasing granularity...";
85 std::vector NewChunks;
86 bool SplitOne = false;
87
88 for (auto &C : Chunks) {
89 if (C.end - C.begin == 0)
90 NewChunks.push_back(C);
91 else {
92 unsigned Half = (C.begin + C.end) / 2;
93 NewChunks.push_back({C.begin, Half});
94 NewChunks.push_back({Half + 1, C.end});
95 SplitOne = true;
96 }
97 }
98 if (SplitOne) {
99 Chunks = NewChunks;
100 outs() << "Success! New Chunks:\n";
101 printChunks(Chunks);
102 }
103 return SplitOne;
104 }
105
106 /// Runs the Delta Debugging algorithm, splits the code into chunks and
107 /// reduces the amount of chunks that are considered interesting by the
108 /// given test.
109 void llvm::runDeltaPass(
110 TestRunner &Test, unsigned Targets,
111 std::function &, Module *)>
112 ExtractChunksFromModule) {
113 if (!Targets) {
114 outs() << "\nNothing to reduce\n";
115 return;
116 }
117
118 std::vector Chunks = {{1, Targets}};
119 std::set UninterestingChunks;
120 std::unique_ptr ReducedProgram;
121
122 if (!Test.run(Test.getReducedFilepath())) {
123 outs() << "\nInput isn't interesting! Verify interesting-ness test\n";
124 return;
125 }
126
127 if (!increaseGranularity(Chunks)) {
128 outs() << "\nAlready at minimum size. Cannot reduce anymore.\n";
129 return;
130 }
131
132 do {
133 UninterestingChunks = {};
134 for (int I = Chunks.size() - 1; I >= 0; --I) {
135 std::vector CurrentChunks;
136
137 for (auto C : Chunks)
138 if (!UninterestingChunks.count(C) && C != Chunks[I])
139 CurrentChunks.push_back(C);
140
141 if (CurrentChunks.empty())
142 continue;
143
144 // Clone module before hacking it up..
145 std::unique_ptr Clone = CloneModule(*Test.getProgram());
146 // Generate Module with only Targets inside Current Chunks
147 ExtractChunksFromModule(CurrentChunks, Clone.get());
148 // Write Module to tmp file
149 SmallString<128> CurrentFilepath =
150 createTmpFile(Clone.get(), Test.getTmpDir());
151
152 outs() << "Testing with: ";
153 printChunks(CurrentChunks, /*Oneline=*/true);
154 outs() << " | " << sys::path::filename(CurrentFilepath);
155
156 // Current Chunks aren't interesting
157 if (!Test.run(CurrentFilepath)) {
158 outs() << "\n";
159 continue;
160 }
161
162 UninterestingChunks.insert(Chunks[I]);
163 Test.setReducedFilepath(CurrentFilepath);
164 ReducedProgram = std::move(Clone);
165 outs() << " **** SUCCESS | lines: " << getLines(CurrentFilepath) << "\n";
166 }
167 // Delete uninteresting chunks
168 erase_if(Chunks, [&UninterestingChunks](const Chunk &C) {
169 return UninterestingChunks.count(C);
170 });
171
172 } while (!UninterestingChunks.empty() || increaseGranularity(Chunks));
173
174 // If we reduced the testcase replace it
175 if (ReducedProgram)
176 Test.setProgram(std::move(ReducedProgram));
177 outs() << "Couldn't increase anymore.\n";
178 }
0 //===- Delta.h - Delta Debugging Algorithm Implementation -----------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file contains the implementation for the Delta Debugging Algorithm:
9 // it splits a given set of Targets (i.e. Functions, Instructions, BBs, etc.)
10 // into chunks and tries to reduce the number chunks that are interesting.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_TOOLS_LLVMREDUCE_LLVMREDUCE_DELTA_H
15 #define LLVM_TOOLS_LLVMREDUCE_LLVMREDUCE_DELTA_H
16
17 #include "../TestRunner.h"
18 #include "llvm/IR/Verifier.h"
19 #include "llvm/Support/FileSystem.h"
20 #include "llvm/Support/Path.h"
21 #include "llvm/Support/ScopedPrinter.h"
22 #include "llvm/Support/ToolOutputFile.h"
23 #include "llvm/Transforms/Utils/Cloning.h"
24 #include
25 #include
26 #include
27
28 using namespace llvm;
29
30 struct Chunk {
31 unsigned begin;
32 unsigned end;
33
34 /// Helper function to verify if a given Target-index is inside the Chunk
35 bool contains(unsigned Index) const { return Index >= begin && Index <= end; }
36
37 void print() const {
38 outs() << "[" << begin;
39 if (end - begin != 0)
40 outs() << "," << end;
41 outs() << "]";
42 }
43
44 /// Operator when populating CurrentChunks in Generic Delta Pass
45 friend bool operator!=(const Chunk &C1, const Chunk &C2) {
46 return C1.begin != C2.begin || C1.end != C2.end;
47 }
48
49 /// Operator used for sets
50 friend bool operator<(const Chunk &C1, const Chunk &C2) {
51 return std::tie(C1.begin, C1.end) < std::tie(C2.begin, C2.end);
52 }
53 };
54
55 namespace llvm {
56
57 /// This function implements the Delta Debugging algorithm, it receives a
58 /// number of Targets (e.g. Functions, Instructions, Basic Blocks, etc.) and
59 /// splits them in half; these chunks of targets are then tested while ignoring
60 /// one chunk, if a chunk is proven to be uninteresting (i.e. fails the test)
61 /// it is removed from consideration. The algorithm will attempt to split the
62 /// Chunks in half and start the process again until it can't split chunks
63 /// anymore.
64 ///
65 /// This function is intended to be called by each specialized delta pass (e.g.
66 /// RemoveFunctions) and receives three key parameters:
67 /// * Test: The main TestRunner instance which is used to run the provided
68 /// interesting-ness test, as well as to store and access the reduced Program.
69 /// * Targets: The amount of Targets that are going to be reduced by the
70 /// algorithm, for example, the RemoveGlobalVars pass would send the amount of
71 /// initialized GVs.
72 /// * ExtractChunksFromModule: A function used to tailor the main program so it
73 /// only contains Targets that are inside Chunks of the given iteration.
74 /// Note: This function is implemented by each specialized Delta pass
75 ///
76 /// Other implementations of the Delta Debugging algorithm can also be found in
77 /// the CReduce, Delta, and Lithium projects.
78 void runDeltaPass(TestRunner &Test, unsigned Targets,
79 std::function &, Module *)>
80 ExtractChunksFromModule);
81 } // namespace llvm
82
83 #endif
0 //===- ReduceFunctions.cpp - Specialized Delta Pass -----------------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file implements a function which calls the Generic Delta pass in order
9 // to reduce functions (and any instruction that calls it) in the provided
10 // Module.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "ReduceFunctions.h"
15
16 /// Removes all the Defined Functions (as well as their calls)
17 /// that aren't inside any of the desired Chunks.
18 /// @returns the Module stripped of out-of-chunk functions
19 static void extractFunctionsFromModule(const std::vector &ChunksToKeep,
20 Module *Program) {
21 // Get functions inside desired chunks
22 std::set FuncsToKeep;
23 unsigned I = 0, FunctionCount = 0;
24 for (auto &F : *Program)
25 if (!F.isDeclaration() && I < ChunksToKeep.size()) {
26 if (ChunksToKeep[I].contains(++FunctionCount))
27 FuncsToKeep.insert(&F);
28 if (FunctionCount == ChunksToKeep[I].end)
29 ++I;
30 }
31
32 // Delete out-of-chunk functions, and replace their calls with undef
33 std::vector FuncsToRemove;
34 for (auto &F : *Program)
35 if (!F.isDeclaration() && !FuncsToKeep.count(&F)) {
36 F.replaceAllUsesWith(UndefValue::get(F.getType()));
37 FuncsToRemove.push_back(&F);
38 }
39
40 for (auto *F : FuncsToRemove)
41 F->eraseFromParent();
42
43 // Delete instructions with undef calls
44 std::vector InstToRemove;
45 for (auto &F : *Program)
46 for (auto &BB : F)
47 for (auto &I : BB)
48 if (auto *Call = dyn_cast(&I))
49 if (!Call->getCalledFunction()) {
50 // Instruction might be stored / used somewhere else
51 I.replaceAllUsesWith(UndefValue::get(I.getType()));
52 InstToRemove.push_back(&I);
53 }
54
55 for (auto *I : InstToRemove)
56 I->eraseFromParent();
57 }
58
59 /// Counts the amount of non-declaration functions and prints their
60 /// respective name & index
61 static unsigned countDefinedFunctions(Module *Program) {
62 // TODO: Silence index with --quiet flag
63 outs() << "----------------------------\n";
64 outs() << "Function Index Reference:\n";
65 unsigned FunctionCount = 0;
66 for (auto &F : *Program)
67 if (!F.isDeclaration())
68 outs() << "\t" << ++FunctionCount << ": " << F.getName() << "\n";
69
70 outs() << "----------------------------\n";
71 return FunctionCount;
72 }
73
74 void llvm::reduceFunctionsDeltaPass(TestRunner &Test) {
75 outs() << "*** Reducing Functions...\n";
76 unsigned Functions = countDefinedFunctions(Test.getProgram());
77 runDeltaPass(Test, Functions, extractFunctionsFromModule);
78 outs() << "----------------------------\n";
79 }
0 //===- ReduceFunctions.h - Specialized Delta Pass -------------------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file implements a function which calls the Generic Delta pass in order
9 // to reduce functions (and any instruction that calls it) in the provided
10 // Module.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "Delta.h"
15 #include "llvm/Transforms/Utils/Cloning.h"
16
17 namespace llvm {
18 void reduceFunctionsDeltaPass(TestRunner &Test);
19 } // namespace llvm
0 //===- llvm-reduce.cpp - The LLVM Delta Reduction utility -----------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This program tries to reduce an IR test case for a given interesting-ness
9 // test. It runs multiple delta debugging passes in order to minimize the input
10 // file. It's worth noting that this is a part of the bugpoint redesign
11 // proposal, and thus a *temporary* tool that will eventually be integrated
12 // into the bugpoint tool itself.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "DeltaManager.h"
17 #include "llvm/ADT/SmallString.h"
18 #include "llvm/IR/LLVMContext.h"
19 #include "llvm/IR/Verifier.h"
20 #include "llvm/IRReader/IRReader.h"
21 #include "llvm/Support/CommandLine.h"
22 #include "llvm/Support/InitLLVM.h"
23 #include "llvm/Support/SourceMgr.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include
26 #include
27
28 using namespace llvm;
29
30 static cl::opt Help("h", cl::desc("Alias for -help"), cl::Hidden);
31 static cl::opt Version("v", cl::desc("Alias for -version"), cl::Hidden);
32
33 static cl::opt InputFilename(cl::Positional, cl::Required,
34 cl::desc(""));
35
36 static cl::opt
37 TestFilename("test", cl::Required,
38 cl::desc("Name of the interesting-ness test to be run"));
39
40 static cl::list
41 TestArguments("test-arg", cl::ZeroOrMore,
42 cl::desc("Arguments passed onto the interesting-ness test"));
43
44 static cl::opt
45 OutputFilename("output",
46 cl::desc("Specify the output file. default: reduced.ll"));
47 static cl::alias OutputFileAlias("o", cl::desc("Alias for -output"),
48 cl::aliasopt(OutputFilename));
49
50 static cl::opt
51 ReplaceInput("in-place",
52 cl::desc("WARNING: This option will replace your input file"
53 "with the reduced version!"));
54
55 // Parses IR into a Module and verifies it
56 static std::unique_ptr parseInputFile(StringRef Filename,
57 LLVMContext &Ctxt) {
58 SMDiagnostic Err;
59 std::unique_ptr Result = parseIRFile(Filename, Err, Ctxt);
60 if (!Result) {
61 Err.print("llvm-reduce", errs());
62 return Result;
63 }
64
65 if (verifyModule(*Result, &errs())) {
66 errs() << "Error: " << Filename << " - input module is broken!\n";
67 return std::unique_ptr();
68 }
69
70 return Result;
71 }
72
73 int main(int argc, char **argv) {
74 InitLLVM X(argc, argv);
75
76 cl::ParseCommandLineOptions(argc, argv, "LLVM automatic testcase reducer.\n");
77
78 LLVMContext Context;
79 std::unique_ptr OriginalProgram =
80 parseInputFile(InputFilename, Context);
81
82 // Initialize test environment
83 TestRunner Tester(TestFilename, TestArguments, InputFilename);
84 Tester.setProgram(std::move(OriginalProgram));
85
86 // Try to reduce code
87 runDeltaPasses(Tester);
88 StringRef ReducedFilename = sys::path::filename(Tester.getReducedFilepath());
89
90 if (ReducedFilename == sys::path::filename(InputFilename)) {
91 outs() << "\nCouldnt reduce input :/\n";
92 } else {
93 if (ReplaceInput) // In-place
94 OutputFilename = InputFilename.c_str();
95 else if (OutputFilename.empty())
96 OutputFilename = "reduced.ll";
97 else
98 OutputFilename += ".ll";
99
100 sys::fs::copy_file(Tester.getReducedFilepath(), OutputFilename);
101 outs() << "\nDone reducing! Reduced IR to file: " << OutputFilename << "\n";
102 }
103
104 return 0;
105 }