Skip to content

Commit 7a797b2

Browse files
tarindujmtrofin
authored andcommitted
Take OptimizationLevel class out of Pass Builder
Pulled out the OptimizationLevel class from PassBuilder in order to be able to access it from within the PassManager and avoid include conflicts. Reviewed By: mtrofin Differential Revision: https://reviews.llvm.org/D107025
1 parent 3c7d2f1 commit 7a797b2

File tree

15 files changed

+203
-190
lines changed

15 files changed

+203
-190
lines changed

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,42 +1069,42 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
10691069
DwoOS->keep();
10701070
}
10711071

1072-
static PassBuilder::OptimizationLevel mapToLevel(const CodeGenOptions &Opts) {
1072+
static OptimizationLevel mapToLevel(const CodeGenOptions &Opts) {
10731073
switch (Opts.OptimizationLevel) {
10741074
default:
10751075
llvm_unreachable("Invalid optimization level!");
10761076

10771077
case 0:
1078-
return PassBuilder::OptimizationLevel::O0;
1078+
return OptimizationLevel::O0;
10791079

10801080
case 1:
1081-
return PassBuilder::OptimizationLevel::O1;
1081+
return OptimizationLevel::O1;
10821082

10831083
case 2:
10841084
switch (Opts.OptimizeSize) {
10851085
default:
10861086
llvm_unreachable("Invalid optimization level for size!");
10871087

10881088
case 0:
1089-
return PassBuilder::OptimizationLevel::O2;
1089+
return OptimizationLevel::O2;
10901090

10911091
case 1:
1092-
return PassBuilder::OptimizationLevel::Os;
1092+
return OptimizationLevel::Os;
10931093

10941094
case 2:
1095-
return PassBuilder::OptimizationLevel::Oz;
1095+
return OptimizationLevel::Oz;
10961096
}
10971097

10981098
case 3:
1099-
return PassBuilder::OptimizationLevel::O3;
1099+
return OptimizationLevel::O3;
11001100
}
11011101
}
11021102

11031103
static void addSanitizers(const Triple &TargetTriple,
11041104
const CodeGenOptions &CodeGenOpts,
11051105
const LangOptions &LangOpts, PassBuilder &PB) {
11061106
PB.registerOptimizerLastEPCallback([&](ModulePassManager &MPM,
1107-
PassBuilder::OptimizationLevel Level) {
1107+
OptimizationLevel Level) {
11081108
if (CodeGenOpts.hasSanitizeCoverage()) {
11091109
auto SancovOpts = getSancovOptsFromCGOpts(CodeGenOpts);
11101110
MPM.addPass(ModuleSanitizerCoveragePass(
@@ -1122,7 +1122,7 @@ static void addSanitizers(const Triple &TargetTriple,
11221122
FunctionPassManager FPM;
11231123
FPM.addPass(
11241124
MemorySanitizerPass({TrackOrigins, Recover, CompileKernel}));
1125-
if (Level != PassBuilder::OptimizationLevel::O0) {
1125+
if (Level != OptimizationLevel::O0) {
11261126
// MemorySanitizer inserts complex instrumentation that mostly
11271127
// follows the logic of the original code, but operates on
11281128
// "shadow" values. It can benefit from re-running some
@@ -1325,26 +1325,26 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
13251325
if (!CodeGenOpts.DisableLLVMPasses) {
13261326
// Map our optimization levels into one of the distinct levels used to
13271327
// configure the pipeline.
1328-
PassBuilder::OptimizationLevel Level = mapToLevel(CodeGenOpts);
1328+
OptimizationLevel Level = mapToLevel(CodeGenOpts);
13291329

13301330
bool IsThinLTO = CodeGenOpts.PrepareForThinLTO;
13311331
bool IsLTO = CodeGenOpts.PrepareForLTO;
13321332

13331333
if (LangOpts.ObjCAutoRefCount) {
13341334
PB.registerPipelineStartEPCallback(
1335-
[](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
1336-
if (Level != PassBuilder::OptimizationLevel::O0)
1335+
[](ModulePassManager &MPM, OptimizationLevel Level) {
1336+
if (Level != OptimizationLevel::O0)
13371337
MPM.addPass(
13381338
createModuleToFunctionPassAdaptor(ObjCARCExpandPass()));
13391339
});
13401340
PB.registerPipelineEarlySimplificationEPCallback(
1341-
[](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
1342-
if (Level != PassBuilder::OptimizationLevel::O0)
1341+
[](ModulePassManager &MPM, OptimizationLevel Level) {
1342+
if (Level != OptimizationLevel::O0)
13431343
MPM.addPass(ObjCARCAPElimPass());
13441344
});
13451345
PB.registerScalarOptimizerLateEPCallback(
1346-
[](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
1347-
if (Level != PassBuilder::OptimizationLevel::O0)
1346+
[](FunctionPassManager &FPM, OptimizationLevel Level) {
1347+
if (Level != OptimizationLevel::O0)
13481348
FPM.addPass(ObjCARCOptPass());
13491349
});
13501350
}
@@ -1357,7 +1357,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
13571357
// vtables so that codegen doesn't complain.
13581358
if (IsThinLTOPostLink)
13591359
PB.registerPipelineStartEPCallback(
1360-
[](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
1360+
[](ModulePassManager &MPM, OptimizationLevel Level) {
13611361
MPM.addPass(LowerTypeTestsPass(/*ExportSummary=*/nullptr,
13621362
/*ImportSummary=*/nullptr,
13631363
/*DropTypeTests=*/true));
@@ -1368,12 +1368,12 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
13681368
CodeGenOpts.InstrumentFunctionsAfterInlining ||
13691369
CodeGenOpts.InstrumentForProfiling) {
13701370
PB.registerPipelineStartEPCallback(
1371-
[](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
1371+
[](ModulePassManager &MPM, OptimizationLevel Level) {
13721372
MPM.addPass(createModuleToFunctionPassAdaptor(
13731373
EntryExitInstrumenterPass(/*PostInlining=*/false)));
13741374
});
13751375
PB.registerOptimizerLastEPCallback(
1376-
[](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
1376+
[](ModulePassManager &MPM, OptimizationLevel Level) {
13771377
MPM.addPass(createModuleToFunctionPassAdaptor(
13781378
EntryExitInstrumenterPass(/*PostInlining=*/true)));
13791379
});
@@ -1383,7 +1383,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
13831383
// of the pipeline.
13841384
if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds))
13851385
PB.registerScalarOptimizerLateEPCallback(
1386-
[](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
1386+
[](FunctionPassManager &FPM, OptimizationLevel Level) {
13871387
FPM.addPass(BoundsCheckingPass());
13881388
});
13891389

@@ -1394,15 +1394,13 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
13941394

13951395
if (Optional<GCOVOptions> Options = getGCOVOptions(CodeGenOpts, LangOpts))
13961396
PB.registerPipelineStartEPCallback(
1397-
[Options](ModulePassManager &MPM,
1398-
PassBuilder::OptimizationLevel Level) {
1397+
[Options](ModulePassManager &MPM, OptimizationLevel Level) {
13991398
MPM.addPass(GCOVProfilerPass(*Options));
14001399
});
14011400
if (Optional<InstrProfOptions> Options =
14021401
getInstrProfOptions(CodeGenOpts, LangOpts))
14031402
PB.registerPipelineStartEPCallback(
1404-
[Options](ModulePassManager &MPM,
1405-
PassBuilder::OptimizationLevel Level) {
1403+
[Options](ModulePassManager &MPM, OptimizationLevel Level) {
14061404
MPM.addPass(InstrProfiling(*Options, false));
14071405
});
14081406

llvm/examples/Bye/Bye.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ llvm::PassPluginLibraryInfo getByePluginInfo() {
5555
return {LLVM_PLUGIN_API_VERSION, "Bye", LLVM_VERSION_STRING,
5656
[](PassBuilder &PB) {
5757
PB.registerVectorizerStartEPCallback(
58-
[](llvm::FunctionPassManager &PM,
59-
llvm::PassBuilder::OptimizationLevel Level) {
58+
[](llvm::FunctionPassManager &PM, OptimizationLevel Level) {
6059
PM.addPass(Bye());
6160
});
6261
PB.registerPipelineParsingCallback(
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
//===-------- LLVM-provided High-Level Optimization levels -*- C++ -*------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
/// \file
9+
///
10+
/// This header enumerates the LLVM-provided high-level optimization levels.
11+
/// Each level has a specific goal and rationale.
12+
///
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_PASSES_OPTIMIZATIONLEVEL_H
16+
#define LLVM_PASSES_OPTIMIZATIONLEVEL_H
17+
18+
#include <assert.h>
19+
20+
namespace llvm {
21+
22+
class OptimizationLevel final {
23+
unsigned SpeedLevel = 2;
24+
unsigned SizeLevel = 0;
25+
OptimizationLevel(unsigned SpeedLevel, unsigned SizeLevel)
26+
: SpeedLevel(SpeedLevel), SizeLevel(SizeLevel) {
27+
// Check that only valid combinations are passed.
28+
assert(SpeedLevel <= 3 &&
29+
"Optimization level for speed should be 0, 1, 2, or 3");
30+
assert(SizeLevel <= 2 &&
31+
"Optimization level for size should be 0, 1, or 2");
32+
assert((SizeLevel == 0 || SpeedLevel == 2) &&
33+
"Optimize for size should be encoded with speedup level == 2");
34+
}
35+
36+
public:
37+
OptimizationLevel() = default;
38+
/// Disable as many optimizations as possible. This doesn't completely
39+
/// disable the optimizer in all cases, for example always_inline functions
40+
/// can be required to be inlined for correctness.
41+
static const OptimizationLevel O0;
42+
43+
/// Optimize quickly without destroying debuggability.
44+
///
45+
/// This level is tuned to produce a result from the optimizer as quickly
46+
/// as possible and to avoid destroying debuggability. This tends to result
47+
/// in a very good development mode where the compiled code will be
48+
/// immediately executed as part of testing. As a consequence, where
49+
/// possible, we would like to produce efficient-to-execute code, but not
50+
/// if it significantly slows down compilation or would prevent even basic
51+
/// debugging of the resulting binary.
52+
///
53+
/// As an example, complex loop transformations such as versioning,
54+
/// vectorization, or fusion don't make sense here due to the degree to
55+
/// which the executed code differs from the source code, and the compile
56+
/// time cost.
57+
static const OptimizationLevel O1;
58+
/// Optimize for fast execution as much as possible without triggering
59+
/// significant incremental compile time or code size growth.
60+
///
61+
/// The key idea is that optimizations at this level should "pay for
62+
/// themselves". So if an optimization increases compile time by 5% or
63+
/// increases code size by 5% for a particular benchmark, that benchmark
64+
/// should also be one which sees a 5% runtime improvement. If the compile
65+
/// time or code size penalties happen on average across a diverse range of
66+
/// LLVM users' benchmarks, then the improvements should as well.
67+
///
68+
/// And no matter what, the compile time needs to not grow superlinearly
69+
/// with the size of input to LLVM so that users can control the runtime of
70+
/// the optimizer in this mode.
71+
///
72+
/// This is expected to be a good default optimization level for the vast
73+
/// majority of users.
74+
static const OptimizationLevel O2;
75+
/// Optimize for fast execution as much as possible.
76+
///
77+
/// This mode is significantly more aggressive in trading off compile time
78+
/// and code size to get execution time improvements. The core idea is that
79+
/// this mode should include any optimization that helps execution time on
80+
/// balance across a diverse collection of benchmarks, even if it increases
81+
/// code size or compile time for some benchmarks without corresponding
82+
/// improvements to execution time.
83+
///
84+
/// Despite being willing to trade more compile time off to get improved
85+
/// execution time, this mode still tries to avoid superlinear growth in
86+
/// order to make even significantly slower compile times at least scale
87+
/// reasonably. This does not preclude very substantial constant factor
88+
/// costs though.
89+
static const OptimizationLevel O3;
90+
/// Similar to \c O2 but tries to optimize for small code size instead of
91+
/// fast execution without triggering significant incremental execution
92+
/// time slowdowns.
93+
///
94+
/// The logic here is exactly the same as \c O2, but with code size and
95+
/// execution time metrics swapped.
96+
///
97+
/// A consequence of the different core goal is that this should in general
98+
/// produce substantially smaller executables that still run in
99+
/// a reasonable amount of time.
100+
static const OptimizationLevel Os;
101+
/// A very specialized mode that will optimize for code size at any and all
102+
/// costs.
103+
///
104+
/// This is useful primarily when there are absolute size limitations and
105+
/// any effort taken to reduce the size is worth it regardless of the
106+
/// execution time impact. You should expect this level to produce rather
107+
/// slow, but very small, code.
108+
static const OptimizationLevel Oz;
109+
110+
bool isOptimizingForSpeed() const { return SizeLevel == 0 && SpeedLevel > 0; }
111+
112+
bool isOptimizingForSize() const { return SizeLevel > 0; }
113+
114+
bool operator==(const OptimizationLevel &Other) const {
115+
return SizeLevel == Other.SizeLevel && SpeedLevel == Other.SpeedLevel;
116+
}
117+
bool operator!=(const OptimizationLevel &Other) const {
118+
return SizeLevel != Other.SizeLevel || SpeedLevel != Other.SpeedLevel;
119+
}
120+
121+
unsigned getSpeedupLevel() const { return SpeedLevel; }
122+
123+
unsigned getSizeLevel() const { return SizeLevel; }
124+
};
125+
} // namespace llvm
126+
127+
#endif

0 commit comments

Comments
 (0)