diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -866,6 +866,10 @@ if (!CodeGenOpts.DebugPass.empty()) { BackendArgs.push_back("-debug-pass"); BackendArgs.push_back(CodeGenOpts.DebugPass.c_str()); + // New PM supports structure dumping. Old PM is still used for codegen, + // so we need to pass both options. + if (!CodeGenOpts.LegacyPassManager && CodeGenOpts.DebugPass == "Structure") + BackendArgs.push_back("-debug-pass-structure"); } if (!CodeGenOpts.LimitFloatPrecision.empty()) { BackendArgs.push_back("-limit-float-precision"); diff --git a/clang/test/Driver/debug-pass-structure.c b/clang/test/Driver/debug-pass-structure.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/debug-pass-structure.c @@ -0,0 +1,62 @@ +// Test that we print pass structure with new and legacy PM. +// RUN: %clang -fexperimental-new-pass-manager -fdebug-pass-structure -O3 -S -emit-llvm %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=NEWPM +// RUN: %clang -flegacy-pass-manager -fdebug-pass-structure -O0 -S -emit-llvm %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=LEGACYPM + +// NEWPM: Annotation2MetadataPass on [module] +// NEWPM-NEXT: ForceFunctionAttrsPass on [module] +// NEWPM-NEXT: InferFunctionAttrsPass on [module] +// NEWPM-NEXT: InnerAnalysisManagerProxy<{{.*}}> analysis on [module] +// NEWPM-NEXT: ModuleToFunctionPassAdaptor on [module] +// NEWPM-NEXT: OpenMPOptPass on [module] +// NEWPM-NEXT: IPSCCPPass on [module] +// NEWPM-NEXT: CalledValuePropagationPass on [module] +// NEWPM-NEXT: GlobalOptPass on [module] +// NEWPM-NEXT: ModuleToFunctionPassAdaptor on [module] +// NEWPM-NEXT: DeadArgumentEliminationPass on [module] +// NEWPM-NEXT: ModuleToFunctionPassAdaptor on [module] +// NEWPM-NEXT: ModuleInlinerWrapperPass on [module] +// NEWPM-NEXT: InlineAdvisorAnalysis analysis on [module] +// NEWPM-NEXT: RequireAnalysisPass<{{.*}}> on [module] +// NEWPM-NEXT: GlobalsAA analysis on [module] +// NEWPM-NEXT: CallGraphAnalysis analysis on [module] +// NEWPM-NEXT: RequireAnalysisPass<{{.*}}> on [module] +// NEWPM-NEXT: ProfileSummaryAnalysis analysis on [module] +// NEWPM-NEXT: ModuleToPostOrderCGSCCPassAdaptor on [module] +// NEWPM-NEXT: InnerAnalysisManagerProxy<{{.*}}> analysis on [module] +// NEWPM-NEXT: LazyCallGraphAnalysis analysis on [module] +// NEWPM-NEXT: GlobalOptPass on [module] +// NEWPM-NEXT: GlobalDCEPass on [module] +// NEWPM-NEXT: EliminateAvailableExternallyPass on [module] +// NEWPM-NEXT: ReversePostOrderFunctionAttrsPass on [module] +// NEWPM-NEXT: RequireAnalysisPass<{{.*}}> on [module] +// NEWPM-NEXT: ModuleToFunctionPassAdaptor on [module] +// NEWPM-NEXT: CGProfilePass on [module] +// NEWPM-NEXT: GlobalDCEPass on [module] +// NEWPM-NEXT: ConstantMergePass on [module] +// NEWPM-NEXT: RelLookupTableConverterPass on [module] +// NEWPM-NEXT: ModuleToFunctionPassAdaptor on [module] +// NEWPM-NEXT: PrintModulePass on [module] + +// LEGACYPM: Pass Arguments: -tti -targetlibinfo -verify +// LEGACYPM-NEXT: Target Transform Information +// LEGACYPM-NEXT: Target Library Information +// LEGACYPM-NEXT: FunctionPass Manager +// LEGACYPM-NEXT: Module Verifier +// LEGACYPM-NEXT: Pass Arguments: -tti -targetlibinfo -assumption-cache-tracker -profile-summary-info -annotation2metadata -forceattrs -basiccg -always-inline -annotation-remarks +// LEGACYPM-NEXT: Target Transform Information +// LEGACYPM-NEXT: Target Library Information +// LEGACYPM-NEXT: Assumption Cache Tracker +// LEGACYPM-NEXT: Profile summary info +// LEGACYPM-NEXT: ModulePass Manager +// LEGACYPM-NEXT: Annotation2Metadata +// LEGACYPM-NEXT: Force set function attributes +// LEGACYPM-NEXT: CallGraph Construction +// LEGACYPM-NEXT: Call Graph SCC Pass Manager +// LEGACYPM-NEXT: Inliner for always_inline functions +// LEGACYPM-NEXT: FunctionPass Manager +// LEGACYPM-NEXT: Annotation Remarks +// LEGACYPM-NEXT: Print Module IR +// LEGACYPM-NEXT: Pass Arguments: -tti +// LEGACYPM-NEXT: Target Transform Information +// LEGACYPM-NEXT: ModulePass Manager + diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h --- a/llvm/include/llvm/Passes/StandardInstrumentations.h +++ b/llvm/include/llvm/Passes/StandardInstrumentations.h @@ -82,12 +82,25 @@ // Debug logging for transformation and analysis passes. class PrintPassInstrumentation { + void printWithIdent(bool Expand, const Twine &Msg); + public: PrintPassInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {} void registerCallbacks(PassInstrumentationCallbacks &PIC); private: bool DebugLogging; + int Ident = 0; +}; + +// Pass structure dumper +class PassStructurePrinter { + int Ident = 0; + void printWithIdent(bool Expand, const Twine &Msg); + +public: + PassStructurePrinter() {} + void registerCallbacks(PassInstrumentationCallbacks &PIC); }; class PreservedCFGCheckerInstrumentation { @@ -401,6 +414,7 @@ class StandardInstrumentations { PrintIRInstrumentation PrintIR; PrintPassInstrumentation PrintPass; + PassStructurePrinter StructurePrinter; TimePassesHandler TimePasses; OptNoneInstrumentation OptNone; OptBisectInstrumentation OptBisect; diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp --- a/llvm/lib/Passes/StandardInstrumentations.cpp +++ b/llvm/lib/Passes/StandardInstrumentations.cpp @@ -20,6 +20,7 @@ #include "llvm/Analysis/LazyCallGraph.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/IR/Function.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassInstrumentation.h" #include "llvm/IR/PassManager.h" @@ -51,6 +52,10 @@ cl::desc("Print all pass management debugging information. " "`-debug-pass-manager` must also be specified")); +static cl::opt + DebugPassStructure("debug-pass-structure", cl::Hidden, cl::init(false), + cl::desc("Print pass structure information.")); + // An option that prints out the IR after passes, similar to // -print-after-all except that it only prints the IR after passes that // change the IR. Those passes that do not make changes to the IR are @@ -897,6 +902,38 @@ }); } +void PassStructurePrinter::printWithIdent(bool Expand, const Twine &Msg) { + if (!Msg.isTriviallyEmpty()) + dbgs().indent(Ident) << Msg << "\n"; + Ident = Expand ? Ident + 2 : Ident - 2; + assert(Ident >= 0); +} + +void PassStructurePrinter::registerCallbacks( + PassInstrumentationCallbacks &PIC) { + if (!DebugPassStructure) + return; + + PIC.registerBeforeNonSkippedPassCallback([this](StringRef PassID, Any IR) { + printWithIdent(true, PassID + " on " + getIRName(IR)); + }); + PIC.registerAfterPassCallback( + [this](StringRef PassID, Any IR, const PreservedAnalyses &) { + printWithIdent(false, Twine()); + }); + + PIC.registerAfterPassInvalidatedCallback( + [this](StringRef PassID, const PreservedAnalyses &) { + printWithIdent(false, Twine()); + }); + + PIC.registerBeforeAnalysisCallback([this](StringRef PassID, Any IR) { + printWithIdent(true, PassID + " analysis on " + getIRName(IR)); + }); + PIC.registerAfterAnalysisCallback( + [this](StringRef PassID, Any IR) { printWithIdent(false, Twine()); }); +} + PreservedCFGCheckerInstrumentation::CFG::CFG(const Function *F, bool TrackBBLifetime) { if (TrackBBLifetime) @@ -1195,6 +1232,7 @@ PassInstrumentationCallbacks &PIC, FunctionAnalysisManager *FAM) { PrintIR.registerCallbacks(PIC); PrintPass.registerCallbacks(PIC); + StructurePrinter.registerCallbacks(PIC); TimePasses.registerCallbacks(PIC); OptNone.registerCallbacks(PIC); OptBisect.registerCallbacks(PIC); diff --git a/llvm/test/Other/opt-O3-pipeline.ll b/llvm/test/Other/opt-O3-pipeline.ll --- a/llvm/test/Other/opt-O3-pipeline.ll +++ b/llvm/test/Other/opt-O3-pipeline.ll @@ -1,4 +1,5 @@ ; RUN: opt -enable-new-pm=0 -mtriple=x86_64-- -O3 -debug-pass=Structure < %s -o /dev/null 2>&1 | FileCheck --check-prefixes=CHECK,%llvmcheckext %s +; RUN: opt -enable-new-pm=1 -mtriple=x86_64-- -O3 -debug-pass-structure < %s -o /dev/null 2>&1 | FileCheck --check-prefixes=NEWPM,%llvmcheckext %s ; REQUIRES: asserts @@ -335,6 +336,178 @@ ; CHECK-NEXT: Branch Probability Analysis ; CHECK-NEXT: Block Frequency Analysis +; NEWPM: VerifierPass on [module] +; NEWPM-NEXT: VerifierAnalysis analysis on [module] +; NEWPM-NEXT: Annotation2MetadataPass on [module] +; NEWPM-NEXT: ForceFunctionAttrsPass on [module] +; NEWPM-NEXT: InferFunctionAttrsPass on [module] +; NEWPM-NEXT: InnerAnalysisManagerProxy<{{.*}}> analysis on [module] +; NEWPM-NEXT: ModuleToFunctionPassAdaptor on [module] +; NEWPM-NEXT: PassManager<{{.*}}> on f +; NEWPM-NEXT: PreservedCFGCheckerAnalysis analysis on f +; NEWPM-NEXT: LowerExpectIntrinsicPass on f +; NEWPM-NEXT: SimplifyCFGPass on f +; NEWPM-NEXT: TargetIRAnalysis analysis on f +; NEWPM-NEXT: AssumptionAnalysis analysis on f +; NEWPM-NEXT: SROA on f +; NEWPM-NEXT: DominatorTreeAnalysis analysis on f +; NEWPM-NEXT: EarlyCSEPass on f +; NEWPM-NEXT: TargetLibraryAnalysis analysis on f +; NEWPM-NEXT: CallSiteSplittingPass on f +; NEWPM-NEXT: OpenMPOptPass on [module] +; NEWPM-NEXT: IPSCCPPass on [module] +; NEWPM-NEXT: CalledValuePropagationPass on [module] +; NEWPM-NEXT: GlobalOptPass on [module] +; NEWPM-NEXT: ModuleToFunctionPassAdaptor on [module] +; NEWPM-NEXT: InnerAnalysisManagerProxy<{{.*}}> analysis on [module] +; NEWPM-NEXT: PromotePass on f +; NEWPM-NEXT: PreservedCFGCheckerAnalysis analysis on f +; NEWPM-NEXT: DominatorTreeAnalysis analysis on f +; NEWPM-NEXT: AssumptionAnalysis analysis on f +; NEWPM-NEXT: DeadArgumentEliminationPass on [module] +; NEWPM-NEXT: ModuleToFunctionPassAdaptor on [module] +; NEWPM-NEXT: PassManager<{{.*}}> on f +; NEWPM-NEXT: InstCombinePass on f +; NEWPM-NEXT: TargetLibraryAnalysis analysis on f +; NEWPM-NEXT: OptimizationRemarkEmitterAnalysis analysis on f +; NEWPM-NEXT: TargetIRAnalysis analysis on f +; NEWPM-NEXT: AAManager analysis on f +; NEWPM-NEXT: BasicAA analysis on f +; NEWPM-NEXT: OuterAnalysisManagerProxy<{{.*}}> analysis on f +; NEWPM-NEXT: SimplifyCFGPass on f +; NEWPM-NEXT: ModuleInlinerWrapperPass on [module] +; NEWPM-NEXT: InlineAdvisorAnalysis analysis on [module] +; NEWPM-NEXT: RequireAnalysisPass<{{.*}}> on [module] +; NEWPM-NEXT: GlobalsAA analysis on [module] +; NEWPM-NEXT: CallGraphAnalysis analysis on [module] +; NEWPM-NEXT: RequireAnalysisPass<{{.*}}> on [module] +; NEWPM-NEXT: ProfileSummaryAnalysis analysis on [module] +; NEWPM-NEXT: ModuleToPostOrderCGSCCPassAdaptor on [module] +; NEWPM-NEXT: InnerAnalysisManagerProxy<{{.*}}> analysis on [module] +; NEWPM-NEXT: LazyCallGraphAnalysis analysis on [module] +; NEWPM-NEXT: FunctionAnalysisManagerCGSCCProxy analysis on (f) +; NEWPM-NEXT: OuterAnalysisManagerProxy<{{.*}}> analysis on (f) +; NEWPM-NEXT: DevirtSCCRepeatedPass on (f) +; NEWPM-NEXT: PassManager<{{.*}}> on (f) +; NEWPM-NEXT: InlinerPass on (f) +; NEWPM-NEXT: InlinerPass on (f) +; NEWPM-NEXT: PostOrderFunctionAttrsPass on (f) +; NEWPM-NEXT: ArgumentPromotionPass on (f) +; NEWPM-NEXT: OpenMPOptCGSCCPass on (f) +; NEWPM-NEXT: CGSCCToFunctionPassAdaptor on (f) +; NEWPM-NEXT: PassManager<{{.*}}> on f +; NEWPM-NEXT: PreservedCFGCheckerAnalysis analysis on f +; NEWPM-NEXT: SROA on f +; NEWPM-NEXT: DominatorTreeAnalysis analysis on f +; NEWPM-NEXT: EarlyCSEPass on f +; NEWPM-NEXT: MemorySSAAnalysis analysis on f +; NEWPM-NEXT: AAManager analysis on f +; NEWPM-NEXT: BasicAA analysis on f +; NEWPM-NEXT: SpeculativeExecutionPass on f +; NEWPM-NEXT: JumpThreadingPass on f +; NEWPM-NEXT: LazyValueAnalysis analysis on f +; NEWPM-NEXT: CorrelatedValuePropagationPass on f +; NEWPM-NEXT: SimplifyCFGPass on f +; NEWPM-NEXT: AggressiveInstCombinePass on f +; NEWPM-NEXT: InstCombinePass on f +; NEWPM-NEXT: LibCallsShrinkWrapPass on f +; NEWPM-NEXT: TailCallElimPass on f +; NEWPM-NEXT: SimplifyCFGPass on f +; NEWPM-NEXT: ReassociatePass on f +; NEWPM-NEXT: RequireAnalysisPass<{{.*}}> on f +; NEWPM-NEXT: FunctionToLoopPassAdaptor on f +; NEWPM-NEXT: PassManager<{{.*}}> on f +; NEWPM-NEXT: LoopSimplifyPass on f +; NEWPM-NEXT: LoopAnalysis analysis on f +; NEWPM-NEXT: LCSSAPass on f +; NEWPM-NEXT: SimplifyCFGPass on f +; NEWPM-NEXT: InstCombinePass on f +; NEWPM-NEXT: FunctionToLoopPassAdaptor on f +; NEWPM-NEXT: PassManager<{{.*}}> on f +; NEWPM-NEXT: LoopSimplifyPass on f +; NEWPM-NEXT: LCSSAPass on f +; NEWPM-NEXT: SROA on f +; NEWPM-NEXT: MergedLoadStoreMotionPass on f +; NEWPM-NEXT: GVN on f +; NEWPM-NEXT: MemoryDependenceAnalysis analysis on f +; NEWPM-NEXT: PhiValuesAnalysis analysis on f +; NEWPM-NEXT: SCCPPass on f +; NEWPM-NEXT: BDCEPass on f +; NEWPM-NEXT: DemandedBitsAnalysis analysis on f +; NEWPM-NEXT: InstCombinePass on f +; NEWPM-NEXT: JumpThreadingPass on f +; NEWPM-NEXT: LazyValueAnalysis analysis on f +; NEWPM-NEXT: CorrelatedValuePropagationPass on f +; NEWPM-NEXT: ADCEPass on f +; NEWPM-NEXT: PostDominatorTreeAnalysis analysis on f +; NEWPM-NEXT: MemCpyOptPass on f +; NEWPM-NEXT: DSEPass on f +; NEWPM-NEXT: FunctionToLoopPassAdaptor on f +; NEWPM-NEXT: PassManager<{{.*}}> on f +; NEWPM-NEXT: LoopSimplifyPass on f +; NEWPM-NEXT: LCSSAPass on f +; NEWPM-NEXT: SimplifyCFGPass on f +; NEWPM-NEXT: InstCombinePass on f +; NEWPM-NEXT: GlobalOptPass on [module] +; NEWPM-NEXT: GlobalDCEPass on [module] +; NEWPM-NEXT: EliminateAvailableExternallyPass on [module] +; NEWPM-NEXT: ReversePostOrderFunctionAttrsPass on [module] +; NEWPM-NEXT: CallGraphAnalysis analysis on [module] +; NEWPM-NEXT: RequireAnalysisPass<{{.*}}> on [module] +; NEWPM-NEXT: ModuleToFunctionPassAdaptor on [module] +; NEWPM-NEXT: PassManager<{{.*}}> on f +; NEWPM-NEXT: PreservedCFGCheckerAnalysis analysis on f +; NEWPM-NEXT: Float2IntPass on f +; NEWPM-NEXT: DominatorTreeAnalysis analysis on f +; NEWPM-NEXT: LowerConstantIntrinsicsPass on f +; NEWPM-NEXT: FunctionToLoopPassAdaptor on f +; NEWPM-NEXT: PassManager<{{.*}}> on f +; NEWPM-NEXT: LoopSimplifyPass on f +; NEWPM-NEXT: LoopAnalysis analysis on f +; NEWPM-NEXT: LCSSAPass on f +; NEWPM-NEXT: LoopDistributePass on f +; NEWPM-NEXT: ScalarEvolutionAnalysis analysis on f +; NEWPM-NEXT: AAManager analysis on f +; NEWPM-NEXT: BasicAA analysis on f +; NEWPM-NEXT: InnerAnalysisManagerProxy<{{.*}}> analysis on f +; NEWPM-NEXT: InjectTLIMappings on f +; NEWPM-NEXT: LoopVectorizePass on f +; NEWPM-NEXT: BlockFrequencyAnalysis analysis on f +; NEWPM-NEXT: BranchProbabilityAnalysis analysis on f +; NEWPM-NEXT: PostDominatorTreeAnalysis analysis on f +; NEWPM-NEXT: DemandedBitsAnalysis analysis on f +; NEWPM-NEXT: MemorySSAAnalysis analysis on f +; NEWPM-NEXT: LoopLoadEliminationPass on f +; NEWPM-NEXT: InstCombinePass on f +; NEWPM-NEXT: SimplifyCFGPass on f +; NEWPM-NEXT: SLPVectorizerPass on f +; NEWPM-NEXT: VectorCombinePass on f +; NEWPM-NEXT: InstCombinePass on f +; NEWPM-NEXT: LoopUnrollPass on f +; NEWPM-NEXT: WarnMissedTransformationsPass on f +; NEWPM-NEXT: InstCombinePass on f +; NEWPM-NEXT: RequireAnalysisPass<{{.*}}> on f +; NEWPM-NEXT: FunctionToLoopPassAdaptor on f +; NEWPM-NEXT: PassManager<{{.*}}> on f +; NEWPM-NEXT: LoopSimplifyPass on f +; NEWPM-NEXT: LCSSAPass on f +; NEWPM-NEXT: AlignmentFromAssumptionsPass on f +; NEWPM-NEXT: LoopSinkPass on f +; NEWPM-NEXT: InstSimplifyPass on f +; NEWPM-NEXT: DivRemPairsPass on f +; NEWPM-NEXT: SimplifyCFGPass on f +; NEWPM-NEXT: SpeculateAroundPHIsPass on f +; NEWPM-NEXT: CGProfilePass on [module] +; NEWPM-NEXT: GlobalDCEPass on [module] +; NEWPM-NEXT: ConstantMergePass on [module] +; NEWPM-NEXT: RelLookupTableConverterPass on [module] +; NEWPM-NEXT: ModuleToFunctionPassAdaptor on [module] +; NEWPM-NEXT: PassManager<{{.*}}> on f +; NEWPM-NEXT: AnnotationRemarksPass on f +; NEWPM-NEXT: VerifierPass on [module] +; NEWPM-NEXT: VerifierAnalysis analysis on [module] +; NEWPM-NEXT: BitcodeWriterPass on [module] + define void @f() { ret void }