Index: include/llvm/Passes/PassBuilder.h =================================================================== --- include/llvm/Passes/PassBuilder.h +++ include/llvm/Passes/PassBuilder.h @@ -496,6 +496,15 @@ 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. + 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( @@ -609,6 +618,8 @@ CGSCCOptimizerLateEPCallbacks; SmallVector, 2> VectorizerStartEPCallbacks; + SmallVector, 2> + OptimizerLastEPCallbacks; // Module callbacks SmallVector, 2> PipelineStartEPCallbacks; Index: lib/Passes/PassBuilder.cpp =================================================================== --- lib/Passes/PassBuilder.cpp +++ lib/Passes/PassBuilder.cpp @@ -861,6 +861,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: test/Other/new-pm-defaults.ll =================================================================== --- test/Other/new-pm-defaults.ll +++ 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: tools/opt/NewPMDriver.cpp =================================================================== --- tools/opt/NewPMDriver.cpp +++ 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, @@ -182,6 +188,13 @@ 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