Index: llvm/include/llvm/IR/PassManager.h =================================================================== --- llvm/include/llvm/IR/PassManager.h +++ llvm/include/llvm/IR/PassManager.h @@ -381,6 +381,19 @@ Name = Name.drop_front(strlen("llvm::")); return Name; } + + void printPipeline(raw_ostream &OS, PassInstrumentationCallbacks &PIC) { + auto ClassName = name(); + auto PassName = PIC.getPassNameForClassName(ClassName); + if (!PassName.empty()) { + OS << PassName; + static_cast(this)->printPipelineParams(OS); + } else { + OS << "NO-PASSNAME-FOR(" << ClassName << ")"; + } + } + + void printPipelineParams(raw_ostream &OS) {} }; /// A CRTP mix-in that provides informational APIs needed for analysis passes. @@ -480,6 +493,15 @@ return *this; } + void printPipeline(raw_ostream &OS, PassInstrumentationCallbacks &PIC) { + for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) { + auto *P = Passes[Idx].get(); + P->printPipeline(OS, PIC); + if (Idx + 1 < Size) + OS << ","; + } + } + /// Run all of the passes in this manager over the given unit of IR. /// ExtraArgs are passed to each pass. PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, @@ -1195,6 +1217,7 @@ /// Runs the function pass across every function in the module. PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); + void printPipeline(raw_ostream &OS, PassInstrumentationCallbacks &PIC); static bool isRequired() { return true; } Index: llvm/include/llvm/IR/PassManagerInternal.h =================================================================== --- llvm/include/llvm/IR/PassManagerInternal.h +++ llvm/include/llvm/IR/PassManagerInternal.h @@ -46,6 +46,9 @@ virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs) = 0; + virtual void printPipeline(raw_ostream &OS, + PassInstrumentationCallbacks &PIC) = 0; + virtual void printPipelineParams(raw_ostream &OS) = 0; /// Polymorphic method to access the name of a pass. virtual StringRef name() const = 0; @@ -85,6 +88,15 @@ return Pass.run(IR, AM, ExtraArgs...); } + void printPipeline(raw_ostream &OS, + PassInstrumentationCallbacks &PIC) override { + Pass.printPipeline(OS, PIC); + } + + void printPipelineParams(raw_ostream &OS) override { + Pass.printPipelineParams(OS); + } + StringRef name() const override { return PassT::name(); } template Index: llvm/include/llvm/Transforms/Scalar/LoopPassManager.h =================================================================== --- llvm/include/llvm/Transforms/Scalar/LoopPassManager.h +++ llvm/include/llvm/Transforms/Scalar/LoopPassManager.h @@ -424,6 +424,7 @@ /// Runs the loop passes across every loop in the function. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); + void printPipeline(raw_ostream &OS, PassInstrumentationCallbacks &PIC); static bool isRequired() { return true; } Index: llvm/include/llvm/Transforms/Scalar/SimplifyCFG.h =================================================================== --- llvm/include/llvm/Transforms/Scalar/SimplifyCFG.h +++ llvm/include/llvm/Transforms/Scalar/SimplifyCFG.h @@ -39,6 +39,7 @@ /// Construct a pass with optional optimizations. SimplifyCFGPass(const SimplifyCFGOptions &PassOptions); + void printPipelineParams(raw_ostream &OS); /// Run the pass over the function. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; Index: llvm/lib/IR/PassManager.cpp =================================================================== --- llvm/lib/IR/PassManager.cpp +++ llvm/lib/IR/PassManager.cpp @@ -91,6 +91,13 @@ } } // namespace llvm +void ModuleToFunctionPassAdaptor::printPipeline( + raw_ostream &OS, PassInstrumentationCallbacks &PIC) { + OS << "function("; + Pass->printPipeline(OS, PIC); + OS << ")"; +} + PreservedAnalyses ModuleToFunctionPassAdaptor::run(Module &M, ModuleAnalysisManager &AM) { FunctionAnalysisManager &FAM = Index: llvm/lib/Passes/PassBuilder.cpp =================================================================== --- llvm/lib/Passes/PassBuilder.cpp +++ llvm/lib/Passes/PassBuilder.cpp @@ -439,7 +439,7 @@ /// it. This should be updated if new pass instrumentation wants to use the map. /// We currently only use this for --print-before/after. bool shouldPopulateClassToPassNames() { - return !printBeforePasses().empty() || !printAfterPasses().empty(); + return true || !printBeforePasses().empty() || !printAfterPasses().empty(); } } // namespace Index: llvm/lib/Transforms/Scalar/LoopPassManager.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LoopPassManager.cpp +++ llvm/lib/Transforms/Scalar/LoopPassManager.cpp @@ -172,6 +172,12 @@ } } // namespace llvm +void FunctionToLoopPassAdaptor::printPipeline( + raw_ostream &OS, PassInstrumentationCallbacks &PIC) { + OS << (UseMemorySSA ? "loop-mssa(" : "loop("); + Pass->printPipeline(OS, PIC); + OS << ")"; +} PreservedAnalyses FunctionToLoopPassAdaptor::run(Function &F, FunctionAnalysisManager &AM) { // Before we even compute any loop analyses, first run a miniature function Index: llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp =================================================================== --- llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp +++ llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp @@ -319,6 +319,18 @@ applyCommandLineOverridesToOptions(Options); } +void SimplifyCFGPass::printPipelineParams(raw_ostream &OS) { + OS << "<"; + OS << "bonus-inst-threshold=" << Options.BonusInstThreshold << ";"; + OS << (Options.ForwardSwitchCondToPhi ? "" : "no-") << "forward-switch-cond;"; + OS << (Options.ConvertSwitchToLookupTable ? "" : "no-") + << "switch-to-lookup;"; + OS << (Options.NeedCanonicalLoop ? "" : "no-") << "keep-loops;"; + OS << (Options.HoistCommonInsts ? "" : "no-") << "hoist-common-insts;"; + OS << (Options.SinkCommonInsts ? "" : "no-") << "sink-common-insts"; + OS << ">"; +} + PreservedAnalyses SimplifyCFGPass::run(Function &F, FunctionAnalysisManager &AM) { auto &TTI = AM.getResult(F); Index: llvm/tools/opt/NewPMDriver.cpp =================================================================== --- llvm/tools/opt/NewPMDriver.cpp +++ llvm/tools/opt/NewPMDriver.cpp @@ -50,6 +50,10 @@ DebugifyExport("debugify-export", cl::desc("Export per-pass debugify statistics to this file"), cl::value_desc("filename")); + +cl::opt PrintPipelinePasses( + "print-pipeline-passes", + cl::desc("Print a '-passes' compatible string describing the pipeline.")); } // namespace llvm enum class DebugLogging { None, Normal, Verbose, Quiet }; @@ -473,6 +477,14 @@ // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); + // Print a textual, '-passes=' compatible, representation of pipeline if + // requested. + if (PrintPipelinePasses) { + errs() << "-passes='"; + MPM.printPipeline(errs(), PIC); + errs() << "'\n"; + } + // Now that we have all of the passes ready, run them. MPM.run(M, MAM);