Index: llvm/include/llvm/Passes/PassBuilder.h =================================================================== --- llvm/include/llvm/Passes/PassBuilder.h +++ llvm/include/llvm/Passes/PassBuilder.h @@ -477,6 +477,24 @@ OptimizerLastEPCallbacks.push_back(C); } + /// Register a callback for a default optimizer pipeline extension point + /// + /// This extension point allows adding optimizations at the start of the full + /// LTO pipeline. + void registerFullLinkTimeOptimizationEarlyEPCallback( + const std::function &C) { + FullLinkTimeOptimizationEarlyEPCallbacks.push_back(C); + } + + /// Register a callback for a default optimizer pipeline extension point + /// + /// This extension point allows adding optimizations at the end of the full + /// LTO pipeline. + void registerFullLinkTimeOptimizationLastEPCallback( + const std::function &C) { + FullLinkTimeOptimizationLastEPCallbacks.push_back(C); + } + /// Register a callback for parsing an AliasAnalysis Name to populate /// the given AAManager \p AA void registerParseAACallback( @@ -600,6 +618,10 @@ VectorizerStartEPCallbacks; SmallVector, 2> OptimizerLastEPCallbacks; + SmallVector, 2> + FullLinkTimeOptimizationEarlyEPCallbacks; + SmallVector, 2> + FullLinkTimeOptimizationLastEPCallbacks; // Module callbacks SmallVector, 2> PipelineStartEPCallbacks; Index: llvm/lib/Passes/PassBuilderPipelines.cpp =================================================================== --- llvm/lib/Passes/PassBuilderPipelines.cpp +++ llvm/lib/Passes/PassBuilderPipelines.cpp @@ -1450,6 +1450,9 @@ ModuleSummaryIndex *ExportSummary) { ModulePassManager MPM; + for (auto &C : FullLinkTimeOptimizationEarlyEPCallbacks) + C(MPM, Level); + // Convert @llvm.global.annotations to !annotation metadata. MPM.addPass(Annotation2MetadataPass()); @@ -1466,6 +1469,9 @@ // in ICP. MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); + for (auto &C : FullLinkTimeOptimizationLastEPCallbacks) + C(MPM, Level); + // Emit annotation remarks. addAnnotationRemarksPass(MPM); @@ -1547,6 +1553,9 @@ // pipeline). MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); + for (auto &C : FullLinkTimeOptimizationLastEPCallbacks) + C(MPM, Level); + // Emit annotation remarks. addAnnotationRemarksPass(MPM); @@ -1718,6 +1727,9 @@ if (PTO.MergeFunctions) MPM.addPass(MergeFunctionsPass()); + for (auto &C : FullLinkTimeOptimizationLastEPCallbacks) + C(MPM, Level); + // Emit annotation remarks. addAnnotationRemarksPass(MPM); Index: llvm/test/Other/new-pm-lto-ep-callbacks.ll =================================================================== --- /dev/null +++ llvm/test/Other/new-pm-lto-ep-callbacks.ll @@ -0,0 +1,23 @@ +; RUN: opt -disable-output -debug-pass-manager -passes-ep-full-link-time-optimization-early=no-op-function -passes='lto' 2>&1 < %s | FileCheck %s +; RUN: opt -disable-output -debug-pass-manager -passes-ep-full-link-time-optimization-last=no-op-function -passes='lto' 2>&1 < %s | FileCheck %s +; RUN: opt -disable-output -debug-pass-manager -passes-ep-full-link-time-optimization-early=no-op-function -passes='lto' 2>&1 < %s | FileCheck %s +; RUN: opt -disable-output -debug-pass-manager -passes-ep-full-link-time-optimization-last=no-op-function -passes='lto' 2>&1 < %s | FileCheck %s +; RUN: opt -disable-output -debug-pass-manager -passes-ep-full-link-time-optimization-early=no-op-function -passes='lto' 2>&1 < %s | FileCheck %s +; RUN: opt -disable-output -debug-pass-manager -passes-ep-full-link-time-optimization-last=no-op-function -passes='lto' 2>&1 < %s | FileCheck %s + +; CHECK: Running pass: NoOp + +declare void @bar() local_unnamed_addr + +define void @foo(i32 %n) local_unnamed_addr { +entry: + br label %loop +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %iv.next = add i32 %iv, 1 + tail call void @bar() + %cmp = icmp eq i32 %iv, %n + br i1 %cmp, label %exit, label %loop +exit: + ret void +} Index: llvm/tools/opt/NewPMDriver.cpp =================================================================== --- llvm/tools/opt/NewPMDriver.cpp +++ llvm/tools/opt/NewPMDriver.cpp @@ -127,6 +127,18 @@ cl::desc("A textual description of the module pass pipeline inserted at " "the OptimizerLast extension point into default pipelines"), cl::Hidden); +static cl::opt FullLinkTimeOptimizationEarlyEPPipeline( + "passes-ep-full-link-time-optimization-early", + cl::desc("A textual description of the module pass pipeline inserted at " + "the FullLinkTimeOptimizationEarly extension point into default " + "pipelines"), + cl::Hidden); +static cl::opt FullLinkTimeOptimizationLastEPPipeline( + "passes-ep-full-link-time-optimization-last", + cl::desc("A textual description of the module pass pipeline inserted at " + "the FullLinkTimeOptimizationLast extension point into default " + "pipelines"), + cl::Hidden); // Individual pipeline tuning options. extern cl::opt DisableLoopUnrolling; @@ -229,6 +241,23 @@ ExitOnError Err("Unable to parse OptimizerLastEP pipeline: "); Err(PB.parsePassPipeline(PM, OptimizerLastEPPipeline)); }); + if (tryParsePipelineText( + PB, FullLinkTimeOptimizationEarlyEPPipeline)) + PB.registerFullLinkTimeOptimizationEarlyEPCallback( + [&PB](ModulePassManager &PM, OptimizationLevel) { + ExitOnError Err( + "Unable to parse FullLinkTimeOptimizationEarlyEP pipeline: "); + Err(PB.parsePassPipeline(PM, + FullLinkTimeOptimizationEarlyEPPipeline)); + }); + if (tryParsePipelineText( + PB, FullLinkTimeOptimizationLastEPPipeline)) + PB.registerFullLinkTimeOptimizationLastEPCallback( + [&PB](ModulePassManager &PM, OptimizationLevel) { + ExitOnError Err( + "Unable to parse FullLinkTimeOptimizationLastEP pipeline: "); + Err(PB.parsePassPipeline(PM, FullLinkTimeOptimizationLastEPPipeline)); + }); } #define HANDLE_EXTENSION(Ext) \