diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h --- a/llvm/include/llvm/Passes/PassBuilder.h +++ b/llvm/include/llvm/Passes/PassBuilder.h @@ -78,17 +78,134 @@ PassInstrumentationCallbacks *PIC; public: - /// A struct to capture parsed pass pipeline names. - /// - /// A pipeline is defined as a series of names, each of which may in itself - /// recursively contain a nested pipeline. A name is either the name of a pass - /// (e.g. "instcombine") or the name of a pipeline type (e.g. "cgscc"). If the - /// name is the name of a pass, the InnerPipeline is empty, since passes - /// cannot contain inner pipelines. See parsePassPipeline() for a more - /// detailed description of the textual pipeline format. - struct PipelineElement { - StringRef Name; - std::vector InnerPipeline; + /// This class performs all the tasks related to parsing of the textual + /// representation for the pass pipeline. + class PipelineParser { + + friend class PassBuilder; + + PipelineParser(PassBuilder &PB, StringRef PipelineText = StringRef()) + : PB(PB), PipelineText(PipelineText) {} + + ~PipelineParser() = default; + + public: + /// A struct to capture parsed pass pipeline names. + /// + /// A pipeline is defined as a series of names, each of which may in itself + /// recursively contain a nested pipeline. A name is either the name of a + /// pass (e.g. "instcombine") or the name of a pipeline type (e.g. "cgscc"). + /// If the name is the name of a pass, the InnerPipeline is empty, since + /// passes cannot contain inner pipelines. See parsePassPipeline() for a + /// more detailed description of the textual pipeline format. + struct PipelineElement { + StringRef Name; + std::vector InnerPipeline; + }; + + /// Individual pipeline element parsing methods. + Error parseLoopPassPipeline(LoopPassManager &LPM, + ArrayRef Pipeline, + bool VerifyEachPass, bool DebugLogging) const; + Error parseFunctionPassPipeline(FunctionPassManager &FPM, + ArrayRef Pipeline, + bool VerifyEachPass, + bool DebugLogging) const; + Error parseCGSCCPassPipeline(CGSCCPassManager &CGPM, + ArrayRef Pipeline, + bool VerifyEachPass, bool DebugLogging) const; + Error parseModulePassPipeline(ModulePassManager &MPM, + ArrayRef Pipeline, + bool VerifyEachPass, bool DebugLogging) const; + + /// This utility template takes care of adding require<> and invalidate<> + /// passes for an analysis to a given \c PassManager. It is intended to be + /// used during parsing of a pass pipeline when parsing a single + /// PipelineName. When registering a new function analysis FancyAnalysis + /// with the pass pipeline name "fancy-analysis", a matching + /// ParsePipelineCallback could look like this: + /// + /// static bool parseFunctionPipeline(StringRef Name, FunctionPassManager + /// &FPM, + /// PipelineParser Parser, + /// ArrayRef P) { + /// if (Parser.parseAnalysisUtilityPasses( + /// "fancy-analysis", Name, FPM)) + /// return true; + /// return false; + /// } + template + bool parseAnalysisUtilityPasses( + StringRef AnalysisName, StringRef PipelineName, + PassManager &PM) const { + if (!PipelineName.endswith(">")) + return false; + // See if this is an invalidate<> pass name + if (PipelineName.startswith("invalidate<")) { + PipelineName = PipelineName.substr(11, PipelineName.size() - 12); + if (PipelineName != AnalysisName) + return false; + PM.addPass(InvalidateAnalysisPass()); + return true; + } + + // See if this is a require<> pass name + if (PipelineName.startswith("require<")) { + PipelineName = PipelineName.substr(8, PipelineName.size() - 9); + if (PipelineName != AnalysisName) + return false; + PM.addPass(RequireAnalysisPass()); + return true; + } + + return false; + } + + Error parseModulePass(ModulePassManager &MPM, const PipelineElement &E, + bool VerifyEachPass, bool DebugLogging) const; + Error parseCGSCCPass(CGSCCPassManager &CGPM, const PipelineElement &E, + bool VerifyEachPass, bool DebugLogging) const; + Error parseFunctionPass(FunctionPassManager &FPM, const PipelineElement &E, + bool VerifyEachPass, bool DebugLogging) const; + Error parseLoopPass(LoopPassManager &LPM, const PipelineElement &E, + bool VerifyEachPass, bool DebugLogging) const; + + public: + /// Implementation of PassBuilder::parsePassPipeline methods. + /// They perform parsing of the pipeline-elements tree already populated + /// from text representation. + Error parsePassPipeline(ModulePassManager &MPM, bool VerifyEachPass = true, + bool DebugLogging = false); + Error parsePassPipeline(CGSCCPassManager &CGPM, bool VerifyEachPass = true, + bool DebugLogging = false); + Error parsePassPipeline(FunctionPassManager &FPM, + bool VerifyEachPass = true, + bool DebugLogging = false); + Error parsePassPipeline(LoopPassManager &LPM, bool VerifyEachPass = true, + bool DebugLogging = false); + + private: + template + static bool callbacksAcceptPassName(StringRef Name, CallbacksT &Callbacks); + template + static bool isModulePassName(StringRef Name, CallbacksT &Callbacks); + template + static bool isCGSCCPassName(StringRef Name, CallbacksT &Callbacks); + template + static bool isFunctionPassName(StringRef Name, CallbacksT &Callbacks); + template + static bool isLoopPassName(StringRef Name, CallbacksT &Callbacks); + + /// Utility that performs initial parsing of the pipeline text. + /// Produces a tree of pipeline elements. + static Optional> + parsePipelineText(StringRef Text); + + PassBuilder &PB; + StringRef PipelineText; + Optional> Pipeline = None; }; /// ThinLTO phase. @@ -401,7 +518,10 @@ /// explicitly form a pass manager in which to nest passes. Error parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, bool VerifyEachPass = true, - bool DebugLogging = false); + bool DebugLogging = false) { + return PipelineParser(*this, PipelineText) + .parsePassPipeline(MPM, VerifyEachPass, DebugLogging); + } /// {{@ Parse a textual pass pipeline description into a specific PassManager /// @@ -412,13 +532,22 @@ /// function(lpass) Error parsePassPipeline(CGSCCPassManager &CGPM, StringRef PipelineText, bool VerifyEachPass = true, - bool DebugLogging = false); + bool DebugLogging = false) { + return PipelineParser(*this, PipelineText) + .parsePassPipeline(CGPM, VerifyEachPass, DebugLogging); + } Error parsePassPipeline(FunctionPassManager &FPM, StringRef PipelineText, bool VerifyEachPass = true, - bool DebugLogging = false); + bool DebugLogging = false) { + return PipelineParser(*this, PipelineText) + .parsePassPipeline(FPM, VerifyEachPass, DebugLogging); + } Error parsePassPipeline(LoopPassManager &LPM, StringRef PipelineText, bool VerifyEachPass = true, - bool DebugLogging = false); + bool DebugLogging = false) { + return PipelineParser(*this, PipelineText) + .parsePassPipeline(LPM, VerifyEachPass, DebugLogging); + } /// @}} /// Parse a textual alias analysis pipeline into the provided AA manager. @@ -561,22 +690,26 @@ /// accordingly. void registerPipelineParsingCallback( const std::function)> &C) { + const PipelineParser &Parser, + ArrayRef)> &C) { CGSCCPipelineParsingCallbacks.push_back(C); } void registerPipelineParsingCallback( const std::function)> &C) { + const PipelineParser &Parser, + ArrayRef)> &C) { FunctionPipelineParsingCallbacks.push_back(C); } void registerPipelineParsingCallback( const std::function)> &C) { + const PipelineParser &Parser, + ArrayRef)> &C) { LoopPipelineParsingCallbacks.push_back(C); } void registerPipelineParsingCallback( const std::function)> &C) { + const PipelineParser &Parser, + ArrayRef)> &C) { ModulePipelineParsingCallbacks.push_back(C); } /// @}} @@ -587,42 +720,19 @@ /// text, this Callback should be used to determine the appropriate stack of /// PassManagers and populate the passed ModulePassManager. void registerParseTopLevelPipelineCallback( - const std::function, + const std::function, bool VerifyEachPass, bool DebugLogging)> &C) { TopLevelPipelineParsingCallbacks.push_back(C); } private: - static Optional> - parsePipelineText(StringRef Text); - - Error parseModulePass(ModulePassManager &MPM, const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging); - Error parseCGSCCPass(CGSCCPassManager &CGPM, const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging); - Error parseFunctionPass(FunctionPassManager &FPM, const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging); - Error parseLoopPass(LoopPassManager &LPM, const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging); - bool parseAAPassName(AAManager &AA, StringRef Name); - - Error parseLoopPassPipeline(LoopPassManager &LPM, - ArrayRef Pipeline, - bool VerifyEachPass, bool DebugLogging); - Error parseFunctionPassPipeline(FunctionPassManager &FPM, - ArrayRef Pipeline, - bool VerifyEachPass, bool DebugLogging); - Error parseCGSCCPassPipeline(CGSCCPassManager &CGPM, - ArrayRef Pipeline, - bool VerifyEachPass, bool DebugLogging); - Error parseModulePassPipeline(ModulePassManager &MPM, - ArrayRef Pipeline, - bool VerifyEachPass, bool DebugLogging); void addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging, OptimizationLevel Level, bool RunProfileGen, bool IsCS, std::string ProfileFile, std::string ProfileRemappingFile); + bool parseAAPassName(AAManager &AA, StringRef Name); void invokePeepholeEPCallbacks(FunctionPassManager &, OptimizationLevel); @@ -646,82 +756,45 @@ PipelineStartEPCallbacks; SmallVector, 2> ModuleAnalysisRegistrationCallbacks; - SmallVector)>, - 2> + SmallVector< + std::function)>, + 2> ModulePipelineParsingCallbacks; - SmallVector, + SmallVector, bool VerifyEachPass, bool DebugLogging)>, 2> TopLevelPipelineParsingCallbacks; // CGSCC callbacks SmallVector, 2> CGSCCAnalysisRegistrationCallbacks; - SmallVector)>, - 2> + SmallVector< + std::function)>, + 2> CGSCCPipelineParsingCallbacks; // Function callbacks SmallVector, 2> FunctionAnalysisRegistrationCallbacks; SmallVector)>, + const PipelineParser &, + ArrayRef)>, 2> FunctionPipelineParsingCallbacks; // Loop callbacks SmallVector, 2> LoopAnalysisRegistrationCallbacks; - SmallVector)>, - 2> + SmallVector< + std::function)>, + 2> LoopPipelineParsingCallbacks; // AA callbacks SmallVector, 2> AAParsingCallbacks; }; -/// This utility template takes care of adding require<> and invalidate<> -/// passes for an analysis to a given \c PassManager. It is intended to be used -/// during parsing of a pass pipeline when parsing a single PipelineName. -/// When registering a new function analysis FancyAnalysis with the pass -/// pipeline name "fancy-analysis", a matching ParsePipelineCallback could look -/// like this: -/// -/// static bool parseFunctionPipeline(StringRef Name, FunctionPassManager &FPM, -/// ArrayRef P) { -/// if (parseAnalysisUtilityPasses("fancy-analysis", Name, -/// FPM)) -/// return true; -/// return false; -/// } -template -bool parseAnalysisUtilityPasses( - StringRef AnalysisName, StringRef PipelineName, - PassManager &PM) { - if (!PipelineName.endswith(">")) - return false; - // See if this is an invalidate<> pass name - if (PipelineName.startswith("invalidate<")) { - PipelineName = PipelineName.substr(11, PipelineName.size() - 12); - if (PipelineName != AnalysisName) - return false; - PM.addPass(InvalidateAnalysisPass()); - return true; - } - - // See if this is a require<> pass name - if (PipelineName.startswith("require<")) { - PipelineName = PipelineName.substr(8, PipelineName.size() - 9); - if (PipelineName != AnalysisName) - return false; - PM.addPass(RequireAnalysisPass()); - return true; - } - - return false; -} } #endif diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -1440,18 +1440,22 @@ /// up a dummy PassManager in order to not force the client to also handle this /// type of query. template -static bool callbacksAcceptPassName(StringRef Name, CallbacksT &Callbacks) { +bool PassBuilder::PipelineParser::callbacksAcceptPassName( + StringRef Name, CallbacksT &Callbacks) { if (!Callbacks.empty()) { PassManagerT DummyPM; + PassBuilder DummyPB; + PipelineParser DummyParser(DummyPB); for (auto &CB : Callbacks) - if (CB(Name, DummyPM, {})) + if (CB(Name, DummyPM, DummyParser, {})) return true; } return false; } template -static bool isModulePassName(StringRef Name, CallbacksT &Callbacks) { +bool PassBuilder::PipelineParser::isModulePassName(StringRef Name, + CallbacksT &Callbacks) { // Manually handle aliases for pre-configured pipeline fragments. if (startsWithDefaultPipelineAliasPrefix(Name)) return DefaultAliasRegex.match(Name); @@ -1480,7 +1484,8 @@ } template -static bool isCGSCCPassName(StringRef Name, CallbacksT &Callbacks) { +bool PassBuilder::PipelineParser::isCGSCCPassName(StringRef Name, + CallbacksT &Callbacks) { // Explicitly handle pass manager names. if (Name == "cgscc") return true; @@ -1505,7 +1510,8 @@ } template -static bool isFunctionPassName(StringRef Name, CallbacksT &Callbacks) { +bool PassBuilder::PipelineParser::isFunctionPassName(StringRef Name, + CallbacksT &Callbacks) { // Explicitly handle pass manager names. if (Name == "function") return true; @@ -1531,7 +1537,8 @@ } template -static bool isLoopPassName(StringRef Name, CallbacksT &Callbacks) { +bool PassBuilder::PipelineParser::isLoopPassName(StringRef Name, + CallbacksT &Callbacks) { // Explicitly handle pass manager names. if (Name == "loop") return true; @@ -1551,8 +1558,11 @@ return callbacksAcceptPassName(Name, Callbacks); } -Optional> -PassBuilder::parsePipelineText(StringRef Text) { +Optional> +PassBuilder::PipelineParser::parsePipelineText(StringRef Text) { + if (Text.empty()) + return None; + std::vector ResultPipeline; SmallVector *, 4> PipelineStack = { @@ -1608,9 +1618,10 @@ return {std::move(ResultPipeline)}; } -Error PassBuilder::parseModulePass(ModulePassManager &MPM, - const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging) { +Error PassBuilder::PipelineParser::parseModulePass(ModulePassManager &MPM, + const PipelineElement &E, + bool VerifyEachPass, + bool DebugLogging) const { auto &Name = E.Name; auto &InnerPipeline = E.InnerPipeline; @@ -1649,8 +1660,8 @@ return Error::success(); } - for (auto &C : ModulePipelineParsingCallbacks) - if (C(Name, MPM, InnerPipeline)) + for (auto &C : PB.ModulePipelineParsingCallbacks) + if (C(Name, MPM, *this, InnerPipeline)) return Error::success(); // Normal passes can't have pipelines. @@ -1682,16 +1693,16 @@ return Error::success(); if (Matches[1] == "default") { - MPM.addPass(buildPerModuleDefaultPipeline(L, DebugLogging)); + MPM.addPass(PB.buildPerModuleDefaultPipeline(L, DebugLogging)); } else if (Matches[1] == "thinlto-pre-link") { - MPM.addPass(buildThinLTOPreLinkDefaultPipeline(L, DebugLogging)); + MPM.addPass(PB.buildThinLTOPreLinkDefaultPipeline(L, DebugLogging)); } else if (Matches[1] == "thinlto") { - MPM.addPass(buildThinLTODefaultPipeline(L, DebugLogging, nullptr)); + MPM.addPass(PB.buildThinLTODefaultPipeline(L, DebugLogging, nullptr)); } else if (Matches[1] == "lto-pre-link") { - MPM.addPass(buildLTOPreLinkDefaultPipeline(L, DebugLogging)); + MPM.addPass(PB.buildLTOPreLinkDefaultPipeline(L, DebugLogging)); } else { assert(Matches[1] == "lto" && "Not one of the matched options!"); - MPM.addPass(buildLTODefaultPipeline(L, DebugLogging, nullptr)); + MPM.addPass(PB.buildLTODefaultPipeline(L, DebugLogging, nullptr)); } return Error::success(); } @@ -1716,17 +1727,18 @@ } #include "PassRegistry.def" - for (auto &C : ModulePipelineParsingCallbacks) - if (C(Name, MPM, InnerPipeline)) + for (auto &C : PB.ModulePipelineParsingCallbacks) + if (C(Name, MPM, *this, InnerPipeline)) return Error::success(); return make_error( formatv("unknown module pass '{0}'", Name).str(), inconvertibleErrorCode()); } -Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, - const PipelineElement &E, bool VerifyEachPass, - bool DebugLogging) { +Error PassBuilder::PipelineParser::parseCGSCCPass(CGSCCPassManager &CGPM, + const PipelineElement &E, + bool VerifyEachPass, + bool DebugLogging) const { auto &Name = E.Name; auto &InnerPipeline = E.InnerPipeline; @@ -1768,8 +1780,8 @@ return Error::success(); } - for (auto &C : CGSCCPipelineParsingCallbacks) - if (C(Name, CGPM, InnerPipeline)) + for (auto &C : PB.CGSCCPipelineParsingCallbacks) + if (C(Name, CGPM, *this, InnerPipeline)) return Error::success(); // Normal passes can't have pipelines. @@ -1799,17 +1811,18 @@ } #include "PassRegistry.def" - for (auto &C : CGSCCPipelineParsingCallbacks) - if (C(Name, CGPM, InnerPipeline)) + for (auto &C : PB.CGSCCPipelineParsingCallbacks) + if (C(Name, CGPM, *this, InnerPipeline)) return Error::success(); return make_error( formatv("unknown cgscc pass '{0}'", Name).str(), inconvertibleErrorCode()); } -Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM, - const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging) { +Error PassBuilder::PipelineParser::parseFunctionPass(FunctionPassManager &FPM, + const PipelineElement &E, + bool VerifyEachPass, + bool DebugLogging) const { auto &Name = E.Name; auto &InnerPipeline = E.InnerPipeline; @@ -1843,8 +1856,8 @@ return Error::success(); } - for (auto &C : FunctionPipelineParsingCallbacks) - if (C(Name, FPM, InnerPipeline)) + for (auto &C : PB.FunctionPipelineParsingCallbacks) + if (C(Name, FPM, *this, InnerPipeline)) return Error::success(); // Normal passes can't have pipelines. @@ -1881,16 +1894,18 @@ } #include "PassRegistry.def" - for (auto &C : FunctionPipelineParsingCallbacks) - if (C(Name, FPM, InnerPipeline)) + for (auto &C : PB.FunctionPipelineParsingCallbacks) + if (C(Name, FPM, *this, InnerPipeline)) return Error::success(); return make_error( formatv("unknown function pass '{0}'", Name).str(), inconvertibleErrorCode()); } -Error PassBuilder::parseLoopPass(LoopPassManager &LPM, const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging) { +Error PassBuilder::PipelineParser::parseLoopPass(LoopPassManager &LPM, + const PipelineElement &E, + bool VerifyEachPass, + bool DebugLogging) const { StringRef Name = E.Name; auto &InnerPipeline = E.InnerPipeline; @@ -1914,8 +1929,8 @@ return Error::success(); } - for (auto &C : LoopPipelineParsingCallbacks) - if (C(Name, LPM, InnerPipeline)) + for (auto &C : PB.LoopPipelineParsingCallbacks) + if (C(Name, LPM, *this, InnerPipeline)) return Error::success(); // Normal passes can't have pipelines. @@ -1945,8 +1960,8 @@ } #include "PassRegistry.def" - for (auto &C : LoopPipelineParsingCallbacks) - if (C(Name, LPM, InnerPipeline)) + for (auto &C : PB.LoopPipelineParsingCallbacks) + if (C(Name, LPM, *this, InnerPipeline)) return Error::success(); return make_error(formatv("unknown loop pass '{0}'", Name).str(), inconvertibleErrorCode()); @@ -1973,10 +1988,9 @@ return false; } -Error PassBuilder::parseLoopPassPipeline(LoopPassManager &LPM, - ArrayRef Pipeline, - bool VerifyEachPass, - bool DebugLogging) { +Error PassBuilder::PipelineParser::parseLoopPassPipeline( + LoopPassManager &LPM, ArrayRef Pipeline, + bool VerifyEachPass, bool DebugLogging) const { for (const auto &Element : Pipeline) { if (auto Err = parseLoopPass(LPM, Element, VerifyEachPass, DebugLogging)) return Err; @@ -1985,10 +1999,9 @@ return Error::success(); } -Error PassBuilder::parseFunctionPassPipeline(FunctionPassManager &FPM, - ArrayRef Pipeline, - bool VerifyEachPass, - bool DebugLogging) { +Error PassBuilder::PipelineParser::parseFunctionPassPipeline( + FunctionPassManager &FPM, ArrayRef Pipeline, + bool VerifyEachPass, bool DebugLogging) const { for (const auto &Element : Pipeline) { if (auto Err = parseFunctionPass(FPM, Element, VerifyEachPass, DebugLogging)) @@ -1999,10 +2012,9 @@ return Error::success(); } -Error PassBuilder::parseCGSCCPassPipeline(CGSCCPassManager &CGPM, - ArrayRef Pipeline, - bool VerifyEachPass, - bool DebugLogging) { +Error PassBuilder::PipelineParser::parseCGSCCPassPipeline( + CGSCCPassManager &CGPM, ArrayRef Pipeline, + bool VerifyEachPass, bool DebugLogging) const { for (const auto &Element : Pipeline) { if (auto Err = parseCGSCCPass(CGPM, Element, VerifyEachPass, DebugLogging)) return Err; @@ -2024,10 +2036,9 @@ LAM.registerPass([&] { return FunctionAnalysisManagerLoopProxy(FAM); }); } -Error PassBuilder::parseModulePassPipeline(ModulePassManager &MPM, - ArrayRef Pipeline, - bool VerifyEachPass, - bool DebugLogging) { +Error PassBuilder::PipelineParser::parseModulePassPipeline( + ModulePassManager &MPM, ArrayRef Pipeline, + bool VerifyEachPass, bool DebugLogging) const { for (const auto &Element : Pipeline) { if (auto Err = parseModulePass(MPM, Element, VerifyEachPass, DebugLogging)) return Err; @@ -2040,10 +2051,10 @@ // Primary pass pipeline description parsing routine for a \c ModulePassManager // FIXME: Should this routine accept a TargetMachine or require the caller to // pre-populate the analysis managers with target-specific stuff? -Error PassBuilder::parsePassPipeline(ModulePassManager &MPM, - StringRef PipelineText, - bool VerifyEachPass, bool DebugLogging) { - auto Pipeline = parsePipelineText(PipelineText); +Error PassBuilder::PipelineParser::parsePassPipeline(ModulePassManager &MPM, + bool VerifyEachPass, + bool DebugLogging) { + Pipeline = parsePipelineText(PipelineText); if (!Pipeline || Pipeline->empty()) return make_error( formatv("invalid pipeline '{0}'", PipelineText).str(), @@ -2053,17 +2064,17 @@ // automatically. StringRef FirstName = Pipeline->front().Name; - if (!isModulePassName(FirstName, ModulePipelineParsingCallbacks)) { - if (isCGSCCPassName(FirstName, CGSCCPipelineParsingCallbacks)) { + if (!isModulePassName(FirstName, PB.ModulePipelineParsingCallbacks)) { + if (isCGSCCPassName(FirstName, PB.CGSCCPipelineParsingCallbacks)) { Pipeline = {{"cgscc", std::move(*Pipeline)}}; } else if (isFunctionPassName(FirstName, - FunctionPipelineParsingCallbacks)) { + PB.FunctionPipelineParsingCallbacks)) { Pipeline = {{"function", std::move(*Pipeline)}}; - } else if (isLoopPassName(FirstName, LoopPipelineParsingCallbacks)) { + } else if (isLoopPassName(FirstName, PB.LoopPipelineParsingCallbacks)) { Pipeline = {{"function", {{"loop", std::move(*Pipeline)}}}}; } else { - for (auto &C : TopLevelPipelineParsingCallbacks) - if (C(MPM, *Pipeline, VerifyEachPass, DebugLogging)) + for (auto &C : PB.TopLevelPipelineParsingCallbacks) + if (C(MPM, *this, *Pipeline, VerifyEachPass, DebugLogging)) return Error::success(); // Unknown pass or pipeline name! @@ -2083,17 +2094,17 @@ } // Primary pass pipeline description parsing routine for a \c CGSCCPassManager -Error PassBuilder::parsePassPipeline(CGSCCPassManager &CGPM, - StringRef PipelineText, - bool VerifyEachPass, bool DebugLogging) { - auto Pipeline = parsePipelineText(PipelineText); +Error PassBuilder::PipelineParser::parsePassPipeline(CGSCCPassManager &CGPM, + bool VerifyEachPass, + bool DebugLogging) { + Pipeline = parsePipelineText(PipelineText); if (!Pipeline || Pipeline->empty()) return make_error( formatv("invalid pipeline '{0}'", PipelineText).str(), inconvertibleErrorCode()); StringRef FirstName = Pipeline->front().Name; - if (!isCGSCCPassName(FirstName, CGSCCPipelineParsingCallbacks)) + if (!isCGSCCPassName(FirstName, PB.CGSCCPipelineParsingCallbacks)) return make_error( formatv("unknown cgscc pass '{0}' in pipeline '{1}'", FirstName, PipelineText) @@ -2108,17 +2119,17 @@ // Primary pass pipeline description parsing routine for a \c // FunctionPassManager -Error PassBuilder::parsePassPipeline(FunctionPassManager &FPM, - StringRef PipelineText, - bool VerifyEachPass, bool DebugLogging) { - auto Pipeline = parsePipelineText(PipelineText); +Error PassBuilder::PipelineParser::parsePassPipeline(FunctionPassManager &FPM, + bool VerifyEachPass, + bool DebugLogging) { + Pipeline = parsePipelineText(PipelineText); if (!Pipeline || Pipeline->empty()) return make_error( formatv("invalid pipeline '{0}'", PipelineText).str(), inconvertibleErrorCode()); StringRef FirstName = Pipeline->front().Name; - if (!isFunctionPassName(FirstName, FunctionPipelineParsingCallbacks)) + if (!isFunctionPassName(FirstName, PB.FunctionPipelineParsingCallbacks)) return make_error( formatv("unknown function pass '{0}' in pipeline '{1}'", FirstName, PipelineText) @@ -2132,10 +2143,10 @@ } // Primary pass pipeline description parsing routine for a \c LoopPassManager -Error PassBuilder::parsePassPipeline(LoopPassManager &CGPM, - StringRef PipelineText, - bool VerifyEachPass, bool DebugLogging) { - auto Pipeline = parsePipelineText(PipelineText); +Error PassBuilder::PipelineParser::parsePassPipeline(LoopPassManager &CGPM, + bool VerifyEachPass, + bool DebugLogging) { + Pipeline = parsePipelineText(PipelineText); if (!Pipeline || Pipeline->empty()) return make_error( formatv("invalid pipeline '{0}'", PipelineText).str(), diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp --- a/llvm/tools/opt/NewPMDriver.cpp +++ b/llvm/tools/opt/NewPMDriver.cpp @@ -279,7 +279,8 @@ // Register a callback that creates the debugify passes as needed. PB.registerPipelineParsingCallback( [](StringRef Name, ModulePassManager &MPM, - ArrayRef) { + const PassBuilder::PipelineParser &Parser, + ArrayRef) { if (Name == "debugify") { MPM.addPass(NewPMDebugifyPass()); return true; diff --git a/llvm/unittests/IR/PassBuilderCallbacksTest.cpp b/llvm/unittests/IR/PassBuilderCallbacksTest.cpp --- a/llvm/unittests/IR/PassBuilderCallbacksTest.cpp +++ b/llvm/unittests/IR/PassBuilderCallbacksTest.cpp @@ -435,11 +435,14 @@ /// the latter case, the InnerPipeline is not empty. PB.registerPipelineParsingCallback( [this](StringRef Name, PassManagerT &PM, - ArrayRef InnerPipeline) { + const PassBuilder::PipelineParser &Parser, + ArrayRef + InnerPipeline) { /// Handle parsing of the names of analysis utilities such as /// require and invalidate for our /// analysis mock handle - if (parseAnalysisUtilityPasses("test-analysis", Name, PM)) + if (Parser.parseAnalysisUtilityPasses("test-analysis", + Name, PM)) return true; /// Parse the name of our pass mock handle @@ -942,25 +945,27 @@ /// 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, const PassBuilder::PipelineParser &Parser, + 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 (Parser.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(""), _)) diff --git a/llvm/unittests/Passes/TestPlugin.cpp b/llvm/unittests/Passes/TestPlugin.cpp --- a/llvm/unittests/Passes/TestPlugin.cpp +++ b/llvm/unittests/Passes/TestPlugin.cpp @@ -22,7 +22,8 @@ void registerCallbacks(PassBuilder &PB) { PB.registerPipelineParsingCallback( [](StringRef Name, ModulePassManager &PM, - ArrayRef InnerPipeline) { + const PassBuilder::PipelineParser &Parser, + ArrayRef InnerPipeline) { if (Name == "plugin-pass") { PM.addPass(TestModulePass()); return true;