diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h index b0703457656b21..5adbd5ca76c7b9 100644 --- a/llvm/include/llvm/Passes/PassBuilder.h +++ b/llvm/include/llvm/Passes/PassBuilder.h @@ -488,7 +488,6 @@ class PassBuilder { /// preferred when a pipeline is largely of one type, but one or just a few /// passes are of different types(See PassBuilder.cpp for examples). Error parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, - bool VerifyEachPass = true, bool DebugLogging = false); /// {{@ Parse a textual pass pipeline description into a specific PassManager @@ -499,13 +498,10 @@ class PassBuilder { /// /// function(lpass) Error parsePassPipeline(CGSCCPassManager &CGPM, StringRef PipelineText, - bool VerifyEachPass = true, bool DebugLogging = false); Error parsePassPipeline(FunctionPassManager &FPM, StringRef PipelineText, - bool VerifyEachPass = true, bool DebugLogging = false); Error parsePassPipeline(LoopPassManager &LPM, StringRef PipelineText, - bool VerifyEachPass = true, bool DebugLogging = false); /// @}} @@ -682,10 +678,46 @@ class PassBuilder { /// PassManagers and populate the passed ModulePassManager. void registerParseTopLevelPipelineCallback( const std::function, - bool VerifyEachPass, bool DebugLogging)> &C) { + bool DebugLogging)> &C) { TopLevelPipelineParsingCallbacks.push_back(C); } + /// {{@ Register callbacks for before/after parsing passes. + /// For example, to add a verifier pass after each parsed pass. + void registerBeforeParsingModulePassCallback( + const std::function &C) { + ModulePassBeforeParsingCallbacks.push_back(C); + } + void registerBeforeParsingCGSCCPassCallback( + const std::function &C) { + CGSCCPassBeforeParsingCallbacks.push_back(C); + } + void registerBeforeParsingFunctionPassCallback( + const std::function &C) { + FunctionPassBeforeParsingCallbacks.push_back(C); + } + void registerBeforeParsingLoopPassCallback( + const std::function &C) { + LoopPassBeforeParsingCallbacks.push_back(C); + } + void registerAfterParsingModulePassCallback( + const std::function &C) { + ModulePassAfterParsingCallbacks.push_back(C); + } + void registerAfterParsingCGSCCPassCallback( + const std::function &C) { + CGSCCPassAfterParsingCallbacks.push_back(C); + } + void registerAfterParsingFunctionPassCallback( + const std::function &C) { + FunctionPassAfterParsingCallbacks.push_back(C); + } + void registerAfterParsingLoopPassCallback( + const std::function &C) { + LoopPassAfterParsingCallbacks.push_back(C); + } + /// @}} + /// Add PGOInstrumenation passes for O0 only. void addPGOInstrPassesForO0(ModulePassManager &MPM, bool DebugLogging, bool RunProfileGen, bool IsCS, @@ -708,27 +740,27 @@ class PassBuilder { parsePipelineText(StringRef Text); Error parseModulePass(ModulePassManager &MPM, const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging); + bool DebugLogging); Error parseCGSCCPass(CGSCCPassManager &CGPM, const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging); + bool DebugLogging); Error parseFunctionPass(FunctionPassManager &FPM, const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging); + bool DebugLogging); Error parseLoopPass(LoopPassManager &LPM, const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging); + bool DebugLogging); bool parseAAPassName(AAManager &AA, StringRef Name); Error parseLoopPassPipeline(LoopPassManager &LPM, ArrayRef Pipeline, - bool VerifyEachPass, bool DebugLogging); + bool DebugLogging); Error parseFunctionPassPipeline(FunctionPassManager &FPM, ArrayRef Pipeline, - bool VerifyEachPass, bool DebugLogging); + bool DebugLogging); Error parseCGSCCPassPipeline(CGSCCPassManager &CGPM, ArrayRef Pipeline, - bool VerifyEachPass, bool DebugLogging); + bool DebugLogging); Error parseModulePassPipeline(ModulePassManager &MPM, ArrayRef Pipeline, - bool VerifyEachPass, bool DebugLogging); + bool DebugLogging); void addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging, OptimizationLevel Level, bool RunProfileGen, bool IsCS, @@ -761,7 +793,7 @@ class PassBuilder { 2> ModulePipelineParsingCallbacks; SmallVector, - bool VerifyEachPass, bool DebugLogging)>, + bool DebugLogging)>, 2> TopLevelPipelineParsingCallbacks; // CGSCC callbacks @@ -788,6 +820,23 @@ class PassBuilder { // AA callbacks SmallVector, 2> AAParsingCallbacks; + // Before/after pass parsing callbacks + SmallVector, 2> + ModulePassBeforeParsingCallbacks; + SmallVector, 2> + ModulePassAfterParsingCallbacks; + SmallVector, 2> + CGSCCPassBeforeParsingCallbacks; + SmallVector, 2> + CGSCCPassAfterParsingCallbacks; + SmallVector, 2> + FunctionPassBeforeParsingCallbacks; + SmallVector, 2> + FunctionPassAfterParsingCallbacks; + SmallVector, 2> + LoopPassBeforeParsingCallbacks; + SmallVector, 2> + LoopPassAfterParsingCallbacks; }; /// This utility template takes care of adding require<> and invalidate<> diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 8dfeb158bf1279..a1f8e998c58a19 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -2115,7 +2115,7 @@ PassBuilder::parsePipelineText(StringRef Text) { Error PassBuilder::parseModulePass(ModulePassManager &MPM, const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging) { + bool DebugLogging) { auto &Name = E.Name; auto &InnerPipeline = E.InnerPipeline; @@ -2123,32 +2123,31 @@ Error PassBuilder::parseModulePass(ModulePassManager &MPM, if (!InnerPipeline.empty()) { if (Name == "module") { ModulePassManager NestedMPM(DebugLogging); - if (auto Err = parseModulePassPipeline(NestedMPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = + parseModulePassPipeline(NestedMPM, InnerPipeline, DebugLogging)) return Err; MPM.addPass(std::move(NestedMPM)); return Error::success(); } if (Name == "cgscc") { CGSCCPassManager CGPM(DebugLogging); - if (auto Err = parseCGSCCPassPipeline(CGPM, InnerPipeline, VerifyEachPass, - DebugLogging)) + if (auto Err = parseCGSCCPassPipeline(CGPM, InnerPipeline, DebugLogging)) return Err; MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); return Error::success(); } if (Name == "function") { FunctionPassManager FPM(DebugLogging); - if (auto Err = parseFunctionPassPipeline(FPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = + parseFunctionPassPipeline(FPM, InnerPipeline, DebugLogging)) return Err; MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); return Error::success(); } if (auto Count = parseRepeatPassName(Name)) { ModulePassManager NestedMPM(DebugLogging); - if (auto Err = parseModulePassPipeline(NestedMPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = + parseModulePassPipeline(NestedMPM, InnerPipeline, DebugLogging)) return Err; MPM.addPass(createRepeatedPass(*Count, std::move(NestedMPM))); return Error::success(); @@ -2297,8 +2296,7 @@ Error PassBuilder::parseModulePass(ModulePassManager &MPM, } Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, - const PipelineElement &E, bool VerifyEachPass, - bool DebugLogging) { + const PipelineElement &E, bool DebugLogging) { auto &Name = E.Name; auto &InnerPipeline = E.InnerPipeline; @@ -2306,8 +2304,8 @@ Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, if (!InnerPipeline.empty()) { if (Name == "cgscc") { CGSCCPassManager NestedCGPM(DebugLogging); - if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = + parseCGSCCPassPipeline(NestedCGPM, InnerPipeline, DebugLogging)) return Err; // Add the nested pass manager with the appropriate adaptor. CGPM.addPass(std::move(NestedCGPM)); @@ -2315,8 +2313,8 @@ Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, } if (Name == "function") { FunctionPassManager FPM(DebugLogging); - if (auto Err = parseFunctionPassPipeline(FPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = + parseFunctionPassPipeline(FPM, InnerPipeline, DebugLogging)) return Err; // Add the nested pass manager with the appropriate adaptor. CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM))); @@ -2324,16 +2322,16 @@ Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, } if (auto Count = parseRepeatPassName(Name)) { CGSCCPassManager NestedCGPM(DebugLogging); - if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = + parseCGSCCPassPipeline(NestedCGPM, InnerPipeline, DebugLogging)) return Err; CGPM.addPass(createRepeatedPass(*Count, std::move(NestedCGPM))); return Error::success(); } if (auto MaxRepetitions = parseDevirtPassName(Name)) { CGSCCPassManager NestedCGPM(DebugLogging); - if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = + parseCGSCCPassPipeline(NestedCGPM, InnerPipeline, DebugLogging)) return Err; CGPM.addPass( createDevirtSCCRepeatedPass(std::move(NestedCGPM), *MaxRepetitions)); @@ -2411,7 +2409,7 @@ Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM, const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging) { + bool DebugLogging) { auto &Name = E.Name; auto &InnerPipeline = E.InnerPipeline; @@ -2419,8 +2417,8 @@ Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM, if (!InnerPipeline.empty()) { if (Name == "function") { FunctionPassManager NestedFPM(DebugLogging); - if (auto Err = parseFunctionPassPipeline(NestedFPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = + parseFunctionPassPipeline(NestedFPM, InnerPipeline, DebugLogging)) return Err; // Add the nested pass manager with the appropriate adaptor. FPM.addPass(std::move(NestedFPM)); @@ -2428,8 +2426,7 @@ Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM, } if (Name == "loop" || Name == "loop-mssa") { LoopPassManager LPM(DebugLogging); - if (auto Err = parseLoopPassPipeline(LPM, InnerPipeline, VerifyEachPass, - DebugLogging)) + if (auto Err = parseLoopPassPipeline(LPM, InnerPipeline, DebugLogging)) return Err; // Add the nested pass manager with the appropriate adaptor. bool UseMemorySSA = (Name == "loop-mssa"); @@ -2442,8 +2439,8 @@ Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM, } if (auto Count = parseRepeatPassName(Name)) { FunctionPassManager NestedFPM(DebugLogging); - if (auto Err = parseFunctionPassPipeline(NestedFPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = + parseFunctionPassPipeline(NestedFPM, InnerPipeline, DebugLogging)) return Err; FPM.addPass(createRepeatedPass(*Count, std::move(NestedFPM))); return Error::success(); @@ -2515,7 +2512,7 @@ Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM, } Error PassBuilder::parseLoopPass(LoopPassManager &LPM, const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging) { + bool DebugLogging) { StringRef Name = E.Name; auto &InnerPipeline = E.InnerPipeline; @@ -2523,8 +2520,8 @@ Error PassBuilder::parseLoopPass(LoopPassManager &LPM, const PipelineElement &E, if (!InnerPipeline.empty()) { if (Name == "loop") { LoopPassManager NestedLPM(DebugLogging); - if (auto Err = parseLoopPassPipeline(NestedLPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = + parseLoopPassPipeline(NestedLPM, InnerPipeline, DebugLogging)) return Err; // Add the nested pass manager with the appropriate adaptor. LPM.addPass(std::move(NestedLPM)); @@ -2532,8 +2529,8 @@ Error PassBuilder::parseLoopPass(LoopPassManager &LPM, const PipelineElement &E, } if (auto Count = parseRepeatPassName(Name)) { LoopPassManager NestedLPM(DebugLogging); - if (auto Err = parseLoopPassPipeline(NestedLPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = + parseLoopPassPipeline(NestedLPM, InnerPipeline, DebugLogging)) return Err; LPM.addPass(createRepeatedPass(*Count, std::move(NestedLPM))); return Error::success(); @@ -2608,38 +2605,42 @@ bool PassBuilder::parseAAPassName(AAManager &AA, StringRef Name) { Error PassBuilder::parseLoopPassPipeline(LoopPassManager &LPM, ArrayRef Pipeline, - bool VerifyEachPass, bool DebugLogging) { for (const auto &Element : Pipeline) { - if (auto Err = parseLoopPass(LPM, Element, VerifyEachPass, DebugLogging)) + for (auto &C : LoopPassBeforeParsingCallbacks) + C(LPM); + if (auto Err = parseLoopPass(LPM, Element, DebugLogging)) return Err; - // FIXME: No verifier support for Loop passes! + for (auto &C : LoopPassAfterParsingCallbacks) + C(LPM); } return Error::success(); } Error PassBuilder::parseFunctionPassPipeline(FunctionPassManager &FPM, ArrayRef Pipeline, - bool VerifyEachPass, bool DebugLogging) { for (const auto &Element : Pipeline) { - if (auto Err = - parseFunctionPass(FPM, Element, VerifyEachPass, DebugLogging)) + for (auto &C : FunctionPassBeforeParsingCallbacks) + C(FPM); + if (auto Err = parseFunctionPass(FPM, Element, DebugLogging)) return Err; - if (VerifyEachPass) - FPM.addPass(VerifierPass()); + for (auto &C : FunctionPassAfterParsingCallbacks) + C(FPM); } return Error::success(); } Error PassBuilder::parseCGSCCPassPipeline(CGSCCPassManager &CGPM, ArrayRef Pipeline, - bool VerifyEachPass, bool DebugLogging) { for (const auto &Element : Pipeline) { - if (auto Err = parseCGSCCPass(CGPM, Element, VerifyEachPass, DebugLogging)) + for (auto &C : CGSCCPassBeforeParsingCallbacks) + C(CGPM); + if (auto Err = parseCGSCCPass(CGPM, Element, DebugLogging)) return Err; - // FIXME: No verifier support for CGSCC passes! + for (auto &C : CGSCCPassAfterParsingCallbacks) + C(CGPM); } return Error::success(); } @@ -2659,13 +2660,14 @@ void PassBuilder::crossRegisterProxies(LoopAnalysisManager &LAM, Error PassBuilder::parseModulePassPipeline(ModulePassManager &MPM, ArrayRef Pipeline, - bool VerifyEachPass, bool DebugLogging) { for (const auto &Element : Pipeline) { - if (auto Err = parseModulePass(MPM, Element, VerifyEachPass, DebugLogging)) + for (auto &C : ModulePassBeforeParsingCallbacks) + C(MPM); + if (auto Err = parseModulePass(MPM, Element, DebugLogging)) return Err; - if (VerifyEachPass) - MPM.addPass(VerifierPass()); + for (auto &C : ModulePassAfterParsingCallbacks) + C(MPM); } return Error::success(); } @@ -2675,7 +2677,7 @@ Error PassBuilder::parseModulePassPipeline(ModulePassManager &MPM, // pre-populate the analysis managers with target-specific stuff? Error PassBuilder::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, - bool VerifyEachPass, bool DebugLogging) { + bool DebugLogging) { auto Pipeline = parsePipelineText(PipelineText); if (!Pipeline || Pipeline->empty()) return make_error( @@ -2696,7 +2698,7 @@ Error PassBuilder::parsePassPipeline(ModulePassManager &MPM, Pipeline = {{"function", {{"loop", std::move(*Pipeline)}}}}; } else { for (auto &C : TopLevelPipelineParsingCallbacks) - if (C(MPM, *Pipeline, VerifyEachPass, DebugLogging)) + if (C(MPM, *Pipeline, DebugLogging)) return Error::success(); // Unknown pass or pipeline name! @@ -2709,8 +2711,7 @@ Error PassBuilder::parsePassPipeline(ModulePassManager &MPM, } } - if (auto Err = - parseModulePassPipeline(MPM, *Pipeline, VerifyEachPass, DebugLogging)) + if (auto Err = parseModulePassPipeline(MPM, *Pipeline, DebugLogging)) return Err; return Error::success(); } @@ -2718,7 +2719,7 @@ Error PassBuilder::parsePassPipeline(ModulePassManager &MPM, // Primary pass pipeline description parsing routine for a \c CGSCCPassManager Error PassBuilder::parsePassPipeline(CGSCCPassManager &CGPM, StringRef PipelineText, - bool VerifyEachPass, bool DebugLogging) { + bool DebugLogging) { auto Pipeline = parsePipelineText(PipelineText); if (!Pipeline || Pipeline->empty()) return make_error( @@ -2733,8 +2734,7 @@ Error PassBuilder::parsePassPipeline(CGSCCPassManager &CGPM, .str(), inconvertibleErrorCode()); - if (auto Err = - parseCGSCCPassPipeline(CGPM, *Pipeline, VerifyEachPass, DebugLogging)) + if (auto Err = parseCGSCCPassPipeline(CGPM, *Pipeline, DebugLogging)) return Err; return Error::success(); } @@ -2743,7 +2743,7 @@ Error PassBuilder::parsePassPipeline(CGSCCPassManager &CGPM, // FunctionPassManager Error PassBuilder::parsePassPipeline(FunctionPassManager &FPM, StringRef PipelineText, - bool VerifyEachPass, bool DebugLogging) { + bool DebugLogging) { auto Pipeline = parsePipelineText(PipelineText); if (!Pipeline || Pipeline->empty()) return make_error( @@ -2758,8 +2758,7 @@ Error PassBuilder::parsePassPipeline(FunctionPassManager &FPM, .str(), inconvertibleErrorCode()); - if (auto Err = parseFunctionPassPipeline(FPM, *Pipeline, VerifyEachPass, - DebugLogging)) + if (auto Err = parseFunctionPassPipeline(FPM, *Pipeline, DebugLogging)) return Err; return Error::success(); } @@ -2767,15 +2766,14 @@ Error PassBuilder::parsePassPipeline(FunctionPassManager &FPM, // Primary pass pipeline description parsing routine for a \c LoopPassManager Error PassBuilder::parsePassPipeline(LoopPassManager &CGPM, StringRef PipelineText, - bool VerifyEachPass, bool DebugLogging) { + bool DebugLogging) { auto Pipeline = parsePipelineText(PipelineText); if (!Pipeline || Pipeline->empty()) return make_error( formatv("invalid pipeline '{0}'", PipelineText).str(), inconvertibleErrorCode()); - if (auto Err = - parseLoopPassPipeline(CGPM, *Pipeline, VerifyEachPass, DebugLogging)) + if (auto Err = parseLoopPassPipeline(CGPM, *Pipeline, DebugLogging)) return Err; return Error::success(); diff --git a/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp b/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp index 4c672bc2a3bd41..40aac7c3a2814a 100644 --- a/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp +++ b/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp @@ -148,7 +148,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { PB.registerLoopAnalyses(LAM); PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); - auto Err = PB.parsePassPipeline(MPM, PassPipeline, false, false); + auto Err = PB.parsePassPipeline(MPM, PassPipeline, false); assert(!Err && "Should have been checked during fuzzer initialization"); // Only fail with assert above, otherwise ignore the parsing error. consumeError(std::move(Err)); @@ -241,7 +241,7 @@ extern "C" LLVM_ATTRIBUTE_USED int LLVMFuzzerInitialize( PassBuilder PB(TM.get()); ModulePassManager MPM; - if (auto Err = PB.parsePassPipeline(MPM, PassPipeline, false, false)) { + if (auto Err = PB.parsePassPipeline(MPM, PassPipeline, false)) { errs() << *argv[0] << ": " << toString(std::move(Err)) << "\n"; exit(1); } diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp index c6c4191c14592e..ae97877d3adad7 100644 --- a/llvm/tools/opt/NewPMDriver.cpp +++ b/llvm/tools/opt/NewPMDriver.cpp @@ -140,72 +140,68 @@ bool tryParsePipelineText(PassBuilder &PB, /// If one of the EPPipeline command line options was given, register callbacks /// for parsing and inserting the given pipeline -static void registerEPCallbacks(PassBuilder &PB, bool VerifyEachPass, - bool DebugLogging) { +static void registerEPCallbacks(PassBuilder &PB, bool DebugLogging) { if (tryParsePipelineText(PB, PeepholeEPPipeline)) PB.registerPeepholeEPCallback( - [&PB, VerifyEachPass, DebugLogging]( - FunctionPassManager &PM, PassBuilder::OptimizationLevel Level) { + [&PB, DebugLogging](FunctionPassManager &PM, + PassBuilder::OptimizationLevel Level) { ExitOnError Err("Unable to parse PeepholeEP pipeline: "); - Err(PB.parsePassPipeline(PM, PeepholeEPPipeline, VerifyEachPass, - DebugLogging)); + Err(PB.parsePassPipeline(PM, PeepholeEPPipeline, DebugLogging)); }); if (tryParsePipelineText(PB, LateLoopOptimizationsEPPipeline)) PB.registerLateLoopOptimizationsEPCallback( - [&PB, VerifyEachPass, DebugLogging]( - LoopPassManager &PM, PassBuilder::OptimizationLevel Level) { + [&PB, DebugLogging](LoopPassManager &PM, + PassBuilder::OptimizationLevel Level) { ExitOnError Err("Unable to parse LateLoopOptimizationsEP pipeline: "); Err(PB.parsePassPipeline(PM, LateLoopOptimizationsEPPipeline, - VerifyEachPass, DebugLogging)); + DebugLogging)); }); if (tryParsePipelineText(PB, LoopOptimizerEndEPPipeline)) PB.registerLoopOptimizerEndEPCallback( - [&PB, VerifyEachPass, DebugLogging]( - LoopPassManager &PM, PassBuilder::OptimizationLevel Level) { + [&PB, DebugLogging](LoopPassManager &PM, + PassBuilder::OptimizationLevel Level) { ExitOnError Err("Unable to parse LoopOptimizerEndEP pipeline: "); Err(PB.parsePassPipeline(PM, LoopOptimizerEndEPPipeline, - VerifyEachPass, DebugLogging)); + DebugLogging)); }); if (tryParsePipelineText(PB, ScalarOptimizerLateEPPipeline)) PB.registerScalarOptimizerLateEPCallback( - [&PB, VerifyEachPass, DebugLogging]( - FunctionPassManager &PM, PassBuilder::OptimizationLevel Level) { + [&PB, DebugLogging](FunctionPassManager &PM, + PassBuilder::OptimizationLevel Level) { ExitOnError Err("Unable to parse ScalarOptimizerLateEP pipeline: "); Err(PB.parsePassPipeline(PM, ScalarOptimizerLateEPPipeline, - VerifyEachPass, DebugLogging)); + DebugLogging)); }); if (tryParsePipelineText(PB, CGSCCOptimizerLateEPPipeline)) PB.registerCGSCCOptimizerLateEPCallback( - [&PB, VerifyEachPass, DebugLogging]( - CGSCCPassManager &PM, PassBuilder::OptimizationLevel Level) { + [&PB, DebugLogging](CGSCCPassManager &PM, + PassBuilder::OptimizationLevel Level) { ExitOnError Err("Unable to parse CGSCCOptimizerLateEP pipeline: "); Err(PB.parsePassPipeline(PM, CGSCCOptimizerLateEPPipeline, - VerifyEachPass, DebugLogging)); + DebugLogging)); }); if (tryParsePipelineText(PB, VectorizerStartEPPipeline)) PB.registerVectorizerStartEPCallback( - [&PB, VerifyEachPass, DebugLogging]( - FunctionPassManager &PM, PassBuilder::OptimizationLevel Level) { + [&PB, DebugLogging](FunctionPassManager &PM, + PassBuilder::OptimizationLevel Level) { ExitOnError Err("Unable to parse VectorizerStartEP pipeline: "); Err(PB.parsePassPipeline(PM, VectorizerStartEPPipeline, - VerifyEachPass, DebugLogging)); + DebugLogging)); }); if (tryParsePipelineText(PB, PipelineStartEPPipeline)) PB.registerPipelineStartEPCallback( - [&PB, VerifyEachPass, DebugLogging](ModulePassManager &PM) { + [&PB, DebugLogging](ModulePassManager &PM) { ExitOnError Err("Unable to parse PipelineStartEP pipeline: "); - Err(PB.parsePassPipeline(PM, PipelineStartEPPipeline, VerifyEachPass, - DebugLogging)); + Err(PB.parsePassPipeline(PM, PipelineStartEPPipeline, DebugLogging)); }); if (tryParsePipelineText(PB, OptimizerLastEPPipeline)) PB.registerOptimizerLastEPCallback( - [&PB, VerifyEachPass, DebugLogging](ModulePassManager &PM, - PassBuilder::OptimizationLevel) { + [&PB, DebugLogging](ModulePassManager &PM, + PassBuilder::OptimizationLevel) { ExitOnError Err("Unable to parse OptimizerLastEP pipeline: "); - Err(PB.parsePassPipeline(PM, OptimizerLastEPPipeline, VerifyEachPass, - DebugLogging)); + Err(PB.parsePassPipeline(PM, OptimizerLastEPPipeline, DebugLogging)); }); } @@ -274,7 +270,15 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM, PTO.LoopUnrolling = !DisableLoopUnrolling; PTO.Coroutines = Coroutines; PassBuilder PB(TM, PTO, P, &PIC); - registerEPCallbacks(PB, VerifyEachPass, DebugPM); + registerEPCallbacks(PB, DebugPM); + + if (VerifyEachPass) { + // No verifier support for CGSCC/Loop passes. + PB.registerAfterParsingFunctionPassCallback( + [](FunctionPassManager &FPM) { FPM.addPass(VerifierPass()); }); + PB.registerAfterParsingModulePassCallback( + [](ModulePassManager &MPM) { MPM.addPass(VerifierPass()); }); + } // Load requested pass plugins and let them register pass builder callbacks for (auto &PluginFN : PassPlugins) { @@ -384,8 +388,7 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM, if (!PassPipeline.empty()) { assert(Passes.empty() && "PassPipeline and Passes should not both contain passes"); - if (auto Err = - PB.parsePassPipeline(MPM, PassPipeline, VerifyEachPass, DebugPM)) { + if (auto Err = PB.parsePassPipeline(MPM, PassPipeline, DebugPM)) { errs() << Arg0 << ": " << toString(std::move(Err)) << "\n"; return false; } @@ -394,8 +397,7 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM, std::string ModifiedPassName(PassName.begin(), PassName.end()); if (PB.isAnalysisPassName(PassName)) ModifiedPassName = "require<" + ModifiedPassName + ">"; - if (auto Err = PB.parsePassPipeline(MPM, ModifiedPassName, VerifyEachPass, - DebugPM)) { + if (auto Err = PB.parsePassPipeline(MPM, ModifiedPassName, DebugPM)) { errs() << Arg0 << ": " << toString(std::move(Err)) << "\n"; return false; } diff --git a/llvm/unittests/IR/PassBuilderCallbacksTest.cpp b/llvm/unittests/IR/PassBuilderCallbacksTest.cpp index 44c0fe9ffd1661..7052f655a422de 100644 --- a/llvm/unittests/IR/PassBuilderCallbacksTest.cpp +++ b/llvm/unittests/IR/PassBuilderCallbacksTest.cpp @@ -502,7 +502,7 @@ TEST_F(ModuleCallbacksTest, Passes) { .WillOnce(Invoke(getAnalysisResult)); StringRef PipelineText = "test-transform"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); @@ -547,7 +547,7 @@ TEST_F(ModuleCallbacksTest, InstrumentedPasses) { .Times(0); StringRef PipelineText = "test-transform"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); @@ -663,7 +663,7 @@ TEST_F(ModuleCallbacksTest, InstrumentedSkippedPasses) { StringRef PipelineText = "test-transform,function(test-transform),cgscc(" "function(loop(test-transform)))"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); @@ -675,7 +675,7 @@ TEST_F(FunctionCallbacksTest, Passes) { .WillOnce(Invoke(getAnalysisResult)); StringRef PipelineText = "test-transform"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); } @@ -725,7 +725,7 @@ TEST_F(FunctionCallbacksTest, InstrumentedPasses) { .Times(0); StringRef PipelineText = "test-transform"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); } @@ -771,7 +771,7 @@ TEST_F(FunctionCallbacksTest, InstrumentedSkippedPasses) { .Times(0); StringRef PipelineText = "test-transform"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); } @@ -782,7 +782,7 @@ TEST_F(LoopCallbacksTest, Passes) { .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult))); StringRef PipelineText = "test-transform"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); } @@ -833,7 +833,7 @@ TEST_F(LoopCallbacksTest, InstrumentedPasses) { .Times(0); StringRef PipelineText = "test-transform"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); } @@ -881,7 +881,7 @@ TEST_F(LoopCallbacksTest, InstrumentedInvalidatingPasses) { .Times(0); StringRef PipelineText = "test-transform"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); } @@ -925,7 +925,7 @@ TEST_F(LoopCallbacksTest, InstrumentedSkippedPasses) { .Times(0); StringRef PipelineText = "test-transform"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); } @@ -936,7 +936,7 @@ TEST_F(CGSCCCallbacksTest, Passes) { .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult))); StringRef PipelineText = "test-transform"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); } @@ -987,7 +987,7 @@ TEST_F(CGSCCCallbacksTest, InstrumentedPasses) { .Times(0); StringRef PipelineText = "test-transform"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); } @@ -1035,7 +1035,7 @@ TEST_F(CGSCCCallbacksTest, InstrumentedInvalidatingPasses) { .Times(0); StringRef PipelineText = "test-transform"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); } @@ -1080,7 +1080,7 @@ TEST_F(CGSCCCallbacksTest, InstrumentedSkippedPasses) { .Times(0); StringRef PipelineText = "test-transform"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); } @@ -1095,7 +1095,7 @@ TEST_F(ModuleCallbacksTest, AnalysisUtilities) { EXPECT_CALL(AnalysisHandle, invalidate(HasName(""), _, _)); StringRef PipelineText = "require,invalidate"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); } @@ -1105,7 +1105,7 @@ TEST_F(CGSCCCallbacksTest, PassUtilities) { EXPECT_CALL(AnalysisHandle, invalidate(HasName("(foo)"), _, _)); StringRef PipelineText = "require,invalidate"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); } @@ -1115,7 +1115,7 @@ TEST_F(FunctionCallbacksTest, AnalysisUtilities) { EXPECT_CALL(AnalysisHandle, invalidate(HasName("foo"), _, _)); StringRef PipelineText = "require,invalidate"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); } @@ -1126,7 +1126,7 @@ TEST_F(LoopCallbacksTest, PassUtilities) { StringRef PipelineText = "require,invalidate"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); } @@ -1139,25 +1139,27 @@ TEST_F(LoopCallbacksTest, PassUtilities) { /// This test parses a pipeline named 'another-pipeline', whose only elements /// may be the test-transform pass or the analysis utilities TEST_F(ModuleCallbacksTest, ParseTopLevelPipeline) { - PB.registerParseTopLevelPipelineCallback([this]( - ModulePassManager &MPM, ArrayRef Pipeline, - bool VerifyEachPass, bool DebugLogging) { - auto &FirstName = Pipeline.front().Name; - auto &InnerPipeline = Pipeline.front().InnerPipeline; - if (FirstName == "another-pipeline") { - for (auto &E : InnerPipeline) { - if (parseAnalysisUtilityPasses("test-analysis", E.Name, PM)) - continue; - - if (E.Name == "test-transform") { - PM.addPass(PassHandle.getPass()); - continue; + PB.registerParseTopLevelPipelineCallback( + [this](ModulePassManager &MPM, + ArrayRef Pipeline, + bool DebugLogging) { + auto &FirstName = Pipeline.front().Name; + auto &InnerPipeline = Pipeline.front().InnerPipeline; + if (FirstName == "another-pipeline") { + for (auto &E : InnerPipeline) { + if (parseAnalysisUtilityPasses("test-analysis", E.Name, + PM)) + continue; + + if (E.Name == "test-transform") { + PM.addPass(PassHandle.getPass()); + continue; + } + return false; + } } - return false; - } - } - return true; - }); + return true; + }); EXPECT_CALL(AnalysisHandle, run(HasName(""), _)); EXPECT_CALL(PassHandle, run(HasName(""), _)) @@ -1166,13 +1168,121 @@ TEST_F(ModuleCallbacksTest, ParseTopLevelPipeline) { StringRef PipelineText = "another-pipeline(test-transform,invalidate)"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) << "Pipeline was: " << PipelineText; PM.run(*M, AM); /// Test the negative case PipelineText = "another-pipeline(instcombine)"; - ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Failed()) + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Failed()) << "Pipeline was: " << PipelineText; } + +struct CounterPass : PassInfoMixin { + int &Counter; + int &I; + + CounterPass(int &Counter, int &I) : Counter(Counter), I(I) {} + + void impl() { + int C = Counter++; + // A pass can be run multiple times (e.g. passes added via before/after + // parsing passes callbacks when implicit pass managers are involved), so + // only take the first number. + if (I == 0) + I = C; + } + + PreservedAnalyses run(Module &F, ModuleAnalysisManager &AM) { + impl(); + return PreservedAnalyses::none(); + } + PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, + LazyCallGraph &CG, CGSCCUpdateResult &UR) { + impl(); + return PreservedAnalyses::none(); + } + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { + impl(); + return PreservedAnalyses::none(); + } + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U) { + impl(); + return PreservedAnalyses::none(); + } +}; + +TEST_F(ModuleCallbacksTest, AddPassCallbacks) { + int M1 = 0, M2 = 0, M3 = 0, C1 = 0, C2 = 0, C3 = 0, F1 = 0, F2 = 0, F3 = 0, + L1 = 0, L2 = 0, L3 = 0, Counter = 1; + PB.registerBeforeParsingModulePassCallback( + [&](ModulePassManager &MPM) { MPM.addPass(CounterPass(Counter, M1)); }); + PB.registerAfterParsingModulePassCallback( + [&](ModulePassManager &MPM) { MPM.addPass(CounterPass(Counter, M3)); }); + PB.registerBeforeParsingCGSCCPassCallback( + [&](CGSCCPassManager &MPM) { MPM.addPass(CounterPass(Counter, C1)); }); + PB.registerAfterParsingCGSCCPassCallback( + [&](CGSCCPassManager &MPM) { MPM.addPass(CounterPass(Counter, C3)); }); + PB.registerBeforeParsingFunctionPassCallback( + [&](FunctionPassManager &MPM) { MPM.addPass(CounterPass(Counter, F1)); }); + PB.registerAfterParsingFunctionPassCallback( + [&](FunctionPassManager &MPM) { MPM.addPass(CounterPass(Counter, F3)); }); + PB.registerBeforeParsingLoopPassCallback( + [&](LoopPassManager &MPM) { MPM.addPass(CounterPass(Counter, L1)); }); + PB.registerAfterParsingLoopPassCallback( + [&](LoopPassManager &MPM) { MPM.addPass(CounterPass(Counter, L3)); }); + + PB.registerPipelineParsingCallback( + [&](StringRef Name, ModulePassManager &MPM, + ArrayRef) { + if (Name == "test") { + MPM.addPass(CounterPass(Counter, M2)); + return true; + } + return false; + }); + + PB.registerPipelineParsingCallback( + [&](StringRef Name, CGSCCPassManager &CGPM, + ArrayRef) { + if (Name == "test") { + CGPM.addPass(CounterPass(Counter, C2)); + return true; + } + return false; + }); + PB.registerPipelineParsingCallback( + [&](StringRef Name, FunctionPassManager &FPM, + ArrayRef) { + if (Name == "test") { + FPM.addPass(CounterPass(Counter, F2)); + return true; + } + return false; + }); + PB.registerPipelineParsingCallback( + [&](StringRef Name, LoopPassManager &LPM, + ArrayRef) { + if (Name == "test") { + LPM.addPass(CounterPass(Counter, L2)); + return true; + } + return false; + }); + + StringRef PipelineText = "test,cgscc(test,function(test,loop(test)))"; + ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText), Succeeded()) + << "Pipeline was: " << PipelineText; + PM.run(*M, AM); + + ASSERT_LT(M1, M2); + ASSERT_LT(M2, M3); + ASSERT_LT(C1, C2); + ASSERT_LT(C2, C3); + ASSERT_LT(F1, F2); + ASSERT_LT(F2, F3); + ASSERT_LT(L1, L2); + ASSERT_LT(L2, L3); +} } // end anonymous namespace diff --git a/polly/lib/Support/RegisterPasses.cpp b/polly/lib/Support/RegisterPasses.cpp index ad6edb5807ccec..e9687df6e964be 100644 --- a/polly/lib/Support/RegisterPasses.cpp +++ b/polly/lib/Support/RegisterPasses.cpp @@ -678,7 +678,7 @@ static bool isScopPassName(StringRef Name) { static bool parseTopLevelPipeline(ModulePassManager &MPM, ArrayRef Pipeline, - bool VerifyEachPass, bool DebugLogging) { + bool DebugLogging) { std::vector FullPipeline; StringRef FirstName = Pipeline.front().Name; @@ -698,11 +698,7 @@ parseTopLevelPipeline(ModulePassManager &MPM, } FPM.addPass(createFunctionToScopPassAdaptor(std::move(SPM))); - if (VerifyEachPass) - FPM.addPass(VerifierPass()); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); - if (VerifyEachPass) - MPM.addPass(VerifierPass()); return true; }