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 @@ -1010,13 +1010,13 @@ DwoOS->keep(); } -static PassBuilder::OptimizationLevel mapToLevel(const CodeGenOptions &Opts) { +static OptimizationLevel mapToLevel(const CodeGenOptions &Opts) { switch (Opts.OptimizationLevel) { default: llvm_unreachable("Invalid optimization level!"); case 1: - return PassBuilder::OptimizationLevel::O1; + return OptimizationLevel::O1; case 2: switch (Opts.OptimizeSize) { @@ -1024,17 +1024,17 @@ llvm_unreachable("Invalid optimization level for size!"); case 0: - return PassBuilder::OptimizationLevel::O2; + return OptimizationLevel::O2; case 1: - return PassBuilder::OptimizationLevel::Os; + return OptimizationLevel::Os; case 2: - return PassBuilder::OptimizationLevel::Oz; + return OptimizationLevel::Oz; } case 3: - return PassBuilder::OptimizationLevel::O3; + return OptimizationLevel::O3; } } @@ -1294,7 +1294,7 @@ } else { // Map our optimization levels into one of the distinct levels used to // configure the pipeline. - PassBuilder::OptimizationLevel Level = mapToLevel(CodeGenOpts); + OptimizationLevel Level = mapToLevel(CodeGenOpts); // If we reached here with a non-empty index file name, then the index // file was empty and we are not performing ThinLTO backend compilation @@ -1317,7 +1317,7 @@ // the pipeline. if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds)) PB.registerScalarOptimizerLateEPCallback( - [](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { + [](FunctionPassManager &FPM, OptimizationLevel Level) { FPM.addPass(BoundsCheckingPass()); }); @@ -1325,8 +1325,7 @@ CodeGenOpts.SanitizeCoverageIndirectCalls || CodeGenOpts.SanitizeCoverageTraceCmp) { PB.registerOptimizerLastEPCallback( - [this](ModulePassManager &MPM, - PassBuilder::OptimizationLevel Level) { + [this](ModulePassManager &MPM, OptimizationLevel Level) { auto SancovOpts = getSancovOptsFromCGOpts(CodeGenOpts); MPM.addPass(ModuleSanitizerCoveragePass( SancovOpts, CodeGenOpts.SanitizeCoverageAllowlistFiles, @@ -1339,7 +1338,7 @@ bool Recover = CodeGenOpts.SanitizeRecover.has(SanitizerKind::Memory); PB.registerOptimizerLastEPCallback( [TrackOrigins, Recover](ModulePassManager &MPM, - PassBuilder::OptimizationLevel Level) { + OptimizationLevel Level) { MPM.addPass(MemorySanitizerPass({TrackOrigins, Recover, false})); MPM.addPass(createModuleToFunctionPassAdaptor( MemorySanitizerPass({TrackOrigins, Recover, false}))); @@ -1347,7 +1346,7 @@ } if (LangOpts.Sanitize.has(SanitizerKind::Thread)) { PB.registerOptimizerLastEPCallback( - [](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) { + [](ModulePassManager &MPM, OptimizationLevel Level) { MPM.addPass(ThreadSanitizerPass()); MPM.addPass( createModuleToFunctionPassAdaptor(ThreadSanitizerPass())); @@ -1359,8 +1358,8 @@ bool ModuleUseAfterScope = asanUseGlobalsGC(TargetTriple, CodeGenOpts); bool UseOdrIndicator = CodeGenOpts.SanitizeAddressUseOdrIndicator; PB.registerOptimizerLastEPCallback( - [Recover, UseAfterScope, ModuleUseAfterScope, UseOdrIndicator]( - ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) { + [Recover, UseAfterScope, ModuleUseAfterScope, + UseOdrIndicator](ModulePassManager &MPM, OptimizationLevel Level) { MPM.addPass( RequireAnalysisPass()); MPM.addPass(ModuleAddressSanitizerPass( @@ -1376,8 +1375,7 @@ bool Recover = CodeGenOpts.SanitizeRecover.has(SanitizerKind::HWAddress); PB.registerOptimizerLastEPCallback( - [Recover](ModulePassManager &MPM, - PassBuilder::OptimizationLevel Level) { + [Recover](ModulePassManager &MPM, OptimizationLevel Level) { MPM.addPass(HWAddressSanitizerPass( /*CompileKernel=*/false, Recover)); }); @@ -1386,8 +1384,7 @@ bool Recover = CodeGenOpts.SanitizeRecover.has(SanitizerKind::KernelHWAddress); PB.registerOptimizerLastEPCallback( - [Recover](ModulePassManager &MPM, - PassBuilder::OptimizationLevel Level) { + [Recover](ModulePassManager &MPM, OptimizationLevel Level) { MPM.addPass(HWAddressSanitizerPass( /*CompileKernel=*/true, Recover)); }); diff --git a/llvm/examples/Bye/Bye.cpp b/llvm/examples/Bye/Bye.cpp --- a/llvm/examples/Bye/Bye.cpp +++ b/llvm/examples/Bye/Bye.cpp @@ -55,9 +55,7 @@ [](PassBuilder &PB) { PB.registerVectorizerStartEPCallback( [](llvm::FunctionPassManager &PM, - llvm::PassBuilder::OptimizationLevel Level) { - PM.addPass(Bye()); - }); + llvm::OptimizationLevel Level) { PM.addPass(Bye()); }); PB.registerPipelineParsingCallback( [](StringRef Name, llvm::FunctionPassManager &PM, ArrayRef) { diff --git a/llvm/include/llvm/Passes/OptimizationLevel.h b/llvm/include/llvm/Passes/OptimizationLevel.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/Passes/OptimizationLevel.h @@ -0,0 +1,125 @@ +//===- OptimizationLevel.h -------------------------------------*- C++ -*--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASSES_OPTIMIZATIONLEVEL_H +#define LLVM_PASSES_OPTIMIZATIONLEVEL_H + +#include "llvm/Support/Error.h" + +namespace llvm { + +/// LLVM-provided high-level optimization levels. +/// +/// This enumerates the LLVM-provided high-level optimization levels. Each +/// level has a specific goal and rationale. +class OptimizationLevel final { + unsigned SpeedLevel = 2; + unsigned SizeLevel = 0; + OptimizationLevel(unsigned SpeedLevel, unsigned SizeLevel) + : SpeedLevel(SpeedLevel), SizeLevel(SizeLevel) { + // Check that only valid combinations are passed. + assert(SpeedLevel <= 3 && + "Optimization level for speed should be 0, 1, 2, or 3"); + assert(SizeLevel <= 2 && + "Optimization level for size should be 0, 1, or 2"); + assert((SizeLevel == 0 || SpeedLevel == 2) && + "Optimize for size should be encoded with speedup level == 2"); + } + +public: + OptimizationLevel() = default; + /// Disable as many optimizations as possible. This doesn't completely + /// disable the optimizer in all cases, for example always_inline functions + /// can be required to be inlined for correctness. + static const OptimizationLevel O0; + + /// Optimize quickly without destroying debuggability. + /// + /// This level is tuned to produce a result from the optimizer as quickly + /// as possible and to avoid destroying debuggability. This tends to result + /// in a very good development mode where the compiled code will be + /// immediately executed as part of testing. As a consequence, where + /// possible, we would like to produce efficient-to-execute code, but not + /// if it significantly slows down compilation or would prevent even basic + /// debugging of the resulting binary. + /// + /// As an example, complex loop transformations such as versioning, + /// vectorization, or fusion don't make sense here due to the degree to + /// which the executed code differs from the source code, and the compile + /// time cost. + static const OptimizationLevel O1; + /// Optimize for fast execution as much as possible without triggering + /// significant incremental compile time or code size growth. + /// + /// The key idea is that optimizations at this level should "pay for + /// themselves". So if an optimization increases compile time by 5% or + /// increases code size by 5% for a particular benchmark, that benchmark + /// should also be one which sees a 5% runtime improvement. If the compile + /// time or code size penalties happen on average across a diverse range of + /// LLVM users' benchmarks, then the improvements should as well. + /// + /// And no matter what, the compile time needs to not grow superlinearly + /// with the size of input to LLVM so that users can control the runtime of + /// the optimizer in this mode. + /// + /// This is expected to be a good default optimization level for the vast + /// majority of users. + static const OptimizationLevel O2; + /// Optimize for fast execution as much as possible. + /// + /// This mode is significantly more aggressive in trading off compile time + /// and code size to get execution time improvements. The core idea is that + /// this mode should include any optimization that helps execution time on + /// balance across a diverse collection of benchmarks, even if it increases + /// code size or compile time for some benchmarks without corresponding + /// improvements to execution time. + /// + /// Despite being willing to trade more compile time off to get improved + /// execution time, this mode still tries to avoid superlinear growth in + /// order to make even significantly slower compile times at least scale + /// reasonably. This does not preclude very substantial constant factor + /// costs though. + static const OptimizationLevel O3; + /// Similar to \c O2 but tries to optimize for small code size instead of + /// fast execution without triggering significant incremental execution + /// time slowdowns. + /// + /// The logic here is exactly the same as \c O2, but with code size and + /// execution time metrics swapped. + /// + /// A consequence of the different core goal is that this should in general + /// produce substantially smaller executables that still run in + /// a reasonable amount of time. + static const OptimizationLevel Os; + /// A very specialized mode that will optimize for code size at any and all + /// costs. + /// + /// This is useful primarily when there are absolute size limitations and + /// any effort taken to reduce the size is worth it regardless of the + /// execution time impact. You should expect this level to produce rather + /// slow, but very small, code. + static const OptimizationLevel Oz; + + bool isOptimizingForSpeed() const { return SizeLevel == 0 && SpeedLevel > 0; } + + bool isOptimizingForSize() const { return SizeLevel > 0; } + + bool operator==(const OptimizationLevel &Other) const { + return SizeLevel == Other.SizeLevel && SpeedLevel == Other.SpeedLevel; + } + bool operator!=(const OptimizationLevel &Other) const { + return SizeLevel != Other.SizeLevel || SpeedLevel != Other.SpeedLevel; + } + + unsigned getSpeedupLevel() const { return SpeedLevel; } + + unsigned getSizeLevel() const { return SizeLevel; } +}; +} // namespace llvm + +#endif // LLVM_PASSES_OPTIMIZATIONLEVEL_H diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h --- a/llvm/include/llvm/Passes/PassBuilder.h +++ b/llvm/include/llvm/Passes/PassBuilder.h @@ -18,6 +18,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/Analysis/CGSCCPassManager.h" #include "llvm/IR/PassManager.h" +#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/Error.h" #include "llvm/Transforms/IPO/Inliner.h" #include "llvm/Transforms/Instrumentation.h" @@ -150,116 +151,6 @@ PostLink }; - /// LLVM-provided high-level optimization levels. - /// - /// This enumerates the LLVM-provided high-level optimization levels. Each - /// level has a specific goal and rationale. - class OptimizationLevel final { - unsigned SpeedLevel = 2; - unsigned SizeLevel = 0; - OptimizationLevel(unsigned SpeedLevel, unsigned SizeLevel) - : SpeedLevel(SpeedLevel), SizeLevel(SizeLevel) { - // Check that only valid combinations are passed. - assert(SpeedLevel <= 3 && - "Optimization level for speed should be 0, 1, 2, or 3"); - assert(SizeLevel <= 2 && - "Optimization level for size should be 0, 1, or 2"); - assert((SizeLevel == 0 || SpeedLevel == 2) && - "Optimize for size should be encoded with speedup level == 2"); - } - - public: - OptimizationLevel() = default; - /// Disable as many optimizations as possible. This doesn't completely - /// disable the optimizer in all cases, for example always_inline functions - /// can be required to be inlined for correctness. - static const OptimizationLevel O0; - - /// Optimize quickly without destroying debuggability. - /// - /// This level is tuned to produce a result from the optimizer as quickly - /// as possible and to avoid destroying debuggability. This tends to result - /// in a very good development mode where the compiled code will be - /// immediately executed as part of testing. As a consequence, where - /// possible, we would like to produce efficient-to-execute code, but not - /// if it significantly slows down compilation or would prevent even basic - /// debugging of the resulting binary. - /// - /// As an example, complex loop transformations such as versioning, - /// vectorization, or fusion don't make sense here due to the degree to - /// which the executed code differs from the source code, and the compile - /// time cost. - static const OptimizationLevel O1; - /// Optimize for fast execution as much as possible without triggering - /// significant incremental compile time or code size growth. - /// - /// The key idea is that optimizations at this level should "pay for - /// themselves". So if an optimization increases compile time by 5% or - /// increases code size by 5% for a particular benchmark, that benchmark - /// should also be one which sees a 5% runtime improvement. If the compile - /// time or code size penalties happen on average across a diverse range of - /// LLVM users' benchmarks, then the improvements should as well. - /// - /// And no matter what, the compile time needs to not grow superlinearly - /// with the size of input to LLVM so that users can control the runtime of - /// the optimizer in this mode. - /// - /// This is expected to be a good default optimization level for the vast - /// majority of users. - static const OptimizationLevel O2; - /// Optimize for fast execution as much as possible. - /// - /// This mode is significantly more aggressive in trading off compile time - /// and code size to get execution time improvements. The core idea is that - /// this mode should include any optimization that helps execution time on - /// balance across a diverse collection of benchmarks, even if it increases - /// code size or compile time for some benchmarks without corresponding - /// improvements to execution time. - /// - /// Despite being willing to trade more compile time off to get improved - /// execution time, this mode still tries to avoid superlinear growth in - /// order to make even significantly slower compile times at least scale - /// reasonably. This does not preclude very substantial constant factor - /// costs though. - static const OptimizationLevel O3; - /// Similar to \c O2 but tries to optimize for small code size instead of - /// fast execution without triggering significant incremental execution - /// time slowdowns. - /// - /// The logic here is exactly the same as \c O2, but with code size and - /// execution time metrics swapped. - /// - /// A consequence of the different core goal is that this should in general - /// produce substantially smaller executables that still run in - /// a reasonable amount of time. - static const OptimizationLevel Os; - /// A very specialized mode that will optimize for code size at any and all - /// costs. - /// - /// This is useful primarily when there are absolute size limitations and - /// any effort taken to reduce the size is worth it regardless of the - /// execution time impact. You should expect this level to produce rather - /// slow, but very small, code. - static const OptimizationLevel Oz; - - bool isOptimizingForSpeed() const { - return SizeLevel == 0 && SpeedLevel > 0; - } - - bool isOptimizingForSize() const { return SizeLevel > 0; } - - bool operator==(const OptimizationLevel &Other) const { - return SizeLevel == Other.SizeLevel && SpeedLevel == Other.SpeedLevel; - } - bool operator!=(const OptimizationLevel &Other) const { - return SizeLevel != Other.SizeLevel || SpeedLevel != Other.SpeedLevel; - } - - unsigned getSpeedupLevel() const { return SpeedLevel; } - - unsigned getSizeLevel() const { return SizeLevel; } - }; - explicit PassBuilder(bool DebugLogging = false, TargetMachine *TM = nullptr, PipelineTuningOptions PTO = PipelineTuningOptions(), Optional PGOOpt = None, @@ -678,6 +569,8 @@ } private: + void registerTargetMachineEPCallbacks(OptimizationLevel Level); + // O1 pass pipeline FunctionPassManager buildO1FunctionSimplificationPipeline(OptimizationLevel Level, diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h --- a/llvm/include/llvm/Target/TargetMachine.h +++ b/llvm/include/llvm/Target/TargetMachine.h @@ -17,6 +17,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/IR/DataLayout.h" #include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/CodeGen.h" #include "llvm/Target/TargetOptions.h" #include @@ -304,6 +305,7 @@ /// Allow the target to modify the pass pipeline with New Pass Manager /// (similar to adjustPassManager for Legacy Pass manager). virtual void registerPassBuilderCallbacks(PassBuilder &, + OptimizationLevel Level, bool DebugPassManager) {} /// Add passes to the specified pass manager to get the specified file diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -250,22 +250,22 @@ ModulePassManager MPM(Conf.DebugPassManager); // FIXME (davide): verify the input. - PassBuilder::OptimizationLevel OL; + OptimizationLevel OL; switch (OptLevel) { default: llvm_unreachable("Invalid optimization level"); case 0: - OL = PassBuilder::OptimizationLevel::O0; + OL = OptimizationLevel::O0; break; case 1: - OL = PassBuilder::OptimizationLevel::O1; + OL = OptimizationLevel::O1; break; case 2: - OL = PassBuilder::OptimizationLevel::O2; + OL = OptimizationLevel::O2; break; case 3: - OL = PassBuilder::OptimizationLevel::O3; + OL = OptimizationLevel::O3; break; } diff --git a/llvm/lib/Passes/CMakeLists.txt b/llvm/lib/Passes/CMakeLists.txt --- a/llvm/lib/Passes/CMakeLists.txt +++ b/llvm/lib/Passes/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_component_library(LLVMPasses + OptimizationLevel.cpp PassBuilder.cpp PassPlugin.cpp StandardInstrumentations.cpp diff --git a/llvm/lib/Passes/OptimizationLevel.cpp b/llvm/lib/Passes/OptimizationLevel.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Passes/OptimizationLevel.cpp @@ -0,0 +1,30 @@ +//===- OptimizationLevel.cpp -----------------------------------*- C++ -*--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/Passes/OptimizationLevel.h" + +using namespace llvm; + +const OptimizationLevel OptimizationLevel::O0 = { + /*SpeedLevel*/ 0, + /*SizeLevel*/ 0}; +const OptimizationLevel OptimizationLevel::O1 = { + /*SpeedLevel*/ 1, + /*SizeLevel*/ 0}; +const OptimizationLevel OptimizationLevel::O2 = { + /*SpeedLevel*/ 2, + /*SizeLevel*/ 0}; +const OptimizationLevel OptimizationLevel::O3 = { + /*SpeedLevel*/ 3, + /*SizeLevel*/ 0}; +const OptimizationLevel OptimizationLevel::Os = { + /*SpeedLevel*/ 2, + /*SizeLevel*/ 1}; +const OptimizationLevel OptimizationLevel::Oz = { + /*SpeedLevel*/ 2, + /*SizeLevel*/ 2}; diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -316,25 +316,6 @@ extern cl::opt EnableMatrix; -const PassBuilder::OptimizationLevel PassBuilder::OptimizationLevel::O0 = { - /*SpeedLevel*/ 0, - /*SizeLevel*/ 0}; -const PassBuilder::OptimizationLevel PassBuilder::OptimizationLevel::O1 = { - /*SpeedLevel*/ 1, - /*SizeLevel*/ 0}; -const PassBuilder::OptimizationLevel PassBuilder::OptimizationLevel::O2 = { - /*SpeedLevel*/ 2, - /*SizeLevel*/ 0}; -const PassBuilder::OptimizationLevel PassBuilder::OptimizationLevel::O3 = { - /*SpeedLevel*/ 3, - /*SizeLevel*/ 0}; -const PassBuilder::OptimizationLevel PassBuilder::OptimizationLevel::Os = { - /*SpeedLevel*/ 2, - /*SizeLevel*/ 1}; -const PassBuilder::OptimizationLevel PassBuilder::OptimizationLevel::Oz = { - /*SpeedLevel*/ 2, - /*SizeLevel*/ 2}; - namespace { // The following passes/analyses have custom names, otherwise their name will @@ -435,12 +416,10 @@ PipelineTuningOptions PTO, Optional PGOOpt, PassInstrumentationCallbacks *PIC) : DebugLogging(DebugLogging), TM(TM), PTO(PTO), PGOOpt(PGOOpt), PIC(PIC) { - if (TM) - TM->registerPassBuilderCallbacks(*this, DebugLogging); } -void PassBuilder::invokePeepholeEPCallbacks( - FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { +void PassBuilder::invokePeepholeEPCallbacks(FunctionPassManager &FPM, + OptimizationLevel Level) { for (auto &C : PeepholeEPCallbacks) C(FPM, Level); } @@ -481,6 +460,11 @@ C(LAM); } +void PassBuilder::registerTargetMachineEPCallbacks(OptimizationLevel Level) { + if (TM) + TM->registerPassBuilderCallbacks(*this, Level, DebugLogging); +} + // TODO: Investigate the cost/benefit of tail call elimination on debugging. FunctionPassManager PassBuilder::buildO1FunctionSimplificationPipeline(OptimizationLevel Level, @@ -793,9 +777,8 @@ } void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM, - PassBuilder::OptimizationLevel Level, - bool RunProfileGen, bool IsCS, - std::string ProfileFile, + OptimizationLevel Level, bool RunProfileGen, + bool IsCS, std::string ProfileFile, std::string ProfileRemappingFile) { assert(Level != OptimizationLevel::O0 && "Not expecting O0 here!"); // Generally running simplification passes and the inliner with an high @@ -886,8 +869,7 @@ MPM.addPass(InstrProfiling(Options, IsCS)); } -static InlineParams -getInlineParamsFromOptLevel(PassBuilder::OptimizationLevel Level) { +static InlineParams getInlineParamsFromOptLevel(OptimizationLevel Level) { return getInlineParams(Level.getSpeedupLevel(), Level.getSizeLevel()); } @@ -1311,6 +1293,8 @@ assert(Level != OptimizationLevel::O0 && "Must request optimizations for the default pipeline!"); + registerTargetMachineEPCallbacks(Level); + ModulePassManager MPM(DebugLogging); // Force any function attributes we want the rest of the pipeline to observe. @@ -1337,6 +1321,8 @@ assert(Level != OptimizationLevel::O0 && "Must request optimizations for the default pipeline!"); + registerTargetMachineEPCallbacks(Level); + ModulePassManager MPM(DebugLogging); // Force any function attributes we want the rest of the pipeline to observe. @@ -1378,6 +1364,8 @@ ModulePassManager PassBuilder::buildThinLTODefaultPipeline( OptimizationLevel Level, const ModuleSummaryIndex *ImportSummary) { + registerTargetMachineEPCallbacks(Level); + ModulePassManager MPM(DebugLogging); if (ImportSummary) { @@ -1427,6 +1415,8 @@ ModulePassManager PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, ModuleSummaryIndex *ExportSummary) { + registerTargetMachineEPCallbacks(Level); + ModulePassManager MPM(DebugLogging); if (Level == OptimizationLevel::O0) { @@ -2216,6 +2206,8 @@ .Case("Os", OptimizationLevel::Os) .Case("Oz", OptimizationLevel::Oz); if (L == OptimizationLevel::O0) { + registerTargetMachineEPCallbacks(L); + // Add instrumentation PGO passes -- at O0 we can still do PGO. if (PGOOpt && Matches[1] != "thinlto" && (PGOOpt->Action == PGOOptions::IRInstr || diff --git a/llvm/lib/Target/BPF/BPFTargetMachine.h b/llvm/lib/Target/BPF/BPFTargetMachine.h --- a/llvm/lib/Target/BPF/BPFTargetMachine.h +++ b/llvm/lib/Target/BPF/BPFTargetMachine.h @@ -39,7 +39,7 @@ } void adjustPassManager(PassManagerBuilder &) override; - void registerPassBuilderCallbacks(PassBuilder &PB, + void registerPassBuilderCallbacks(PassBuilder &PB, OptimizationLevel Level, bool DebugPassManager) override; }; } diff --git a/llvm/lib/Target/BPF/BPFTargetMachine.cpp b/llvm/lib/Target/BPF/BPFTargetMachine.cpp --- a/llvm/lib/Target/BPF/BPFTargetMachine.cpp +++ b/llvm/lib/Target/BPF/BPFTargetMachine.cpp @@ -124,6 +124,7 @@ } void BPFTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB, + OptimizationLevel Level, bool DebugPassManager) { PB.registerPipelineStartEPCallback([=](ModulePassManager &MPM) { FunctionPassManager FPM(DebugPassManager); @@ -132,7 +133,7 @@ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); }); PB.registerPeepholeEPCallback([=](FunctionPassManager &FPM, - PassBuilder::OptimizationLevel Level) { + OptimizationLevel Level) { FPM.addPass(SimplifyCFGPass(SimplifyCFGOptions().hoistCommonInsts(true))); }); } diff --git a/llvm/lib/Target/Hexagon/HexagonTargetMachine.h b/llvm/lib/Target/Hexagon/HexagonTargetMachine.h --- a/llvm/lib/Target/Hexagon/HexagonTargetMachine.h +++ b/llvm/lib/Target/Hexagon/HexagonTargetMachine.h @@ -37,7 +37,7 @@ static unsigned getModuleMatchQuality(const Module &M); void adjustPassManager(PassManagerBuilder &PMB) override; - void registerPassBuilderCallbacks(PassBuilder &PB, + void registerPassBuilderCallbacks(PassBuilder &PB, OptimizationLevel Level, bool DebugPassManager) override; TargetPassConfig *createPassConfig(PassManagerBase &PM) override; TargetTransformInfo getTargetTransformInfo(const Function &F) override; diff --git a/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp b/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp --- a/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp +++ b/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp @@ -275,9 +275,10 @@ } void HexagonTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB, + OptimizationLevel Level, bool DebugPassManager) { PB.registerOptimizerLastEPCallback( - [=](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) { + [=](ModulePassManager &MPM, OptimizationLevel Level) { LoopPassManager LPM(DebugPassManager); FunctionPassManager FPM(DebugPassManager); LPM.addPass(HexagonVectorLoopCarriedReusePass()); diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp --- a/llvm/tools/opt/NewPMDriver.cpp +++ b/llvm/tools/opt/NewPMDriver.cpp @@ -143,39 +143,39 @@ static void registerEPCallbacks(PassBuilder &PB) { if (tryParsePipelineText(PB, PeepholeEPPipeline)) PB.registerPeepholeEPCallback( - [&PB](FunctionPassManager &PM, PassBuilder::OptimizationLevel Level) { + [&PB](FunctionPassManager &PM, OptimizationLevel Level) { ExitOnError Err("Unable to parse PeepholeEP pipeline: "); Err(PB.parsePassPipeline(PM, PeepholeEPPipeline)); }); if (tryParsePipelineText(PB, LateLoopOptimizationsEPPipeline)) PB.registerLateLoopOptimizationsEPCallback( - [&PB](LoopPassManager &PM, PassBuilder::OptimizationLevel Level) { + [&PB](LoopPassManager &PM, OptimizationLevel Level) { ExitOnError Err("Unable to parse LateLoopOptimizationsEP pipeline: "); Err(PB.parsePassPipeline(PM, LateLoopOptimizationsEPPipeline)); }); if (tryParsePipelineText(PB, LoopOptimizerEndEPPipeline)) PB.registerLoopOptimizerEndEPCallback( - [&PB](LoopPassManager &PM, PassBuilder::OptimizationLevel Level) { + [&PB](LoopPassManager &PM, OptimizationLevel Level) { ExitOnError Err("Unable to parse LoopOptimizerEndEP pipeline: "); Err(PB.parsePassPipeline(PM, LoopOptimizerEndEPPipeline)); }); if (tryParsePipelineText(PB, ScalarOptimizerLateEPPipeline)) PB.registerScalarOptimizerLateEPCallback( - [&PB](FunctionPassManager &PM, PassBuilder::OptimizationLevel Level) { + [&PB](FunctionPassManager &PM, OptimizationLevel Level) { ExitOnError Err("Unable to parse ScalarOptimizerLateEP pipeline: "); Err(PB.parsePassPipeline(PM, ScalarOptimizerLateEPPipeline)); }); if (tryParsePipelineText(PB, CGSCCOptimizerLateEPPipeline)) PB.registerCGSCCOptimizerLateEPCallback( - [&PB](CGSCCPassManager &PM, PassBuilder::OptimizationLevel Level) { + [&PB](CGSCCPassManager &PM, OptimizationLevel Level) { ExitOnError Err("Unable to parse CGSCCOptimizerLateEP pipeline: "); Err(PB.parsePassPipeline(PM, CGSCCOptimizerLateEPPipeline)); }); if (tryParsePipelineText(PB, VectorizerStartEPPipeline)) PB.registerVectorizerStartEPCallback( - [&PB](FunctionPassManager &PM, PassBuilder::OptimizationLevel Level) { + [&PB](FunctionPassManager &PM, OptimizationLevel Level) { ExitOnError Err("Unable to parse VectorizerStartEP pipeline: "); Err(PB.parsePassPipeline(PM, VectorizerStartEPPipeline)); }); @@ -186,7 +186,7 @@ }); if (tryParsePipelineText(PB, OptimizerLastEPPipeline)) PB.registerOptimizerLastEPCallback( - [&PB](ModulePassManager &PM, PassBuilder::OptimizationLevel) { + [&PB](ModulePassManager &PM, OptimizationLevel) { ExitOnError Err("Unable to parse OptimizerLastEP pipeline: "); Err(PB.parsePassPipeline(PM, OptimizerLastEPPipeline)); }); diff --git a/llvm/utils/gn/secondary/llvm/lib/Passes/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Passes/BUILD.gn --- a/llvm/utils/gn/secondary/llvm/lib/Passes/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Passes/BUILD.gn @@ -18,6 +18,7 @@ "//llvm/lib/Transforms/Vectorize", ] sources = [ + "OptimizationLevel.cpp", "PassBuilder.cpp", "PassPlugin.cpp", "StandardInstrumentations.cpp", diff --git a/polly/lib/Support/RegisterPasses.cpp b/polly/lib/Support/RegisterPasses.cpp --- a/polly/lib/Support/RegisterPasses.cpp +++ b/polly/lib/Support/RegisterPasses.cpp @@ -470,7 +470,7 @@ } static void buildDefaultPollyPipeline(FunctionPassManager &PM, - PassBuilder::OptimizationLevel Level) { + OptimizationLevel Level) { if (!polly::shouldEnablePolly()) return; PassBuilder PB;