diff --git a/llvm/tools/llvm-reduce/CMakeLists.txt b/llvm/tools/llvm-reduce/CMakeLists.txt --- a/llvm/tools/llvm-reduce/CMakeLists.txt +++ b/llvm/tools/llvm-reduce/CMakeLists.txt @@ -8,6 +8,7 @@ BitWriter CodeGen Core + Demangle IRReader MC MIRParser @@ -24,6 +25,8 @@ ReducerWorkItem.cpp TestRunner.cpp deltas/Delta.cpp + deltas/Demangle.cpp + deltas/MoveToEntry.cpp deltas/Utils.cpp deltas/ReduceAliases.cpp deltas/ReduceArguments.cpp diff --git a/llvm/tools/llvm-reduce/DeltaManager.h b/llvm/tools/llvm-reduce/DeltaManager.h --- a/llvm/tools/llvm-reduce/DeltaManager.h +++ b/llvm/tools/llvm-reduce/DeltaManager.h @@ -14,12 +14,16 @@ #ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAMANAGER_H #define LLVM_TOOLS_LLVM_REDUCE_DELTAMANAGER_H +#include "llvm/Support/CommandLine.h" + namespace llvm { class raw_ostream; class TestRunner; void printDeltaPasses(raw_ostream &OS); void runDeltaPasses(TestRunner &Tester, int MaxPassIterations); +void runUnconditionalPasses(TestRunner &Tester, + const cl::list &PassList); } // namespace llvm #endif diff --git a/llvm/tools/llvm-reduce/DeltaManager.cpp b/llvm/tools/llvm-reduce/DeltaManager.cpp --- a/llvm/tools/llvm-reduce/DeltaManager.cpp +++ b/llvm/tools/llvm-reduce/DeltaManager.cpp @@ -15,6 +15,8 @@ #include "ReducerWorkItem.h" #include "TestRunner.h" #include "deltas/Delta.h" +#include "deltas/Demangle.h" +#include "deltas/MoveToEntry.h" #include "deltas/ReduceAliases.h" #include "deltas/ReduceArguments.h" #include "deltas/ReduceAttributes.h" @@ -69,6 +71,17 @@ "default, run all delta passes."), cl::cat(LLVMReduceOptions), cl::CommaSeparated); +#define UNCONDITIONAL_PASSES \ + do { \ + DELTA_PASS("intrinsics", reduceInstrinsicsPass) \ + DELTA_PASS("noisy-intrinsics", reduceNoisyInstrinsicsPass) \ + DELTA_PASS("to-calls", reduceToCallsPass) \ + DELTA_PASS("move-to-entry", moveToEntryPass) \ + DELTA_PASS("mangling", demanglePass) \ + DELTA_PASS("noise", reduceNoisePass) \ + DELTA_PASS("to-call-list", reduceToCallListPass) \ + } while (false) + #define DELTA_PASSES \ do { \ DELTA_PASS("strip-debug-info", stripDebugInfoDeltaPass) \ @@ -78,9 +91,11 @@ DELTA_PASS("aliases", reduceAliasesDeltaPass) \ DELTA_PASS("ifuncs", reduceIFuncsDeltaPass) \ DELTA_PASS("simplify-conditionals-true", reduceConditionalsTrueDeltaPass) \ - DELTA_PASS("simplify-conditionals-false", reduceConditionalsFalseDeltaPass)\ + DELTA_PASS("simplify-conditionals-false", \ + reduceConditionalsFalseDeltaPass) \ DELTA_PASS("invokes", reduceInvokesDeltaPass) \ - DELTA_PASS("unreachable-basic-blocks", reduceUnreachableBasicBlocksDeltaPass) \ + DELTA_PASS("unreachable-basic-blocks", \ + reduceUnreachableBasicBlocksDeltaPass) \ DELTA_PASS("basic-blocks", reduceBasicBlocksDeltaPass) \ DELTA_PASS("simplify-cfg", reduceUsingSimplifyCFGDeltaPass) \ DELTA_PASS("function-data", reduceFunctionDataDeltaPass) \ @@ -108,7 +123,7 @@ DELTA_PASS("atomic-ordering", reduceAtomicOrderingDeltaPass) \ DELTA_PASS("syncscopes", reduceAtomicSyncScopesDeltaPass) \ DELTA_PASS("instruction-flags", reduceInstructionFlagsDeltaPass) \ -} while (false) + } while (false) #define DELTA_PASSES_MIR \ do { \ @@ -124,6 +139,43 @@ DELTA_PASS("register-masks", reduceRegisterMasksMIRDeltaPass) \ } while (false) +static void reduceNoisePass(TestRunner &Test) { + demanglePass(Test); + reduceNoisyInstrinsicsPass(Test); + reduceAttributesDeltaPass(Test); + stripDebugInfoDeltaPass(Test); + reduceDIMetadataDeltaPass(Test); + reduceMetadataDeltaPass(Test); + reduceNamedMetadataDeltaPass(Test); + + // Simplify CFG in case `invoke` was used as a previous pass, to remove the + // unwind paths. + reduceUsingSimplifyCFGDeltaPass(Test); + reduceUnreachableBasicBlocksDeltaPass(Test); +} + +static void reduceToCallListPass(TestRunner &Test) { + // Remove noise to start + reduceNoisePass(Test); + + // Strip intrinsics as we're interested in user defined calls only. + reduceInstrinsicsPass(Test); + + // Reduce invokes to calls so reducing arguments and reducing non-call + // instructions work as expected. + reduceInvokesDeltaPass(Test); + + reduceArgumentsDeltaPass(Test); + reduceToCallsPass(Test); + + // Move everything to the entry block. + moveToEntryPass(Test); + + // Then prune everything else + reduceUsingSimplifyCFGDeltaPass(Test); + reduceUnreachableBasicBlocksDeltaPass(Test); +} + static void runAllDeltaPasses(TestRunner &Tester, const SmallStringSet &SkipPass) { #define DELTA_PASS(NAME, FUNC) \ @@ -148,6 +200,7 @@ DELTA_PASSES_MIR; } else { DELTA_PASSES; + UNCONDITIONAL_PASSES; } #undef DELTA_PASS @@ -161,6 +214,7 @@ #define DELTA_PASS(NAME, FUNC) OS << " " << NAME << "\n"; OS << " IR:\n"; DELTA_PASSES; + UNCONDITIONAL_PASSES; OS << " MIR:\n"; DELTA_PASSES_MIR; #undef DELTA_PASS @@ -174,6 +228,7 @@ DELTA_PASSES_MIR; } else { DELTA_PASSES; + UNCONDITIONAL_PASSES; } #undef DELTA_PASS } @@ -225,3 +280,12 @@ OldComplexity = NewComplexity; } } + +void llvm::runUnconditionalPasses(TestRunner &Tester, + const cl::list &PassList) { + auto PassSet = handlePassList(Tester, PassList); + + for (StringRef PassName : PassList) { + runDeltaPassName(Tester, PassName); + } +} diff --git a/llvm/tools/llvm-reduce/TestRunner.h b/llvm/tools/llvm-reduce/TestRunner.h --- a/llvm/tools/llvm-reduce/TestRunner.h +++ b/llvm/tools/llvm-reduce/TestRunner.h @@ -29,7 +29,10 @@ TestRunner(StringRef TestName, const std::vector &TestArgs, std::unique_ptr Program, std::unique_ptr TM, StringRef ToolName, - StringRef OutputFilename, bool InputIsBitcode, bool OutputBitcode); + StringRef OutputFilename, bool InputIsBitcode, bool OutputBitcode, + bool Unconditional); + + bool unconditional() const { return Unconditional; } /// Runs the interesting-ness test for the specified file /// @returns 0 if test was successful, 1 if otherwise @@ -49,11 +52,10 @@ void writeOutput(StringRef Message); - bool inputIsBitcode() const { - return InputIsBitcode; - } + bool inputIsBitcode() const { return InputIsBitcode; } private: + const bool Unconditional; StringRef TestName; StringRef ToolName; const std::vector &TestArgs; diff --git a/llvm/tools/llvm-reduce/TestRunner.cpp b/llvm/tools/llvm-reduce/TestRunner.cpp --- a/llvm/tools/llvm-reduce/TestRunner.cpp +++ b/llvm/tools/llvm-reduce/TestRunner.cpp @@ -18,9 +18,9 @@ std::unique_ptr Program, std::unique_ptr TM, StringRef ToolName, StringRef OutputName, bool InputIsBitcode, - bool OutputBitcode) - : TestName(TestName), ToolName(ToolName), TestArgs(TestArgs), - Program(std::move(Program)), TM(std::move(TM)), + bool OutputBitcode, bool Unconditional) + : Unconditional(Unconditional), TestName(TestName), ToolName(ToolName), + TestArgs(TestArgs), Program(std::move(Program)), TM(std::move(TM)), OutputFilename(OutputName), InputIsBitcode(InputIsBitcode), EmitBitcode(OutputBitcode) { assert(this->Program && "Initialized with null program?"); diff --git a/llvm/tools/llvm-reduce/deltas/Delta.cpp b/llvm/tools/llvm-reduce/deltas/Delta.cpp --- a/llvm/tools/llvm-reduce/deltas/Delta.cpp +++ b/llvm/tools/llvm-reduce/deltas/Delta.cpp @@ -169,12 +169,26 @@ using SharedTaskQueue = std::deque>>; +static void runUnconditionalPass(TestRunner &Test, + ReductionFunc ExtractChunksFromModule, + StringRef Message) { + errs() << "*** " << Message << "...\n"; + + // Run the function with no chunks so all possible changes get made. + std::vector NoChunks = {}; + Oracle Counter(NoChunks); + ExtractChunksFromModule(Counter, Test.getProgram()); +} + /// Runs the Delta Debugging algorithm, splits the code into chunks and /// reduces the amount of chunks that are considered interesting by the /// given test. The number of chunks is determined by a preliminary run of the /// reduction pass where no change must be made to the module. void llvm::runDeltaPass(TestRunner &Test, ReductionFunc ExtractChunksFromModule, StringRef Message) { + if (Test.unconditional()) { + return runUnconditionalPass(Test, ExtractChunksFromModule, Message); + } assert(!Test.getProgram().verify(&errs()) && "input module is broken before making changes"); errs() << "*** " << Message << "...\n"; @@ -199,7 +213,7 @@ std::vector NoChunks = {{0, INT_MAX}}; Oracle NoChunksCounter(NoChunks); std::unique_ptr Clone = - Test.getProgram().clone(Test.getTargetMachine()); + Test.getProgram().clone(Test.getTargetMachine()); ExtractChunksFromModule(NoChunksCounter, *Clone); assert(Targets == NoChunksCounter.count() && "number of chunks changes when reducing"); diff --git a/llvm/tools/llvm-reduce/deltas/Demangle.h b/llvm/tools/llvm-reduce/deltas/Demangle.h new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-reduce/deltas/Demangle.h @@ -0,0 +1,23 @@ +//===- Demangle.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. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements a function which calls the Generic Delta pass in order +// to demangle function names. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVM_REDUCE_DEMANGLE_H +#define LLVM_TOOLS_LLVM_REDUCE_DEMANGLE_H + +#include "Delta.h" + +namespace llvm { +void demanglePass(TestRunner &Test); +} // namespace llvm + +#endif diff --git a/llvm/tools/llvm-reduce/deltas/Demangle.cpp b/llvm/tools/llvm-reduce/deltas/Demangle.cpp new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-reduce/deltas/Demangle.cpp @@ -0,0 +1,33 @@ +//===- Demangle.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 demangle function names. +// +//===----------------------------------------------------------------------===// + +#include "Demangle.h" +#include "llvm/Demangle/Demangle.h" + +using namespace llvm; + +static void demangleModule(Oracle &O, ReducerWorkItem &WorkItem) { + Module &Program = WorkItem.getModule(); + + if (O.shouldKeep()) + return; + + for (auto &F : Program) { + F.setName(llvm::demangle(F.getName().str())); + } +} + +void llvm::demanglePass(TestRunner &Test) { + runDeltaPass(Test, demangleModule, "Demangling names"); +} diff --git a/llvm/tools/llvm-reduce/deltas/MoveToEntry.h b/llvm/tools/llvm-reduce/deltas/MoveToEntry.h new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-reduce/deltas/MoveToEntry.h @@ -0,0 +1,23 @@ +//===- MoveToEntry.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. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements a function which calls the Generic Delta pass in order +// to move instructions to the entry basic block. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_MOVETOENTRY_H +#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_MOVETOENTRY_H + +#include "Delta.h" + +namespace llvm { +void moveToEntryPass(TestRunner &Test); +} // namespace llvm + +#endif diff --git a/llvm/tools/llvm-reduce/deltas/MoveToEntry.cpp b/llvm/tools/llvm-reduce/deltas/MoveToEntry.cpp new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-reduce/deltas/MoveToEntry.cpp @@ -0,0 +1,61 @@ +//===- MoveToEntry.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 move instructions to the entry basic block. +// +//===----------------------------------------------------------------------===// + +#include "MoveToEntry.h" +#include "Utils.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Cloning.h" + +using namespace llvm; + +/// Filter out cases where deleting the instruction will likely cause the +/// user/def of the instruction to fail the verifier. +// +// TODO: Technically the verifier only enforces preallocated token usage and +// there is a none token. +static bool shouldAlwaysKeep(const Instruction &I) { + return I.isEHPad() || I.getType()->isTokenTy() || I.isSwiftError(); +} + +static void moveToEntryModule(Oracle &O, ReducerWorkItem &WorkItem) { + Module &Program = WorkItem.getModule(); + + if (O.shouldKeep()) + return; + + for (auto &F : Program) { + std::vector ToMove; + + for (auto &BB : make_range(std::next(F.begin()), F.end())) { + for (auto &Inst : make_range(BB.begin(), std::prev(BB.end()))) { + if (!shouldAlwaysKeep(Inst)) { + Inst.replaceAllUsesWith(getDefaultValue(Inst.getType())); + ToMove.push_back(&Inst); + } + } + } + auto &Entry = *F.begin(); + + for (auto &Inst : ToMove) { + Inst->removeFromParent(); + Inst->insertBefore(&*std::prev(Entry.end())); + } + } +} + +void llvm::moveToEntryPass(TestRunner &Test) { + runDeltaPass(Test, moveToEntryModule, "Moving instructions to entry block"); +} diff --git a/llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp b/llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp --- a/llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp +++ b/llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp @@ -27,7 +27,7 @@ static void replaceFunctionCalls(Function &OldF, Function &NewF, const std::set &ArgIndexesToKeep) { const auto &Users = OldF.users(); - for (auto I = Users.begin(), E = Users.end(); I != E; ) + for (auto I = Users.begin(), E = Users.end(); I != E;) if (auto *CI = dyn_cast(*I++)) { // Skip uses in call instructions where OldF isn't the called function // (e.g. if OldF is an argument of the call). @@ -76,25 +76,12 @@ for (auto *F : Funcs) { ValueToValueMapTy VMap; - std::vector InstToDelete; for (auto &A : F->args()) if (!ArgsToKeep.count(&A)) { // By adding undesired arguments to the VMap, CloneFunction will remove // them from the resulting Function VMap[&A] = getDefaultValue(A.getType()); - for (auto *U : A.users()) - if (auto *I = dyn_cast(*&U)) - InstToDelete.push_back(I); } - // Delete any (unique) instruction that uses the argument - for (Value *V : InstToDelete) { - if (!V) - continue; - auto *I = cast(V); - I->replaceAllUsesWith(getDefaultValue(I->getType())); - if (!I->isTerminator()) - I->eraseFromParent(); - } // No arguments to reduce if (VMap.empty()) diff --git a/llvm/tools/llvm-reduce/deltas/ReduceInstructions.h b/llvm/tools/llvm-reduce/deltas/ReduceInstructions.h --- a/llvm/tools/llvm-reduce/deltas/ReduceInstructions.h +++ b/llvm/tools/llvm-reduce/deltas/ReduceInstructions.h @@ -20,6 +20,9 @@ namespace llvm { void reduceInstructionsDeltaPass(TestRunner &Test); +void reduceToCallsPass(TestRunner &Test); +void reduceInstrinsicsPass(TestRunner &Test); +void reduceNoisyInstrinsicsPass(TestRunner &Test); } // namespace llvm #endif diff --git a/llvm/tools/llvm-reduce/deltas/ReduceInstructions.cpp b/llvm/tools/llvm-reduce/deltas/ReduceInstructions.cpp --- a/llvm/tools/llvm-reduce/deltas/ReduceInstructions.cpp +++ b/llvm/tools/llvm-reduce/deltas/ReduceInstructions.cpp @@ -1,4 +1,4 @@ -//===- ReduceInstructions.cpp - Specialized Delta Pass ---------------------===// +//===- ReduceInstructions.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. @@ -14,21 +14,27 @@ #include "ReduceInstructions.h" #include "Utils.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" using namespace llvm; +using FilterFunc = function_ref; + /// Filter out cases where deleting the instruction will likely cause the /// user/def of the instruction to fail the verifier. // // TODO: Technically the verifier only enforces preallocated token usage and // there is a none token. -static bool shouldAlwaysKeep(const Instruction &I) { - return I.isEHPad() || I.getType()->isTokenTy() || I.isSwiftError(); +static bool shouldAlwaysKeep(const Instruction &I, FilterFunc Filter) { + return I.isEHPad() || I.getType()->isTokenTy() || I.isSwiftError() || + Filter(I); } /// Removes out-of-chunk arguments from functions, and modifies their calls /// accordingly. It also removes allocations of out-of-chunk arguments. -static void extractInstrFromModule(Oracle &O, ReducerWorkItem &WorkItem) { +static void extractInstrFromModule(Oracle &O, ReducerWorkItem &WorkItem, + FilterFunc Filter) { Module &Program = WorkItem.getModule(); std::vector InitInstToKeep; @@ -38,7 +44,7 @@ // instructions before the terminator. InitInstToKeep.push_back(BB.getTerminator()); for (auto &Inst : make_range(BB.begin(), std::prev(BB.end()))) { - if (shouldAlwaysKeep(Inst) || O.shouldKeep()) + if (shouldAlwaysKeep(Inst, Filter) || O.shouldKeep()) InitInstToKeep.push_back(&Inst); } } @@ -63,5 +69,55 @@ } void llvm::reduceInstructionsDeltaPass(TestRunner &Test) { - runDeltaPass(Test, extractInstrFromModule, "Reducing Instructions"); + runDeltaPass( + Test, + [](Oracle &O, ReducerWorkItem &WorkItem) { + extractInstrFromModule( + O, WorkItem, [](const Instruction &I) -> bool { return false; }); + }, + "Reducing Instructions"); +} + +void llvm::reduceToCallsPass(TestRunner &Test) { + runDeltaPass( + Test, + [](Oracle &O, ReducerWorkItem &WorkItem) { + extractInstrFromModule(O, WorkItem, [](const Instruction &I) -> bool { + return isa(I); + }); + }, + "Reducing Non-Call Instructions"); +} + +void llvm::reduceInstrinsicsPass(TestRunner &Test) { + runDeltaPass( + Test, + [](Oracle &O, ReducerWorkItem &WorkItem) { + extractInstrFromModule(O, WorkItem, [](const Instruction &I) -> bool { + return !isa(I); + }); + }, + "Reducing Instrinsics"); +} + +static llvm::Intrinsic::ID Noisy[] = { + Intrinsic::assume, Intrinsic::lifetime_start, Intrinsic::lifetime_end}; + +void llvm::reduceNoisyInstrinsicsPass(TestRunner &Test) { + runDeltaPass( + Test, + [](Oracle &O, ReducerWorkItem &WorkItem) { + extractInstrFromModule(O, WorkItem, [](const Instruction &I) -> bool { + if (const IntrinsicInst *II = dyn_cast(&I)) { + auto ID = II->getIntrinsicID(); + for (auto I : Noisy) { + if (ID == I) { + return false; + } + } + } + return true; + }); + }, + "Reducing Noisy Instrinsics"); } diff --git a/llvm/tools/llvm-reduce/llvm-reduce.cpp b/llvm/tools/llvm-reduce/llvm-reduce.cpp --- a/llvm/tools/llvm-reduce/llvm-reduce.cpp +++ b/llvm/tools/llvm-reduce/llvm-reduce.cpp @@ -41,6 +41,11 @@ static cl::opt Version("v", cl::desc("Alias for -version"), cl::Hidden, cl::cat(LLVMReduceOptions)); +static cl::list UnconditionalPasses( + "reduce", + cl::desc("Passes to unconditionally run, disables the delta algorithm"), + cl::cat(LLVMReduceOptions), cl::CommaSeparated); + static cl::opt PreserveDebugEnvironment( "preserve-debug-environment", cl::desc("Don't disable features used for crash " @@ -168,11 +173,6 @@ return 1; } - if (TestFilename.empty()) { - WithColor::error(errs(), ToolName) << "--test option must be specified\n"; - return 1; - } - if (!PreserveDebugEnvironment) disableEnvironmentDebugFeatures(); @@ -190,23 +190,32 @@ std::tie(OutputFilename, OutputBitcode) = determineOutputType(ReduceModeMIR, InputIsBitcode); + if (UnconditionalPasses.empty() && TestFilename.empty()) { + WithColor::error(errs(), ToolName) << "--test option must be specified\n"; + return 1; + } + // Initialize test environment TestRunner Tester(TestFilename, TestArguments, std::move(OriginalProgram), std::move(TM), ToolName, OutputFilename, InputIsBitcode, - OutputBitcode); - - // This parses and writes out the testcase into a temporary file copy for the - // test, rather than evaluating the source IR directly. This is for the - // convenience of lit tests; the stripped out comments may have broken the - // interestingness checks. - if (!Tester.getProgram().isReduced(Tester)) { - errs() << "\nInput isn't interesting! Verify interesting-ness test\n"; - return 1; + OutputBitcode, !UnconditionalPasses.empty()); + + if (UnconditionalPasses.empty()) { + // This parses and writes out the testcase into a temporary file copy for + // the test, rather than evaluating the source IR directly. This is for the + // convenience of lit tests; the stripped out comments may have broken the + // interestingness checks. + if (!Tester.getProgram().isReduced(Tester)) { + errs() << "\nInput isn't interesting! Verify interesting-ness test\n"; + return 1; + } + + // Try to reduce code + runDeltaPasses(Tester, MaxPassIterations); + } else { + runUnconditionalPasses(Tester, UnconditionalPasses); } - // Try to reduce code - runDeltaPasses(Tester, MaxPassIterations); - // Print reduced file to STDOUT if (OutputFilename == "-") Tester.getProgram().print(outs(), nullptr);