Index: llvm/include/llvm/Passes/PassBuilder.h =================================================================== --- llvm/include/llvm/Passes/PassBuilder.h +++ llvm/include/llvm/Passes/PassBuilder.h @@ -468,6 +468,15 @@ PipelineEarlySimplificationEPCallbacks.push_back(C); } + /// Register a callback for a default optimizer pipeline extension point + /// + /// This extension point allows adding optimizations before the function + /// optimization pipeline. + void registerOptimizerEarlyEPCallback( + const std::function &C) { + OptimizerEarlyEPCallbacks.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 @@ -616,13 +625,15 @@ CGSCCOptimizerLateEPCallbacks; SmallVector, 2> VectorizerStartEPCallbacks; + // Module callbacks + SmallVector, 2> + OptimizerEarlyEPCallbacks; SmallVector, 2> OptimizerLastEPCallbacks; SmallVector, 2> FullLinkTimeOptimizationEarlyEPCallbacks; SmallVector, 2> FullLinkTimeOptimizationLastEPCallbacks; - // Module callbacks SmallVector, 2> PipelineStartEPCallbacks; SmallVector, 2> Index: llvm/lib/Passes/PassBuilderPipelines.cpp =================================================================== --- llvm/lib/Passes/PassBuilderPipelines.cpp +++ llvm/lib/Passes/PassBuilderPipelines.cpp @@ -1159,6 +1159,9 @@ PGOOpt->ProfileRemappingFile); } + for (auto &C : OptimizerEarlyEPCallbacks) + C(MPM, Level); + // Re-compute GlobalsAA here prior to function passes. This is particularly // useful as the above will have inlined, DCE'ed, and function-attr // propagated everything. We should at this point have a reasonably minimal @@ -1808,6 +1811,10 @@ if (!FPM.isEmpty()) MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } + + for (auto &C : OptimizerEarlyEPCallbacks) + C(MPM, Level); + if (!VectorizerStartEPCallbacks.empty()) { FunctionPassManager FPM; for (auto &C : VectorizerStartEPCallbacks) Index: llvm/test/Other/new-pm-O0-ep-callbacks.ll =================================================================== --- llvm/test/Other/new-pm-O0-ep-callbacks.ll +++ llvm/test/Other/new-pm-O0-ep-callbacks.ll @@ -5,6 +5,7 @@ ; RUN: opt -disable-output -debug-pass-manager -passes-ep-vectorizer-start=no-op-function -passes='default' 2>&1 < %s | FileCheck %s ; RUN: opt -disable-output -debug-pass-manager -passes-ep-pipeline-start=no-op-module -passes='default' 2>&1 < %s | FileCheck %s ; RUN: opt -disable-output -debug-pass-manager -passes-ep-pipeline-early-simplification=no-op-module -passes='default' 2>&1 < %s | FileCheck %s +; RUN: opt -disable-output -debug-pass-manager -passes-ep-optimizer-early=no-op-module -passes='default' 2>&1 < %s | FileCheck %s ; RUN: opt -disable-output -debug-pass-manager -passes-ep-optimizer-last=no-op-module -passes='default' 2>&1 < %s | FileCheck %s ; RUN: opt -disable-output -debug-pass-manager -passes-ep-full-link-time-optimization-early=no-op-module -passes='lto' 2>&1 < %s | FileCheck %s ; RUN: opt -disable-output -debug-pass-manager -passes-ep-full-link-time-optimization-last=no-op-module -passes='lto' 2>&1 < %s | FileCheck %s Index: llvm/test/Other/new-pm-defaults.ll =================================================================== --- llvm/test/Other/new-pm-defaults.ll +++ llvm/test/Other/new-pm-defaults.ll @@ -63,6 +63,10 @@ ; RUN: -passes='lto-pre-link' -S %s 2>&1 \ ; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-LTO,CHECK-O3,%llvmcheckext,CHECK-EP-PIPELINE-START,CHECK-O23SZ ; RUN: opt -disable-verify -verify-cfg-preserved=1 -eagerly-invalidate-analyses=0 -debug-pass-manager \ +; RUN: -passes-ep-optimizer-early='no-op-module' \ +; RUN: -passes='default' -S %s 2>&1 \ +; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,%llvmcheckext,CHECK-EP-OPTIMIZER-EARLY,CHECK-O23SZ +; RUN: opt -disable-verify -verify-cfg-preserved=1 -eagerly-invalidate-analyses=0 -debug-pass-manager \ ; RUN: -passes-ep-optimizer-last='no-op-module' \ ; RUN: -passes='default' -S %s 2>&1 \ ; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,%llvmcheckext,CHECK-EP-OPTIMIZER-LAST,CHECK-O23SZ @@ -217,6 +221,7 @@ ; CHECK-DEFAULT-NEXT: Running pass: EliminateAvailableExternallyPass ; CHECK-LTO-NOT: Running pass: EliminateAvailableExternallyPass ; CHECK-O-NEXT: Running pass: ReversePostOrderFunctionAttrsPass +; CHECK-EP-OPTIMIZER-EARLY: Running pass: NoOpModulePass ; CHECK-O-NEXT: Running pass: RecomputeGlobalsAAPass ; CHECK-O-NEXT: Running pass: Float2IntPass ; CHECK-O-NEXT: Running pass: LowerConstantIntrinsicsPass on foo Index: llvm/tools/opt/NewPMDriver.cpp =================================================================== --- llvm/tools/opt/NewPMDriver.cpp +++ llvm/tools/opt/NewPMDriver.cpp @@ -118,6 +118,11 @@ cl::desc("A textual description of the module pass pipeline inserted at " "the EarlySimplification extension point into default pipelines"), cl::Hidden); +static cl::opt OptimizerEarlyEPPipeline( + "passes-ep-optimizer-early", + cl::desc("A textual description of the module pass pipeline inserted at " + "the OptimizerEarly extension point into default pipelines"), + cl::Hidden); static cl::opt OptimizerLastEPPipeline( "passes-ep-optimizer-last", cl::desc("A textual description of the module pass pipeline inserted at " @@ -231,6 +236,12 @@ ExitOnError Err("Unable to parse EarlySimplification pipeline: "); Err(PB.parsePassPipeline(PM, PipelineEarlySimplificationEPPipeline)); }); + if (tryParsePipelineText(PB, OptimizerEarlyEPPipeline)) + PB.registerOptimizerEarlyEPCallback( + [&PB](ModulePassManager &PM, OptimizationLevel) { + ExitOnError Err("Unable to parse OptimizerEarlyEP pipeline: "); + Err(PB.parsePassPipeline(PM, OptimizerEarlyEPPipeline)); + }); if (tryParsePipelineText(PB, OptimizerLastEPPipeline)) PB.registerOptimizerLastEPCallback( [&PB](ModulePassManager &PM, OptimizationLevel) {