Index: llvm/test/tools/llvm-reduce/skip-delta-passes.ll =================================================================== --- /dev/null +++ llvm/test/tools/llvm-reduce/skip-delta-passes.ll @@ -0,0 +1,22 @@ +; RUN: llvm-reduce --delta-passes=attributes --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: FileCheck -check-prefix=RESULT %s < %t + +; RUN: llvm-reduce --delta-passes=instructions,attributes --skip-delta-passes=instructions --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: FileCheck -check-prefix=RESULT %s < %t + +; RUN: not llvm-reduce --skip-delta-passes=foo --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t 2>&1 | FileCheck %s --check-prefix=ERROR + + +; CHECK-INTERESTINGNESS: @foo +; RESULT: define void @foo() { +; RESULT-NEXT: store i32 +; RESULT-NEXT: ret void +; RESULT0-NOT: attributes + +; ERROR: unknown pass "foo" +define void @foo() #0 { + store i32 0, ptr null + ret void +} + +attributes #0 = { "arstarstarst" } Index: llvm/tools/llvm-reduce/DeltaManager.cpp =================================================================== --- llvm/tools/llvm-reduce/DeltaManager.cpp +++ llvm/tools/llvm-reduce/DeltaManager.cpp @@ -48,12 +48,20 @@ using namespace llvm; +using SmallStringSet = SmallSet; + extern cl::OptionCategory LLVMReduceOptions; -static cl::opt +static cl::list DeltaPasses("delta-passes", cl::desc("Delta passes to run, separated by commas. By " "default, run all delta passes."), - cl::cat(LLVMReduceOptions)); + cl::cat(LLVMReduceOptions), cl::CommaSeparated); + +static cl::list + SkipDeltaPasses("skip-delta-passes", + cl::desc("Delta passes to not run, separated by commas. By " + "default, run all delta passes."), + cl::cat(LLVMReduceOptions), cl::CommaSeparated); #define DELTA_PASSES \ do { \ @@ -97,8 +105,12 @@ DELTA_PASS("register-masks", reduceRegisterMasksMIRDeltaPass) \ } while (false) -static void runAllDeltaPasses(TestRunner &Tester) { -#define DELTA_PASS(NAME, FUNC) FUNC(Tester); +static void runAllDeltaPasses(TestRunner &Tester, + const SmallStringSet &SkipPass) { +#define DELTA_PASS(NAME, FUNC) \ + if (!SkipPass.count(NAME)) { \ + FUNC(Tester); \ + } if (Tester.getProgram().isMIR()) { DELTA_PASSES_MIR; } else { @@ -119,8 +131,10 @@ DELTA_PASSES; } #undef DELTA_PASS - errs() << "unknown pass \"" << PassName << "\"\n"; - exit(1); + + // We should have errored on unrecognized passes before trying to run + // anything. + llvm_unreachable("unknown delta pass"); } void llvm::printDeltaPasses(raw_ostream &OS) { @@ -133,19 +147,59 @@ #undef DELTA_PASS } +// Built a set of available delta passes. +static void collectPassNames(const TestRunner &Tester, + SmallStringSet &NameSet) { +#define DELTA_PASS(NAME, FUNC) NameSet.insert(NAME); + if (Tester.getProgram().isMIR()) { + DELTA_PASSES_MIR; + } else { + DELTA_PASSES; + } +#undef DELTA_PASS +} + +/// Verify all requested or skipped passes are valid names, and return them in a +/// set. +static SmallStringSet handlePassList(const TestRunner &Tester, + const cl::list &PassList) { + SmallStringSet AllPasses; + collectPassNames(Tester, AllPasses); + + SmallStringSet PassSet; + for (StringRef PassName : PassList) { + if (!AllPasses.count(PassName)) { + errs() << "unknown pass \"" << PassName << "\"\n"; + exit(1); + } + + PassSet.insert(PassName); + } + + return PassSet; +} + void llvm::runDeltaPasses(TestRunner &Tester, int MaxPassIterations) { uint64_t OldComplexity = Tester.getProgram().getComplexityScore(); + + SmallStringSet RunPassSet, SkipPassSet; + + if (!DeltaPasses.empty()) + RunPassSet = handlePassList(Tester, DeltaPasses); + + if (!SkipDeltaPasses.empty()) + SkipPassSet = handlePassList(Tester, SkipDeltaPasses); + for (int Iter = 0; Iter < MaxPassIterations; ++Iter) { if (DeltaPasses.empty()) { - runAllDeltaPasses(Tester); + runAllDeltaPasses(Tester, SkipPassSet); } else { - StringRef Passes = DeltaPasses; - while (!Passes.empty()) { - auto Split = Passes.split(","); - runDeltaPassName(Tester, Split.first); - Passes = Split.second; + for (StringRef PassName : DeltaPasses) { + if (!SkipPassSet.count(PassName)) + runDeltaPassName(Tester, PassName); } } + uint64_t NewComplexity = Tester.getProgram().getComplexityScore(); if (NewComplexity >= OldComplexity) break;