Skip to content

Commit 7acfda6

Browse files
committed
[llvm] Make new pass manager's OptimizationLevel a class
Summary: The old pass manager separated speed optimization and size optimization levels into two unsigned values. Coallescing both in an enum in the new pass manager may lead to unintentional casts and comparisons. In particular, taking a look at how the loop unroll passes were constructed previously, the Os/Oz are now (==new pass manager) treated just like O3, likely unintentionally. This change disallows raw comparisons between optimization levels, to avoid such unintended effects. As an effect, the O{s|z} behavior changes for loop unrolling and loop unroll and jam, matching O2 rather than O3. The change also parameterizes the threshold values used for loop unrolling, primarily to aid testing. Reviewers: tejohnson, davidxl Reviewed By: tejohnson Subscribers: zzheng, ychen, mehdi_amini, hiraditya, steven_wu, dexonsmith, dang, cfe-commits, llvm-commits Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D72547
1 parent c29a9f6 commit 7acfda6

File tree

7 files changed

+233
-79
lines changed

7 files changed

+233
-79
lines changed

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -924,25 +924,25 @@ static PassBuilder::OptimizationLevel mapToLevel(const CodeGenOptions &Opts) {
924924
llvm_unreachable("Invalid optimization level!");
925925

926926
case 1:
927-
return PassBuilder::O1;
927+
return PassBuilder::OptimizationLevel::O1;
928928

929929
case 2:
930930
switch (Opts.OptimizeSize) {
931931
default:
932932
llvm_unreachable("Invalid optimization level for size!");
933933

934934
case 0:
935-
return PassBuilder::O2;
935+
return PassBuilder::OptimizationLevel::O2;
936936

937937
case 1:
938-
return PassBuilder::Os;
938+
return PassBuilder::OptimizationLevel::Os;
939939

940940
case 2:
941-
return PassBuilder::Oz;
941+
return PassBuilder::OptimizationLevel::Oz;
942942
}
943943

944944
case 3:
945-
return PassBuilder::O3;
945+
return PassBuilder::OptimizationLevel::O3;
946946
}
947947
}
948948

llvm/include/llvm/Passes/PassBuilder.h

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -143,11 +143,26 @@ class PassBuilder {
143143
///
144144
/// This enumerates the LLVM-provided high-level optimization levels. Each
145145
/// level has a specific goal and rationale.
146-
enum OptimizationLevel {
146+
class OptimizationLevel final {
147+
unsigned SpeedLevel = 2;
148+
unsigned SizeLevel = 0;
149+
OptimizationLevel(unsigned SpeedLevel, unsigned SizeLevel)
150+
: SpeedLevel(SpeedLevel), SizeLevel(SizeLevel) {
151+
// Check that only valid combinations are passed.
152+
assert(SpeedLevel <= 3 &&
153+
"Optimization level for speed should be 0, 1, 2, or 3");
154+
assert(SizeLevel <= 2 &&
155+
"Optimization level for size should be 0, 1, or 2");
156+
assert((SizeLevel == 0 || SpeedLevel == 2) &&
157+
"Optimize for size should be encoded with speedup level == 2");
158+
}
159+
160+
public:
161+
OptimizationLevel() = default;
147162
/// Disable as many optimizations as possible. This doesn't completely
148163
/// disable the optimizer in all cases, for example always_inline functions
149164
/// can be required to be inlined for correctness.
150-
O0,
165+
static const OptimizationLevel O0;
151166

152167
/// Optimize quickly without destroying debuggability.
153168
///
@@ -161,10 +176,9 @@ class PassBuilder {
161176
///
162177
/// As an example, complex loop transformations such as versioning,
163178
/// vectorization, or fusion don't make sense here due to the degree to
164-
/// which the executed code differs from the source code, and the compile time
165-
/// cost.
166-
O1,
167-
179+
/// which the executed code differs from the source code, and the compile
180+
/// time cost.
181+
static const OptimizationLevel O1;
168182
/// Optimize for fast execution as much as possible without triggering
169183
/// significant incremental compile time or code size growth.
170184
///
@@ -181,8 +195,7 @@ class PassBuilder {
181195
///
182196
/// This is expected to be a good default optimization level for the vast
183197
/// majority of users.
184-
O2,
185-
198+
static const OptimizationLevel O2;
186199
/// Optimize for fast execution as much as possible.
187200
///
188201
/// This mode is significantly more aggressive in trading off compile time
@@ -197,8 +210,7 @@ class PassBuilder {
197210
/// order to make even significantly slower compile times at least scale
198211
/// reasonably. This does not preclude very substantial constant factor
199212
/// costs though.
200-
O3,
201-
213+
static const OptimizationLevel O3;
202214
/// Similar to \c O2 but tries to optimize for small code size instead of
203215
/// fast execution without triggering significant incremental execution
204216
/// time slowdowns.
@@ -209,16 +221,32 @@ class PassBuilder {
209221
/// A consequence of the different core goal is that this should in general
210222
/// produce substantially smaller executables that still run in
211223
/// a reasonable amount of time.
212-
Os,
213-
224+
static const OptimizationLevel Os;
214225
/// A very specialized mode that will optimize for code size at any and all
215226
/// costs.
216227
///
217228
/// This is useful primarily when there are absolute size limitations and
218229
/// any effort taken to reduce the size is worth it regardless of the
219230
/// execution time impact. You should expect this level to produce rather
220231
/// slow, but very small, code.
221-
Oz
232+
static const OptimizationLevel Oz;
233+
234+
bool isOptimizingForSpeed() const {
235+
return SizeLevel == 0 && SpeedLevel > 0;
236+
}
237+
238+
bool isOptimizingForSize() const { return SizeLevel > 0; }
239+
240+
bool operator==(const OptimizationLevel &Other) const {
241+
return SizeLevel == Other.SizeLevel && SpeedLevel == Other.SpeedLevel;
242+
}
243+
bool operator!=(const OptimizationLevel &Other) const {
244+
return SizeLevel != Other.SizeLevel || SpeedLevel != Other.SpeedLevel;
245+
}
246+
247+
unsigned getSpeedupLevel() const { return SpeedLevel; }
248+
249+
unsigned getSizeLevel() const { return SizeLevel; }
222250
};
223251

224252
explicit PassBuilder(TargetMachine *TM = nullptr,

llvm/lib/LTO/LTOBackend.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,16 +203,16 @@ static void runNewPMPasses(const Config &Conf, Module &Mod, TargetMachine *TM,
203203
default:
204204
llvm_unreachable("Invalid optimization level");
205205
case 0:
206-
OL = PassBuilder::O0;
206+
OL = PassBuilder::OptimizationLevel::O0;
207207
break;
208208
case 1:
209-
OL = PassBuilder::O1;
209+
OL = PassBuilder::OptimizationLevel::O1;
210210
break;
211211
case 2:
212-
OL = PassBuilder::O2;
212+
OL = PassBuilder::OptimizationLevel::O2;
213213
break;
214214
case 3:
215-
OL = PassBuilder::O3;
215+
OL = PassBuilder::OptimizationLevel::O3;
216216
break;
217217
}
218218

0 commit comments

Comments
 (0)