blob: d37c43db81f7e683be9c3cac53ed42b97db7c6ee [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"
David Sehr9e734c72018-01-04 17:56:19 -080042#include "dex/code_item_accessors-inl.h"
Aart Bik2ca10eb2017-11-15 15:17:53 -080043#include "driver/dex_compilation_unit.h"
44#include "gvn.h"
45#include "induction_var_analysis.h"
46#include "inliner.h"
47#include "instruction_simplifier.h"
48#include "intrinsics.h"
49#include "licm.h"
50#include "load_store_analysis.h"
51#include "load_store_elimination.h"
52#include "loop_optimization.h"
53#include "scheduler.h"
54#include "select_generator.h"
55#include "sharpening.h"
56#include "side_effects_analysis.h"
57
58// Decide between default or alternative pass name.
59
Roland Levillain75be2832014-10-17 17:02:00 +010060namespace art {
Aart Bik2ca10eb2017-11-15 15:17:53 -080061
62const char* OptimizationPassName(OptimizationPass pass) {
63 switch (pass) {
64 case OptimizationPass::kSideEffectsAnalysis:
65 return SideEffectsAnalysis::kSideEffectsAnalysisPassName;
66 case OptimizationPass::kInductionVarAnalysis:
67 return HInductionVarAnalysis::kInductionPassName;
68 case OptimizationPass::kLoadStoreAnalysis:
69 return LoadStoreAnalysis::kLoadStoreAnalysisPassName;
70 case OptimizationPass::kGlobalValueNumbering:
71 return GVNOptimization::kGlobalValueNumberingPassName;
72 case OptimizationPass::kInvariantCodeMotion:
73 return LICM::kLoopInvariantCodeMotionPassName;
74 case OptimizationPass::kLoopOptimization:
75 return HLoopOptimization::kLoopOptimizationPassName;
76 case OptimizationPass::kBoundsCheckElimination:
77 return BoundsCheckElimination::kBoundsCheckEliminationPassName;
78 case OptimizationPass::kLoadStoreElimination:
79 return LoadStoreElimination::kLoadStoreEliminationPassName;
80 case OptimizationPass::kConstantFolding:
81 return HConstantFolding::kConstantFoldingPassName;
82 case OptimizationPass::kDeadCodeElimination:
83 return HDeadCodeElimination::kDeadCodeEliminationPassName;
84 case OptimizationPass::kInliner:
85 return HInliner::kInlinerPassName;
86 case OptimizationPass::kSharpening:
87 return HSharpening::kSharpeningPassName;
88 case OptimizationPass::kSelectGenerator:
89 return HSelectGenerator::kSelectGeneratorPassName;
90 case OptimizationPass::kInstructionSimplifier:
91 return InstructionSimplifier::kInstructionSimplifierPassName;
92 case OptimizationPass::kIntrinsicsRecognizer:
93 return IntrinsicsRecognizer::kIntrinsicsRecognizerPassName;
94 case OptimizationPass::kCHAGuardOptimization:
95 return CHAGuardOptimization::kCHAGuardOptimizationPassName;
96 case OptimizationPass::kCodeSinking:
97 return CodeSinking::kCodeSinkingPassName;
98 case OptimizationPass::kConstructorFenceRedundancyElimination:
99 return ConstructorFenceRedundancyElimination::kCFREPassName;
100 case OptimizationPass::kScheduling:
101 return HInstructionScheduling::kInstructionSchedulingPassName;
102#ifdef ART_ENABLE_CODEGEN_arm
103 case OptimizationPass::kInstructionSimplifierArm:
104 return arm::InstructionSimplifierArm::kInstructionSimplifierArmPassName;
105#endif
106#ifdef ART_ENABLE_CODEGEN_arm64
107 case OptimizationPass::kInstructionSimplifierArm64:
108 return arm64::InstructionSimplifierArm64::kInstructionSimplifierArm64PassName;
109#endif
110#ifdef ART_ENABLE_CODEGEN_mips
111 case OptimizationPass::kPcRelativeFixupsMips:
112 return mips::PcRelativeFixups::kPcRelativeFixupsMipsPassName;
113 case OptimizationPass::kInstructionSimplifierMips:
114 return mips::InstructionSimplifierMips::kInstructionSimplifierMipsPassName;
115#endif
116#ifdef ART_ENABLE_CODEGEN_x86
117 case OptimizationPass::kPcRelativeFixupsX86:
118 return x86::PcRelativeFixups::kPcRelativeFixupsX86PassName;
119#endif
120#if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64)
121 case OptimizationPass::kX86MemoryOperandGeneration:
122 return x86::X86MemoryOperandGeneration::kX86MemoryOperandGenerationPassName;
123#endif
Aart Bik2e148682018-04-18 16:11:12 -0700124 case OptimizationPass::kNone:
125 LOG(FATAL) << "kNone does not represent an actual pass";
126 UNREACHABLE();
Aart Bik2ca10eb2017-11-15 15:17:53 -0800127 }
128}
129
Aart Bik2e148682018-04-18 16:11:12 -0700130#define X(x) if (pass_name == OptimizationPassName((x))) return (x)
Aart Bik2ca10eb2017-11-15 15:17:53 -0800131
Aart Bik2e148682018-04-18 16:11:12 -0700132OptimizationPass OptimizationPassByName(const std::string& pass_name) {
Aart Bik2ca10eb2017-11-15 15:17:53 -0800133 X(OptimizationPass::kBoundsCheckElimination);
134 X(OptimizationPass::kCHAGuardOptimization);
135 X(OptimizationPass::kCodeSinking);
136 X(OptimizationPass::kConstantFolding);
137 X(OptimizationPass::kConstructorFenceRedundancyElimination);
138 X(OptimizationPass::kDeadCodeElimination);
139 X(OptimizationPass::kGlobalValueNumbering);
140 X(OptimizationPass::kInductionVarAnalysis);
141 X(OptimizationPass::kInliner);
142 X(OptimizationPass::kInstructionSimplifier);
143 X(OptimizationPass::kIntrinsicsRecognizer);
144 X(OptimizationPass::kInvariantCodeMotion);
145 X(OptimizationPass::kLoadStoreAnalysis);
146 X(OptimizationPass::kLoadStoreElimination);
147 X(OptimizationPass::kLoopOptimization);
148 X(OptimizationPass::kScheduling);
149 X(OptimizationPass::kSelectGenerator);
150 X(OptimizationPass::kSharpening);
151 X(OptimizationPass::kSideEffectsAnalysis);
152#ifdef ART_ENABLE_CODEGEN_arm
153 X(OptimizationPass::kInstructionSimplifierArm);
154#endif
155#ifdef ART_ENABLE_CODEGEN_arm64
156 X(OptimizationPass::kInstructionSimplifierArm64);
157#endif
158#ifdef ART_ENABLE_CODEGEN_mips
159 X(OptimizationPass::kPcRelativeFixupsMips);
160 X(OptimizationPass::kInstructionSimplifierMips);
161#endif
162#ifdef ART_ENABLE_CODEGEN_x86
163 X(OptimizationPass::kPcRelativeFixupsX86);
164 X(OptimizationPass::kX86MemoryOperandGeneration);
165#endif
Aart Bik2e148682018-04-18 16:11:12 -0700166 LOG(FATAL) << "Cannot find optimization " << pass_name;
Aart Bik2ca10eb2017-11-15 15:17:53 -0800167 UNREACHABLE();
168}
169
170#undef X
171
172ArenaVector<HOptimization*> ConstructOptimizations(
173 const OptimizationDef definitions[],
174 size_t length,
175 ArenaAllocator* allocator,
176 HGraph* graph,
177 OptimizingCompilerStats* stats,
178 CodeGenerator* codegen,
179 CompilerDriver* driver,
180 const DexCompilationUnit& dex_compilation_unit,
181 VariableSizedHandleScope* handles) {
182 ArenaVector<HOptimization*> optimizations(allocator->Adapter());
183
184 // Some optimizations require SideEffectsAnalysis or HInductionVarAnalysis
185 // instances. This method uses the nearest instance preceeding it in the pass
186 // name list or fails fatally if no such analysis can be found.
187 SideEffectsAnalysis* most_recent_side_effects = nullptr;
188 HInductionVarAnalysis* most_recent_induction = nullptr;
189 LoadStoreAnalysis* most_recent_lsa = nullptr;
190
191 // Loop over the requested optimizations.
192 for (size_t i = 0; i < length; i++) {
Aart Bik2e148682018-04-18 16:11:12 -0700193 OptimizationPass pass = definitions[i].pass;
194 const char* alt_name = definitions[i].pass_name;
195 const char* pass_name = alt_name != nullptr
Aart Bik2ca10eb2017-11-15 15:17:53 -0800196 ? alt_name
197 : OptimizationPassName(pass);
198 HOptimization* opt = nullptr;
199
200 switch (pass) {
201 //
202 // Analysis passes (kept in most recent for subsequent passes).
203 //
204 case OptimizationPass::kSideEffectsAnalysis:
Aart Bik2e148682018-04-18 16:11:12 -0700205 opt = most_recent_side_effects = new (allocator) SideEffectsAnalysis(graph, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800206 break;
207 case OptimizationPass::kInductionVarAnalysis:
Aart Bik2e148682018-04-18 16:11:12 -0700208 opt = most_recent_induction = new (allocator) HInductionVarAnalysis(graph, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800209 break;
210 case OptimizationPass::kLoadStoreAnalysis:
Aart Bik2e148682018-04-18 16:11:12 -0700211 opt = most_recent_lsa = new (allocator) LoadStoreAnalysis(graph, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800212 break;
213 //
214 // Passes that need prior analysis.
215 //
216 case OptimizationPass::kGlobalValueNumbering:
217 CHECK(most_recent_side_effects != nullptr);
Aart Bik2e148682018-04-18 16:11:12 -0700218 opt = new (allocator) GVNOptimization(graph, *most_recent_side_effects, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800219 break;
220 case OptimizationPass::kInvariantCodeMotion:
221 CHECK(most_recent_side_effects != nullptr);
Aart Bik2e148682018-04-18 16:11:12 -0700222 opt = new (allocator) LICM(graph, *most_recent_side_effects, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800223 break;
224 case OptimizationPass::kLoopOptimization:
225 CHECK(most_recent_induction != nullptr);
Aart Bik2e148682018-04-18 16:11:12 -0700226 opt = new (allocator) HLoopOptimization(
227 graph, driver, most_recent_induction, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800228 break;
229 case OptimizationPass::kBoundsCheckElimination:
230 CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr);
231 opt = new (allocator) BoundsCheckElimination(
Aart Bik2e148682018-04-18 16:11:12 -0700232 graph, *most_recent_side_effects, most_recent_induction, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800233 break;
234 case OptimizationPass::kLoadStoreElimination:
235 CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr);
236 opt = new (allocator) LoadStoreElimination(
Aart Bik2e148682018-04-18 16:11:12 -0700237 graph, *most_recent_side_effects, *most_recent_lsa, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800238 break;
239 //
240 // Regular passes.
241 //
242 case OptimizationPass::kConstantFolding:
Aart Bik2e148682018-04-18 16:11:12 -0700243 opt = new (allocator) HConstantFolding(graph, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800244 break;
245 case OptimizationPass::kDeadCodeElimination:
Aart Bik2e148682018-04-18 16:11:12 -0700246 opt = new (allocator) HDeadCodeElimination(graph, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800247 break;
248 case OptimizationPass::kInliner: {
Mathieu Chartier698ebbc2018-01-05 11:00:42 -0800249 CodeItemDataAccessor accessor(*dex_compilation_unit.GetDexFile(),
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800250 dex_compilation_unit.GetCodeItem());
Aart Bik2ca10eb2017-11-15 15:17:53 -0800251 opt = new (allocator) HInliner(graph, // outer_graph
252 graph, // outermost_graph
253 codegen,
254 dex_compilation_unit, // outer_compilation_unit
255 dex_compilation_unit, // outermost_compilation_unit
256 driver,
257 handles,
258 stats,
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800259 accessor.RegistersSize(),
Aart Bik2ca10eb2017-11-15 15:17:53 -0800260 /* total_number_of_instructions */ 0,
261 /* parent */ nullptr,
262 /* depth */ 0,
Aart Bik2e148682018-04-18 16:11:12 -0700263 pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800264 break;
265 }
266 case OptimizationPass::kSharpening:
Aart Bik2e148682018-04-18 16:11:12 -0700267 opt = new (allocator) HSharpening(graph, codegen, driver, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800268 break;
269 case OptimizationPass::kSelectGenerator:
Aart Bik2e148682018-04-18 16:11:12 -0700270 opt = new (allocator) HSelectGenerator(graph, handles, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800271 break;
272 case OptimizationPass::kInstructionSimplifier:
Aart Bik2e148682018-04-18 16:11:12 -0700273 opt = new (allocator) InstructionSimplifier(graph, codegen, driver, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800274 break;
275 case OptimizationPass::kIntrinsicsRecognizer:
Aart Bik2e148682018-04-18 16:11:12 -0700276 opt = new (allocator) IntrinsicsRecognizer(graph, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800277 break;
278 case OptimizationPass::kCHAGuardOptimization:
Aart Bik2e148682018-04-18 16:11:12 -0700279 opt = new (allocator) CHAGuardOptimization(graph, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800280 break;
281 case OptimizationPass::kCodeSinking:
Aart Bik2e148682018-04-18 16:11:12 -0700282 opt = new (allocator) CodeSinking(graph, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800283 break;
284 case OptimizationPass::kConstructorFenceRedundancyElimination:
Aart Bik2e148682018-04-18 16:11:12 -0700285 opt = new (allocator) ConstructorFenceRedundancyElimination(graph, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800286 break;
287 case OptimizationPass::kScheduling:
288 opt = new (allocator) HInstructionScheduling(
Aart Bik2e148682018-04-18 16:11:12 -0700289 graph, driver->GetInstructionSet(), codegen, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800290 break;
291 //
292 // Arch-specific passes.
293 //
294#ifdef ART_ENABLE_CODEGEN_arm
295 case OptimizationPass::kInstructionSimplifierArm:
296 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
297 opt = new (allocator) arm::InstructionSimplifierArm(graph, stats);
298 break;
299#endif
300#ifdef ART_ENABLE_CODEGEN_arm64
301 case OptimizationPass::kInstructionSimplifierArm64:
302 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
303 opt = new (allocator) arm64::InstructionSimplifierArm64(graph, stats);
304 break;
305#endif
306#ifdef ART_ENABLE_CODEGEN_mips
307 case OptimizationPass::kPcRelativeFixupsMips:
308 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
309 opt = new (allocator) mips::PcRelativeFixups(graph, codegen, stats);
310 break;
311 case OptimizationPass::kInstructionSimplifierMips:
312 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
313 opt = new (allocator) mips::InstructionSimplifierMips(graph, codegen, stats);
314 break;
315#endif
316#ifdef ART_ENABLE_CODEGEN_x86
317 case OptimizationPass::kPcRelativeFixupsX86:
318 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
319 opt = new (allocator) x86::PcRelativeFixups(graph, codegen, stats);
320 break;
321 case OptimizationPass::kX86MemoryOperandGeneration:
322 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
323 opt = new (allocator) x86::X86MemoryOperandGeneration(graph, codegen, stats);
324 break;
325#endif
Aart Bik2e148682018-04-18 16:11:12 -0700326 case OptimizationPass::kNone:
327 LOG(FATAL) << "kNone does not represent an actual pass";
328 UNREACHABLE();
Aart Bik2ca10eb2017-11-15 15:17:53 -0800329 } // switch
330
331 // Add each next optimization to result vector.
332 CHECK(opt != nullptr);
Aart Bik2e148682018-04-18 16:11:12 -0700333 DCHECK_STREQ(pass_name, opt->GetPassName()); // sanity
Aart Bik2ca10eb2017-11-15 15:17:53 -0800334 optimizations.push_back(opt);
335 }
336
337 return optimizations;
338}
339
Roland Levillain75be2832014-10-17 17:02:00 +0100340} // namespace art