From 3c95d9ccc0a18e5c88ff73ab0803c06155cc612d Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Tue, 13 Jan 2015 22:42:38 +0000 Subject: [PATCH] [PM] Push the debug option for the new pass manager into the opt tool and expose the necessary hooks in the API directly. This makes it much cleaner for example to log the usage of a pass manager from a library. It also makes it more obvious that this functionality isn't "optional" or "asserts-only" for the pass manager. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225841 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/PassManager.h | 48 ++++++++++++++++++++------------ lib/IR/PassManager.cpp | 5 ---- tools/opt/NewPMDriver.cpp | 14 ++++++---- tools/opt/Passes.cpp | 52 ++++++++++++++++++++--------------- tools/opt/Passes.h | 3 +- 5 files changed, 70 insertions(+), 52 deletions(-) diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h index 0b2a0c4ab7b..26257684926 100644 --- a/include/llvm/IR/PassManager.h +++ b/include/llvm/IR/PassManager.h @@ -56,13 +56,6 @@ namespace llvm { class Module; class Function; -namespace detail { - -// Declare our debug option here so we can refer to it from templates. -extern cl::opt DebugPM; - -} // End detail namespace - /// \brief An abstract set of preserved analyses following a transformation pass /// run. /// @@ -185,12 +178,18 @@ template class AnalysisManager; /// runs. template class PassManager { public: + /// \brief Construct a pass manager. + /// + /// It can be passed a flag to get debug logging as the passes are run. + PassManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - PassManager() {} - PassManager(PassManager &&Arg) : Passes(std::move(Arg.Passes)) {} + PassManager(PassManager &&Arg) + : Passes(std::move(Arg.Passes)), + DebugLogging(std::move(Arg.DebugLogging)) {} PassManager &operator=(PassManager &&RHS) { Passes = std::move(RHS.Passes); + DebugLogging = std::move(RHS.DebugLogging); return *this; } @@ -198,11 +197,11 @@ public: PreservedAnalyses run(IRUnitT &IR, AnalysisManager *AM = nullptr) { PreservedAnalyses PA = PreservedAnalyses::all(); - if (detail::DebugPM) + if (DebugLogging) dbgs() << "Starting pass manager run.\n"; for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) { - if (detail::DebugPM) + if (DebugLogging) dbgs() << "Running pass: " << Passes[Idx]->name() << "\n"; PreservedAnalyses PassPA = Passes[Idx]->run(IR, AM); @@ -226,7 +225,7 @@ public: //IR.getContext().yield(); } - if (detail::DebugPM) + if (DebugLogging) dbgs() << "Finished pass manager run.\n"; return PA; @@ -246,6 +245,9 @@ private: PassManager &operator=(const PassManager &) LLVM_DELETED_FUNCTION; std::vector> Passes; + + /// \brief Flag indicating whether we should do debug logging. + bool DebugLogging; }; /// \brief Convenience typedef for a pass manager over modules. @@ -412,15 +414,22 @@ class AnalysisManager public: // Most public APIs are inherited from the CRTP base class. + /// \brief Construct an empty analysis manager. + /// + /// A flag can be passed to indicate that the manager should perform debug + /// logging. + AnalysisManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {} + // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - AnalysisManager() {} AnalysisManager(AnalysisManager &&Arg) : BaseT(std::move(static_cast(Arg))), - AnalysisResults(std::move(Arg.AnalysisResults)) {} + AnalysisResults(std::move(Arg.AnalysisResults)), + DebugLogging(std::move(Arg.DebugLogging)) {} AnalysisManager &operator=(AnalysisManager &&RHS) { BaseT::operator=(std::move(static_cast(RHS))); AnalysisResults = std::move(RHS.AnalysisResults); + DebugLogging = std::move(RHS.DebugLogging); return *this; } @@ -458,7 +467,7 @@ private: // run it to produce a result, which we then add to the cache. if (Inserted) { auto &P = this->lookupPass(PassID); - if (detail::DebugPM) + if (DebugLogging) dbgs() << "Running analysis: " << P.name() << "\n"; AnalysisResultListT &ResultList = AnalysisResultLists[&IR]; ResultList.emplace_back(PassID, P.run(IR, this)); @@ -482,7 +491,7 @@ private: if (RI == AnalysisResults.end()) return; - if (detail::DebugPM) + if (DebugLogging) dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name() << "\n"; AnalysisResultLists[&IR].erase(RI->second); @@ -495,7 +504,7 @@ private: if (PA.areAllPreserved()) return std::move(PA); - if (detail::DebugPM) + if (DebugLogging) dbgs() << "Invalidating all non-preserved analyses for: " << IR.getName() << "\n"; @@ -512,7 +521,7 @@ private: // necessary. The analysis pass can return false if no action on the part // of the analysis manager is required for this invalidation event. if (I->second->invalidate(IR, PA)) { - if (detail::DebugPM) + if (DebugLogging) dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name() << "\n"; @@ -562,6 +571,9 @@ private: /// \brief Map from an analysis ID and function to a particular cached /// analysis result. AnalysisResultMapT AnalysisResults; + + /// \brief A flag indicating whether debug logging is enabled. + bool DebugLogging; }; /// \brief Convenience typedef for the Module analysis manager. diff --git a/lib/IR/PassManager.cpp b/lib/IR/PassManager.cpp index 3e6efb70260..a5f407c00e8 100644 --- a/lib/IR/PassManager.cpp +++ b/lib/IR/PassManager.cpp @@ -12,11 +12,6 @@ #include "llvm/IR/PassManager.h" using namespace llvm; -using llvm::detail::DebugPM; - -cl::opt llvm::detail::DebugPM( - "debug-pass-manager", cl::Hidden, - cl::desc("Print pass management debugging information")); char FunctionAnalysisManagerModuleProxy::PassID; diff --git a/tools/opt/NewPMDriver.cpp b/tools/opt/NewPMDriver.cpp index 9e24f30c188..d37211faf6d 100644 --- a/tools/opt/NewPMDriver.cpp +++ b/tools/opt/NewPMDriver.cpp @@ -30,12 +30,16 @@ using namespace llvm; using namespace opt_tool; +static cl::opt + DebugPM("debug-pass-manager", cl::Hidden, + cl::desc("Print pass management debugging information")); + bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M, tool_output_file *Out, StringRef PassPipeline, OutputKind OK, VerifierKind VK) { - FunctionAnalysisManager FAM; - CGSCCAnalysisManager CGAM; - ModuleAnalysisManager MAM; + FunctionAnalysisManager FAM(DebugPM); + CGSCCAnalysisManager CGAM(DebugPM); + ModuleAnalysisManager MAM(DebugPM); // Register all the basic analyses with the managers. registerModuleAnalyses(MAM); @@ -50,11 +54,11 @@ bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M, FAM.registerPass(CGSCCAnalysisManagerFunctionProxy(CGAM)); FAM.registerPass(ModuleAnalysisManagerFunctionProxy(MAM)); - ModulePassManager MPM; + ModulePassManager MPM(DebugPM); if (VK > VK_NoVerifier) MPM.addPass(VerifierPass()); - if (!parsePassPipeline(MPM, PassPipeline, VK == VK_VerifyEachPass)) { + if (!parsePassPipeline(MPM, PassPipeline, VK == VK_VerifyEachPass, DebugPM)) { errs() << Arg0 << ": unable to parse pass pipeline description.\n"; return false; } diff --git a/tools/opt/Passes.cpp b/tools/opt/Passes.cpp index 69301256f89..c81c5633684 100644 --- a/tools/opt/Passes.cpp +++ b/tools/opt/Passes.cpp @@ -196,15 +196,16 @@ static bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name) { static bool parseFunctionPassPipeline(FunctionPassManager &FPM, StringRef &PipelineText, - bool VerifyEachPass) { + bool VerifyEachPass, bool DebugLogging) { for (;;) { // Parse nested pass managers by recursing. if (PipelineText.startswith("function(")) { - FunctionPassManager NestedFPM; + FunctionPassManager NestedFPM(DebugLogging); // Parse the inner pipeline inte the nested manager. PipelineText = PipelineText.substr(strlen("function(")); - if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) || + if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass, + DebugLogging) || PipelineText.empty()) return false; assert(PipelineText[0] == ')'); @@ -232,16 +233,17 @@ static bool parseFunctionPassPipeline(FunctionPassManager &FPM, } static bool parseCGSCCPassPipeline(CGSCCPassManager &CGPM, - StringRef &PipelineText, - bool VerifyEachPass) { + StringRef &PipelineText, bool VerifyEachPass, + bool DebugLogging) { for (;;) { // Parse nested pass managers by recursing. if (PipelineText.startswith("cgscc(")) { - CGSCCPassManager NestedCGPM; + CGSCCPassManager NestedCGPM(DebugLogging); // Parse the inner pipeline into the nested manager. PipelineText = PipelineText.substr(strlen("cgscc(")); - if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass) || + if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass, + DebugLogging) || PipelineText.empty()) return false; assert(PipelineText[0] == ')'); @@ -250,11 +252,12 @@ static bool parseCGSCCPassPipeline(CGSCCPassManager &CGPM, // Add the nested pass manager with the appropriate adaptor. CGPM.addPass(std::move(NestedCGPM)); } else if (PipelineText.startswith("function(")) { - FunctionPassManager NestedFPM; + FunctionPassManager NestedFPM(DebugLogging); // Parse the inner pipeline inte the nested manager. PipelineText = PipelineText.substr(strlen("function(")); - if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) || + if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass, + DebugLogging) || PipelineText.empty()) return false; assert(PipelineText[0] == ')'); @@ -282,15 +285,16 @@ static bool parseCGSCCPassPipeline(CGSCCPassManager &CGPM, static bool parseModulePassPipeline(ModulePassManager &MPM, StringRef &PipelineText, - bool VerifyEachPass) { + bool VerifyEachPass, bool DebugLogging) { for (;;) { // Parse nested pass managers by recursing. if (PipelineText.startswith("module(")) { - ModulePassManager NestedMPM; + ModulePassManager NestedMPM(DebugLogging); // Parse the inner pipeline into the nested manager. PipelineText = PipelineText.substr(strlen("module(")); - if (!parseModulePassPipeline(NestedMPM, PipelineText, VerifyEachPass) || + if (!parseModulePassPipeline(NestedMPM, PipelineText, VerifyEachPass, + DebugLogging) || PipelineText.empty()) return false; assert(PipelineText[0] == ')'); @@ -299,11 +303,12 @@ static bool parseModulePassPipeline(ModulePassManager &MPM, // Now add the nested manager as a module pass. MPM.addPass(std::move(NestedMPM)); } else if (PipelineText.startswith("cgscc(")) { - CGSCCPassManager NestedCGPM; + CGSCCPassManager NestedCGPM(DebugLogging); // Parse the inner pipeline inte the nested manager. PipelineText = PipelineText.substr(strlen("cgscc(")); - if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass) || + if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass, + DebugLogging) || PipelineText.empty()) return false; assert(PipelineText[0] == ')'); @@ -313,11 +318,12 @@ static bool parseModulePassPipeline(ModulePassManager &MPM, MPM.addPass( createModuleToPostOrderCGSCCPassAdaptor(std::move(NestedCGPM))); } else if (PipelineText.startswith("function(")) { - FunctionPassManager NestedFPM; + FunctionPassManager NestedFPM(DebugLogging); // Parse the inner pipeline inte the nested manager. PipelineText = PipelineText.substr(strlen("function(")); - if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) || + if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass, + DebugLogging) || PipelineText.empty()) return false; assert(PipelineText[0] == ')'); @@ -348,11 +354,11 @@ static bool parseModulePassPipeline(ModulePassManager &MPM, // FIXME: Should this routine accept a TargetMachine or require the caller to // pre-populate the analysis managers with target-specific stuff? bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, - bool VerifyEachPass) { + bool VerifyEachPass, bool DebugLogging) { // By default, try to parse the pipeline as-if it were within an implicit // 'module(...)' pass pipeline. If this will parse at all, it needs to // consume the entire string. - if (parseModulePassPipeline(MPM, PipelineText, VerifyEachPass)) + if (parseModulePassPipeline(MPM, PipelineText, VerifyEachPass, DebugLogging)) return PipelineText.empty(); // This isn't parsable as a module pipeline, look for the end of a pass name @@ -365,8 +371,9 @@ bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, // If this looks like a CGSCC pass, parse the whole thing as a CGSCC // pipeline. if (isCGSCCPassName(FirstName)) { - CGSCCPassManager CGPM; - if (!parseCGSCCPassPipeline(CGPM, PipelineText, VerifyEachPass) || + CGSCCPassManager CGPM(DebugLogging); + if (!parseCGSCCPassPipeline(CGPM, PipelineText, VerifyEachPass, + DebugLogging) || !PipelineText.empty()) return false; MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); @@ -376,8 +383,9 @@ bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, // Similarly, if this looks like a Function pass, parse the whole thing as // a Function pipelien. if (isFunctionPassName(FirstName)) { - FunctionPassManager FPM; - if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) || + FunctionPassManager FPM(DebugLogging); + if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass, + DebugLogging) || !PipelineText.empty()) return false; MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); diff --git a/tools/opt/Passes.h b/tools/opt/Passes.h index f8273be1e9d..9e58e8b8ac3 100644 --- a/tools/opt/Passes.h +++ b/tools/opt/Passes.h @@ -72,8 +72,7 @@ void registerFunctionAnalyses(FunctionAnalysisManager &FAM); /// an error. You cannot mix different levels implicitly, you must explicitly /// form a pass manager in which to nest passes. bool parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, - bool VerifyEachPass = true); - + bool VerifyEachPass = true, bool DebugLogging = false); } #endif