blob: 7edb642c5b0a3e9e82bc10fb092bac9861aa41d6 [file] [log] [blame]
Roland Levillain75be2832014-10-17 17:02:00 +01001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "optimization.h"
18
Aart Bik2ca10eb2017-11-15 15:17:53 -080019#ifdef ART_ENABLE_CODEGEN_arm
20#include "instruction_simplifier_arm.h"
21#endif
22#ifdef ART_ENABLE_CODEGEN_arm64
23#include "instruction_simplifier_arm64.h"
24#endif
25#ifdef ART_ENABLE_CODEGEN_mips
26#include "instruction_simplifier_mips.h"
27#include "pc_relative_fixups_mips.h"
28#endif
29#ifdef ART_ENABLE_CODEGEN_x86
30#include "pc_relative_fixups_x86.h"
31#endif
32#if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64)
33#include "x86_memory_gen.h"
34#endif
35
36#include "bounds_check_elimination.h"
37#include "cha_guard_optimization.h"
38#include "code_sinking.h"
39#include "constant_folding.h"
40#include "constructor_fence_redundancy_elimination.h"
41#include "dead_code_elimination.h"
42#include "driver/dex_compilation_unit.h"
43#include "gvn.h"
44#include "induction_var_analysis.h"
45#include "inliner.h"
46#include "instruction_simplifier.h"
47#include "intrinsics.h"
48#include "licm.h"
49#include "load_store_analysis.h"
50#include "load_store_elimination.h"
51#include "loop_optimization.h"
52#include "scheduler.h"
53#include "select_generator.h"
54#include "sharpening.h"
55#include "side_effects_analysis.h"
56
57// Decide between default or alternative pass name.
58
Roland Levillain75be2832014-10-17 17:02:00 +010059namespace art {
Aart Bik2ca10eb2017-11-15 15:17:53 -080060
61const char* OptimizationPassName(OptimizationPass pass) {
62 switch (pass) {
63 case OptimizationPass::kSideEffectsAnalysis:
64 return SideEffectsAnalysis::kSideEffectsAnalysisPassName;
65 case OptimizationPass::kInductionVarAnalysis:
66 return HInductionVarAnalysis::kInductionPassName;
67 case OptimizationPass::kLoadStoreAnalysis:
68 return LoadStoreAnalysis::kLoadStoreAnalysisPassName;
69 case OptimizationPass::kGlobalValueNumbering:
70 return GVNOptimization::kGlobalValueNumberingPassName;
71 case OptimizationPass::kInvariantCodeMotion:
72 return LICM::kLoopInvariantCodeMotionPassName;
73 case OptimizationPass::kLoopOptimization:
74 return HLoopOptimization::kLoopOptimizationPassName;
75 case OptimizationPass::kBoundsCheckElimination:
76 return BoundsCheckElimination::kBoundsCheckEliminationPassName;
77 case OptimizationPass::kLoadStoreElimination:
78 return LoadStoreElimination::kLoadStoreEliminationPassName;
79 case OptimizationPass::kConstantFolding:
80 return HConstantFolding::kConstantFoldingPassName;
81 case OptimizationPass::kDeadCodeElimination:
82 return HDeadCodeElimination::kDeadCodeEliminationPassName;
83 case OptimizationPass::kInliner:
84 return HInliner::kInlinerPassName;
85 case OptimizationPass::kSharpening:
86 return HSharpening::kSharpeningPassName;
87 case OptimizationPass::kSelectGenerator:
88 return HSelectGenerator::kSelectGeneratorPassName;
89 case OptimizationPass::kInstructionSimplifier:
90 return InstructionSimplifier::kInstructionSimplifierPassName;
91 case OptimizationPass::kIntrinsicsRecognizer:
92 return IntrinsicsRecognizer::kIntrinsicsRecognizerPassName;
93 case OptimizationPass::kCHAGuardOptimization:
94 return CHAGuardOptimization::kCHAGuardOptimizationPassName;
95 case OptimizationPass::kCodeSinking:
96 return CodeSinking::kCodeSinkingPassName;
97 case OptimizationPass::kConstructorFenceRedundancyElimination:
98 return ConstructorFenceRedundancyElimination::kCFREPassName;
99 case OptimizationPass::kScheduling:
100 return HInstructionScheduling::kInstructionSchedulingPassName;
101#ifdef ART_ENABLE_CODEGEN_arm
102 case OptimizationPass::kInstructionSimplifierArm:
103 return arm::InstructionSimplifierArm::kInstructionSimplifierArmPassName;
104#endif
105#ifdef ART_ENABLE_CODEGEN_arm64
106 case OptimizationPass::kInstructionSimplifierArm64:
107 return arm64::InstructionSimplifierArm64::kInstructionSimplifierArm64PassName;
108#endif
109#ifdef ART_ENABLE_CODEGEN_mips
110 case OptimizationPass::kPcRelativeFixupsMips:
111 return mips::PcRelativeFixups::kPcRelativeFixupsMipsPassName;
112 case OptimizationPass::kInstructionSimplifierMips:
113 return mips::InstructionSimplifierMips::kInstructionSimplifierMipsPassName;
114#endif
115#ifdef ART_ENABLE_CODEGEN_x86
116 case OptimizationPass::kPcRelativeFixupsX86:
117 return x86::PcRelativeFixups::kPcRelativeFixupsX86PassName;
118#endif
119#if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64)
120 case OptimizationPass::kX86MemoryOperandGeneration:
121 return x86::X86MemoryOperandGeneration::kX86MemoryOperandGenerationPassName;
122#endif
123 }
124}
125
126#define X(x) if (name == OptimizationPassName((x))) return (x)
127
128OptimizationPass OptimizationPassByName(const std::string& name) {
129 X(OptimizationPass::kBoundsCheckElimination);
130 X(OptimizationPass::kCHAGuardOptimization);
131 X(OptimizationPass::kCodeSinking);
132 X(OptimizationPass::kConstantFolding);
133 X(OptimizationPass::kConstructorFenceRedundancyElimination);
134 X(OptimizationPass::kDeadCodeElimination);
135 X(OptimizationPass::kGlobalValueNumbering);
136 X(OptimizationPass::kInductionVarAnalysis);
137 X(OptimizationPass::kInliner);
138 X(OptimizationPass::kInstructionSimplifier);
139 X(OptimizationPass::kIntrinsicsRecognizer);
140 X(OptimizationPass::kInvariantCodeMotion);
141 X(OptimizationPass::kLoadStoreAnalysis);
142 X(OptimizationPass::kLoadStoreElimination);
143 X(OptimizationPass::kLoopOptimization);
144 X(OptimizationPass::kScheduling);
145 X(OptimizationPass::kSelectGenerator);
146 X(OptimizationPass::kSharpening);
147 X(OptimizationPass::kSideEffectsAnalysis);
148#ifdef ART_ENABLE_CODEGEN_arm
149 X(OptimizationPass::kInstructionSimplifierArm);
150#endif
151#ifdef ART_ENABLE_CODEGEN_arm64
152 X(OptimizationPass::kInstructionSimplifierArm64);
153#endif
154#ifdef ART_ENABLE_CODEGEN_mips
155 X(OptimizationPass::kPcRelativeFixupsMips);
156 X(OptimizationPass::kInstructionSimplifierMips);
157#endif
158#ifdef ART_ENABLE_CODEGEN_x86
159 X(OptimizationPass::kPcRelativeFixupsX86);
160 X(OptimizationPass::kX86MemoryOperandGeneration);
161#endif
162 LOG(FATAL) << "Cannot find optimization " << name;
163 UNREACHABLE();
164}
165
166#undef X
167
168ArenaVector<HOptimization*> ConstructOptimizations(
169 const OptimizationDef definitions[],
170 size_t length,
171 ArenaAllocator* allocator,
172 HGraph* graph,
173 OptimizingCompilerStats* stats,
174 CodeGenerator* codegen,
175 CompilerDriver* driver,
176 const DexCompilationUnit& dex_compilation_unit,
177 VariableSizedHandleScope* handles) {
178 ArenaVector<HOptimization*> optimizations(allocator->Adapter());
179
180 // Some optimizations require SideEffectsAnalysis or HInductionVarAnalysis
181 // instances. This method uses the nearest instance preceeding it in the pass
182 // name list or fails fatally if no such analysis can be found.
183 SideEffectsAnalysis* most_recent_side_effects = nullptr;
184 HInductionVarAnalysis* most_recent_induction = nullptr;
185 LoadStoreAnalysis* most_recent_lsa = nullptr;
186
187 // Loop over the requested optimizations.
188 for (size_t i = 0; i < length; i++) {
189 OptimizationPass pass = definitions[i].first;
190 const char* alt_name = definitions[i].second;
191 const char* name = alt_name != nullptr
192 ? alt_name
193 : OptimizationPassName(pass);
194 HOptimization* opt = nullptr;
195
196 switch (pass) {
197 //
198 // Analysis passes (kept in most recent for subsequent passes).
199 //
200 case OptimizationPass::kSideEffectsAnalysis:
201 opt = most_recent_side_effects = new (allocator) SideEffectsAnalysis(graph, name);
202 break;
203 case OptimizationPass::kInductionVarAnalysis:
204 opt = most_recent_induction = new (allocator) HInductionVarAnalysis(graph, name);
205 break;
206 case OptimizationPass::kLoadStoreAnalysis:
207 opt = most_recent_lsa = new (allocator) LoadStoreAnalysis(graph, name);
208 break;
209 //
210 // Passes that need prior analysis.
211 //
212 case OptimizationPass::kGlobalValueNumbering:
213 CHECK(most_recent_side_effects != nullptr);
214 opt = new (allocator) GVNOptimization(graph, *most_recent_side_effects, name);
215 break;
216 case OptimizationPass::kInvariantCodeMotion:
217 CHECK(most_recent_side_effects != nullptr);
218 opt = new (allocator) LICM(graph, *most_recent_side_effects, stats, name);
219 break;
220 case OptimizationPass::kLoopOptimization:
221 CHECK(most_recent_induction != nullptr);
222 opt = new (allocator) HLoopOptimization(graph, driver, most_recent_induction, stats, name);
223 break;
224 case OptimizationPass::kBoundsCheckElimination:
225 CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr);
226 opt = new (allocator) BoundsCheckElimination(
227 graph, *most_recent_side_effects, most_recent_induction, name);
228 break;
229 case OptimizationPass::kLoadStoreElimination:
230 CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr);
231 opt = new (allocator) LoadStoreElimination(
232 graph, *most_recent_side_effects, *most_recent_lsa, stats, name);
233 break;
234 //
235 // Regular passes.
236 //
237 case OptimizationPass::kConstantFolding:
238 opt = new (allocator) HConstantFolding(graph, name);
239 break;
240 case OptimizationPass::kDeadCodeElimination:
241 opt = new (allocator) HDeadCodeElimination(graph, stats, name);
242 break;
243 case OptimizationPass::kInliner: {
244 size_t number_of_dex_registers = dex_compilation_unit.GetCodeItem()->registers_size_;
245 opt = new (allocator) HInliner(graph, // outer_graph
246 graph, // outermost_graph
247 codegen,
248 dex_compilation_unit, // outer_compilation_unit
249 dex_compilation_unit, // outermost_compilation_unit
250 driver,
251 handles,
252 stats,
253 number_of_dex_registers,
254 /* total_number_of_instructions */ 0,
255 /* parent */ nullptr,
256 /* depth */ 0,
257 name);
258 break;
259 }
260 case OptimizationPass::kSharpening:
261 opt = new (allocator) HSharpening(
262 graph, codegen, dex_compilation_unit, driver, handles, name);
263 break;
264 case OptimizationPass::kSelectGenerator:
265 opt = new (allocator) HSelectGenerator(graph, handles, stats, name);
266 break;
267 case OptimizationPass::kInstructionSimplifier:
268 opt = new (allocator) InstructionSimplifier(graph, codegen, driver, stats, name);
269 break;
270 case OptimizationPass::kIntrinsicsRecognizer:
271 opt = new (allocator) IntrinsicsRecognizer(graph, stats, name);
272 break;
273 case OptimizationPass::kCHAGuardOptimization:
274 opt = new (allocator) CHAGuardOptimization(graph, name);
275 break;
276 case OptimizationPass::kCodeSinking:
277 opt = new (allocator) CodeSinking(graph, stats, name);
278 break;
279 case OptimizationPass::kConstructorFenceRedundancyElimination:
280 opt = new (allocator) ConstructorFenceRedundancyElimination(graph, stats, name);
281 break;
282 case OptimizationPass::kScheduling:
283 opt = new (allocator) HInstructionScheduling(
284 graph, driver->GetInstructionSet(), codegen, name);
285 break;
286 //
287 // Arch-specific passes.
288 //
289#ifdef ART_ENABLE_CODEGEN_arm
290 case OptimizationPass::kInstructionSimplifierArm:
291 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
292 opt = new (allocator) arm::InstructionSimplifierArm(graph, stats);
293 break;
294#endif
295#ifdef ART_ENABLE_CODEGEN_arm64
296 case OptimizationPass::kInstructionSimplifierArm64:
297 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
298 opt = new (allocator) arm64::InstructionSimplifierArm64(graph, stats);
299 break;
300#endif
301#ifdef ART_ENABLE_CODEGEN_mips
302 case OptimizationPass::kPcRelativeFixupsMips:
303 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
304 opt = new (allocator) mips::PcRelativeFixups(graph, codegen, stats);
305 break;
306 case OptimizationPass::kInstructionSimplifierMips:
307 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
308 opt = new (allocator) mips::InstructionSimplifierMips(graph, codegen, stats);
309 break;
310#endif
311#ifdef ART_ENABLE_CODEGEN_x86
312 case OptimizationPass::kPcRelativeFixupsX86:
313 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
314 opt = new (allocator) x86::PcRelativeFixups(graph, codegen, stats);
315 break;
316 case OptimizationPass::kX86MemoryOperandGeneration:
317 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
318 opt = new (allocator) x86::X86MemoryOperandGeneration(graph, codegen, stats);
319 break;
320#endif
321 } // switch
322
323 // Add each next optimization to result vector.
324 CHECK(opt != nullptr);
325 DCHECK_STREQ(name, opt->GetPassName()); // sanity
326 optimizations.push_back(opt);
327 }
328
329 return optimizations;
330}
331
Roland Levillain75be2832014-10-17 17:02:00 +0100332} // namespace art