OptimizationLevel.h 5.7 KB

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