Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 14 | pmbaty | 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 |