Index: llvm/trunk/include/llvm/Passes/PassBuilder.h =================================================================== --- llvm/trunk/include/llvm/Passes/PassBuilder.h +++ llvm/trunk/include/llvm/Passes/PassBuilder.h @@ -501,6 +501,18 @@ PipelineStartEPCallbacks.push_back(C); } + /// Register a callback for a default optimizer pipeline extension point + /// + /// This extension point allows adding optimizations at the very end of the + /// function optimization pipeline. A key difference between this and the + /// legacy PassManager's OptimizerLast callback is that this extension point + /// is not triggered at O0. Extensions to the O0 pipeline should append their + /// passes to the end of the overall pipeline. + void registerOptimizerLastEPCallback( + const std::function &C) { + OptimizerLastEPCallbacks.push_back(C); + } + /// Register a callback for parsing an AliasAnalysis Name to populate /// the given AAManager \p AA void registerParseAACallback( @@ -614,6 +626,8 @@ CGSCCOptimizerLateEPCallbacks; SmallVector, 2> VectorizerStartEPCallbacks; + SmallVector, 2> + OptimizerLastEPCallbacks; // Module callbacks SmallVector, 2> PipelineStartEPCallbacks; Index: llvm/trunk/lib/Passes/PassBuilder.cpp =================================================================== --- llvm/trunk/lib/Passes/PassBuilder.cpp +++ llvm/trunk/lib/Passes/PassBuilder.cpp @@ -862,6 +862,9 @@ // inserting redudnancies into the progrem. This even includes SimplifyCFG. OptimizePM.addPass(SpeculateAroundPHIsPass()); + for (auto &C : OptimizerLastEPCallbacks) + C(OptimizePM, Level); + // Add the core optimizing pipeline. MPM.addPass(createModuleToFunctionPassAdaptor(std::move(OptimizePM))); Index: llvm/trunk/test/Other/new-pm-defaults.ll =================================================================== --- llvm/trunk/test/Other/new-pm-defaults.ll +++ llvm/trunk/test/Other/new-pm-defaults.ll @@ -66,6 +66,11 @@ ; RUN: -passes='lto-pre-link' -S %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \ ; RUN: --check-prefix=CHECK-EP-PIPELINE-START +; RUN: opt -disable-verify -debug-pass-manager \ +; RUN: -passes-ep-optimizer-last='no-op-function' \ +; RUN: -passes='default' -S %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \ +; RUN: --check-prefix=CHECK-EP-OPTIMIZER-LAST ; CHECK-O: Running analysis: PassInstrumentationAnalysis ; CHECK-O-NEXT: Starting llvm::Module pass manager run. @@ -254,6 +259,7 @@ ; CHECK-O-NEXT: Running pass: DivRemPairsPass ; CHECK-O-NEXT: Running pass: SimplifyCFGPass ; CHECK-O-NEXT: Running pass: SpeculateAroundPHIsPass +; CHECK-EP-OPTIMIZER-LAST: Running pass: NoOpFunctionPass ; CHECK-O-NEXT: Finished llvm::Function pass manager run. ; CHECK-O-NEXT: Running pass: CGProfilePass ; CHECK-O-NEXT: Running pass: GlobalDCEPass Index: llvm/trunk/tools/opt/NewPMDriver.cpp =================================================================== --- llvm/trunk/tools/opt/NewPMDriver.cpp +++ llvm/trunk/tools/opt/NewPMDriver.cpp @@ -95,6 +95,12 @@ cl::desc("A textual description of the function pass pipeline inserted at " "the PipelineStart extension point into default pipelines"), cl::Hidden); +static cl::opt OptimizerLastEPPipeline( + "passes-ep-optimizer-last", + cl::desc("A textual description of the function pass pipeline inserted at " + "the OptimizerLast extension point into default pipelines"), + cl::Hidden); + enum PGOKind { NoPGO, InstrGen, InstrUse, SampleUse }; static cl::opt PGOKindFlag( "pgo-kind", cl::init(NoPGO), cl::Hidden, @@ -195,6 +201,13 @@ Err(PB.parsePassPipeline(PM, PipelineStartEPPipeline, VerifyEachPass, DebugLogging)); }); + if (tryParsePipelineText(PB, OptimizerLastEPPipeline)) + PB.registerOptimizerLastEPCallback( + [&PB, VerifyEachPass, DebugLogging](FunctionPassManager &PM, + PassBuilder::OptimizationLevel) { + PB.parsePassPipeline(PM, OptimizerLastEPPipeline, VerifyEachPass, + DebugLogging); + }); } #ifdef LINK_POLLY_INTO_TOOLS