1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifndef jit_IonOptimizationLevels_h
8 #define jit_IonOptimizationLevels_h
9
10 #include "mozilla/EnumeratedArray.h"
11
12 #include "jstypes.h"
13
14 #include "jit/JitOptions.h"
15 #include "js/TypeDecls.h"
16
17 namespace js {
18 namespace jit {
19
20 enum class OptimizationLevel : uint8_t { Normal, Wasm, Count, DontCompile };
21
22 #ifdef JS_JITSPEW
OptimizationLevelString(OptimizationLevel level)23 inline const char* OptimizationLevelString(OptimizationLevel level) {
24 switch (level) {
25 case OptimizationLevel::DontCompile:
26 return "Optimization_DontCompile";
27 case OptimizationLevel::Normal:
28 return "Optimization_Normal";
29 case OptimizationLevel::Wasm:
30 return "Optimization_Wasm";
31 case OptimizationLevel::Count:;
32 }
33 MOZ_CRASH("Invalid OptimizationLevel");
34 }
35 #endif
36
37 // Class representing the Ion optimization settings for an OptimizationLevel.
38 class OptimizationInfo {
39 OptimizationLevel level_;
40
41 // Toggles whether Effective Address Analysis is performed.
42 bool eaa_;
43
44 // Toggles whether Alignment Mask Analysis is performed.
45 bool ama_;
46
47 // Toggles whether Edge Case Analysis is used.
48 bool edgeCaseAnalysis_;
49
50 // Toggles whether redundant checks get removed.
51 bool eliminateRedundantChecks_;
52
53 // Toggles whether interpreted scripts get inlined.
54 bool inlineInterpreted_;
55
56 // Toggles whether native scripts get inlined.
57 bool inlineNative_;
58
59 // Toggles whether global value numbering is used.
60 bool gvn_;
61
62 // Toggles whether loop invariant code motion is performed.
63 bool licm_;
64
65 // Toggles whether Range Analysis is used.
66 bool rangeAnalysis_;
67
68 // Toggles whether instruction reordering is performed.
69 bool reordering_;
70
71 // Toggles whether Truncation based on Range Analysis is used.
72 bool autoTruncate_;
73
74 // Toggles whether sink is used.
75 bool sink_;
76
77 // Toggles whether scalar replacement is used.
78 bool scalarReplacement_;
79
80 // Describes which register allocator to use.
81 IonRegisterAllocator registerAllocator_;
82
baseCompilerWarmUpThreshold()83 uint32_t baseCompilerWarmUpThreshold() const {
84 MOZ_ASSERT(level_ == OptimizationLevel::Normal);
85 return JitOptions.normalIonWarmUpThreshold;
86 }
87
88 public:
OptimizationInfo()89 constexpr OptimizationInfo()
90 : level_(OptimizationLevel::Normal),
91 eaa_(false),
92 ama_(false),
93 edgeCaseAnalysis_(false),
94 eliminateRedundantChecks_(false),
95 inlineInterpreted_(false),
96 inlineNative_(false),
97 gvn_(false),
98 licm_(false),
99 rangeAnalysis_(false),
100 reordering_(false),
101 autoTruncate_(false),
102 sink_(false),
103 scalarReplacement_(false),
104 registerAllocator_(RegisterAllocator_Backtracking) {}
105
106 void initNormalOptimizationInfo();
107 void initWasmOptimizationInfo();
108
level()109 OptimizationLevel level() const { return level_; }
110
inlineInterpreted()111 bool inlineInterpreted() const {
112 return inlineInterpreted_ && !JitOptions.disableInlining;
113 }
114
inlineNative()115 bool inlineNative() const {
116 return inlineNative_ && !JitOptions.disableInlining;
117 }
118
119 uint32_t compilerWarmUpThreshold(JSScript* script,
120 jsbytecode* pc = nullptr) const;
121
122 uint32_t recompileWarmUpThreshold(JSScript* script, jsbytecode* pc) const;
123
gvnEnabled()124 bool gvnEnabled() const { return gvn_ && !JitOptions.disableGvn; }
125
licmEnabled()126 bool licmEnabled() const { return licm_ && !JitOptions.disableLicm; }
127
rangeAnalysisEnabled()128 bool rangeAnalysisEnabled() const {
129 return rangeAnalysis_ && !JitOptions.disableRangeAnalysis;
130 }
131
instructionReorderingEnabled()132 bool instructionReorderingEnabled() const {
133 return reordering_ && !JitOptions.disableInstructionReordering;
134 }
135
autoTruncateEnabled()136 bool autoTruncateEnabled() const {
137 return autoTruncate_ && rangeAnalysisEnabled();
138 }
139
sinkEnabled()140 bool sinkEnabled() const { return sink_ && !JitOptions.disableSink; }
141
eaaEnabled()142 bool eaaEnabled() const { return eaa_ && !JitOptions.disableEaa; }
143
amaEnabled()144 bool amaEnabled() const { return ama_ && !JitOptions.disableAma; }
145
edgeCaseAnalysisEnabled()146 bool edgeCaseAnalysisEnabled() const {
147 return edgeCaseAnalysis_ && !JitOptions.disableEdgeCaseAnalysis;
148 }
149
eliminateRedundantChecksEnabled()150 bool eliminateRedundantChecksEnabled() const {
151 return eliminateRedundantChecks_;
152 }
153
registerAllocator()154 IonRegisterAllocator registerAllocator() const {
155 return JitOptions.forcedRegisterAllocator.valueOr(registerAllocator_);
156 }
157
scalarReplacementEnabled()158 bool scalarReplacementEnabled() const {
159 return scalarReplacement_ && !JitOptions.disableScalarReplacement;
160 }
161 };
162
163 class OptimizationLevelInfo {
164 private:
165 mozilla::EnumeratedArray<OptimizationLevel, OptimizationLevel::Count,
166 OptimizationInfo>
167 infos_;
168
169 public:
170 OptimizationLevelInfo();
171
get(OptimizationLevel level)172 const OptimizationInfo* get(OptimizationLevel level) const {
173 return &infos_[level];
174 }
175
176 OptimizationLevel levelForScript(JSScript* script,
177 jsbytecode* pc = nullptr) const;
178 };
179
180 extern const OptimizationLevelInfo IonOptimizations;
181
182 } // namespace jit
183 } // namespace js
184
185 #endif /* jit_IonOptimizationLevels_h */
186