1 /*
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
19 #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_x86
26 #include "pc_relative_fixups_x86.h"
27 #include "instruction_simplifier_x86.h"
28 #endif
29 #if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64)
30 #include "x86_memory_gen.h"
31 #endif
32 #ifdef ART_ENABLE_CODEGEN_x86_64
33 #include "instruction_simplifier_x86_64.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 "dex/code_item_accessors-inl.h"
43 #include "driver/compiler_options.h"
44 #include "driver/dex_compilation_unit.h"
45 #include "gvn.h"
46 #include "induction_var_analysis.h"
47 #include "inliner.h"
48 #include "instruction_simplifier.h"
49 #include "intrinsics.h"
50 #include "licm.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
60 namespace art {
61
OptimizationPassName(OptimizationPass pass)62 const 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::kGlobalValueNumbering:
69 return GVNOptimization::kGlobalValueNumberingPassName;
70 case OptimizationPass::kInvariantCodeMotion:
71 return LICM::kLoopInvariantCodeMotionPassName;
72 case OptimizationPass::kLoopOptimization:
73 return HLoopOptimization::kLoopOptimizationPassName;
74 case OptimizationPass::kBoundsCheckElimination:
75 return BoundsCheckElimination::kBoundsCheckEliminationPassName;
76 case OptimizationPass::kLoadStoreElimination:
77 return LoadStoreElimination::kLoadStoreEliminationPassName;
78 case OptimizationPass::kConstantFolding:
79 return HConstantFolding::kConstantFoldingPassName;
80 case OptimizationPass::kDeadCodeElimination:
81 return HDeadCodeElimination::kDeadCodeEliminationPassName;
82 case OptimizationPass::kInliner:
83 return HInliner::kInlinerPassName;
84 case OptimizationPass::kSelectGenerator:
85 return HSelectGenerator::kSelectGeneratorPassName;
86 case OptimizationPass::kAggressiveInstructionSimplifier:
87 case OptimizationPass::kInstructionSimplifier:
88 return InstructionSimplifier::kInstructionSimplifierPassName;
89 case OptimizationPass::kCHAGuardOptimization:
90 return CHAGuardOptimization::kCHAGuardOptimizationPassName;
91 case OptimizationPass::kCodeSinking:
92 return CodeSinking::kCodeSinkingPassName;
93 case OptimizationPass::kConstructorFenceRedundancyElimination:
94 return ConstructorFenceRedundancyElimination::kCFREPassName;
95 case OptimizationPass::kScheduling:
96 return HInstructionScheduling::kInstructionSchedulingPassName;
97 #ifdef ART_ENABLE_CODEGEN_arm
98 case OptimizationPass::kInstructionSimplifierArm:
99 return arm::InstructionSimplifierArm::kInstructionSimplifierArmPassName;
100 #endif
101 #ifdef ART_ENABLE_CODEGEN_arm64
102 case OptimizationPass::kInstructionSimplifierArm64:
103 return arm64::InstructionSimplifierArm64::kInstructionSimplifierArm64PassName;
104 #endif
105 #ifdef ART_ENABLE_CODEGEN_x86
106 case OptimizationPass::kPcRelativeFixupsX86:
107 return x86::PcRelativeFixups::kPcRelativeFixupsX86PassName;
108 case OptimizationPass::kInstructionSimplifierX86:
109 return x86::InstructionSimplifierX86::kInstructionSimplifierX86PassName;
110 #endif
111 #ifdef ART_ENABLE_CODEGEN_x86_64
112 case OptimizationPass::kInstructionSimplifierX86_64:
113 return x86_64::InstructionSimplifierX86_64::kInstructionSimplifierX86_64PassName;
114 #endif
115 #if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64)
116 case OptimizationPass::kX86MemoryOperandGeneration:
117 return x86::X86MemoryOperandGeneration::kX86MemoryOperandGenerationPassName;
118 #endif
119 case OptimizationPass::kNone:
120 LOG(FATAL) << "kNone does not represent an actual pass";
121 UNREACHABLE();
122 }
123 }
124
125 #define X(x) if (pass_name == OptimizationPassName((x))) return (x)
126
OptimizationPassByName(const std::string & pass_name)127 OptimizationPass OptimizationPassByName(const std::string& pass_name) {
128 X(OptimizationPass::kBoundsCheckElimination);
129 X(OptimizationPass::kCHAGuardOptimization);
130 X(OptimizationPass::kCodeSinking);
131 X(OptimizationPass::kConstantFolding);
132 X(OptimizationPass::kConstructorFenceRedundancyElimination);
133 X(OptimizationPass::kDeadCodeElimination);
134 X(OptimizationPass::kGlobalValueNumbering);
135 X(OptimizationPass::kInductionVarAnalysis);
136 X(OptimizationPass::kInliner);
137 X(OptimizationPass::kInstructionSimplifier);
138 X(OptimizationPass::kInvariantCodeMotion);
139 X(OptimizationPass::kLoadStoreElimination);
140 X(OptimizationPass::kLoopOptimization);
141 X(OptimizationPass::kScheduling);
142 X(OptimizationPass::kSelectGenerator);
143 X(OptimizationPass::kSideEffectsAnalysis);
144 #ifdef ART_ENABLE_CODEGEN_arm
145 X(OptimizationPass::kInstructionSimplifierArm);
146 #endif
147 #ifdef ART_ENABLE_CODEGEN_arm64
148 X(OptimizationPass::kInstructionSimplifierArm64);
149 #endif
150 #ifdef ART_ENABLE_CODEGEN_x86
151 X(OptimizationPass::kPcRelativeFixupsX86);
152 X(OptimizationPass::kX86MemoryOperandGeneration);
153 #endif
154 LOG(FATAL) << "Cannot find optimization " << pass_name;
155 UNREACHABLE();
156 }
157
158 #undef X
159
ConstructOptimizations(const OptimizationDef definitions[],size_t length,ArenaAllocator * allocator,HGraph * graph,OptimizingCompilerStats * stats,CodeGenerator * codegen,const DexCompilationUnit & dex_compilation_unit)160 ArenaVector<HOptimization*> ConstructOptimizations(
161 const OptimizationDef definitions[],
162 size_t length,
163 ArenaAllocator* allocator,
164 HGraph* graph,
165 OptimizingCompilerStats* stats,
166 CodeGenerator* codegen,
167 const DexCompilationUnit& dex_compilation_unit) {
168 ArenaVector<HOptimization*> optimizations(allocator->Adapter());
169
170 // Some optimizations require SideEffectsAnalysis or HInductionVarAnalysis
171 // instances. This method uses the nearest instance preceeding it in the pass
172 // name list or fails fatally if no such analysis can be found.
173 SideEffectsAnalysis* most_recent_side_effects = nullptr;
174 HInductionVarAnalysis* most_recent_induction = nullptr;
175
176 // Loop over the requested optimizations.
177 for (size_t i = 0; i < length; i++) {
178 OptimizationPass pass = definitions[i].pass;
179 const char* alt_name = definitions[i].pass_name;
180 const char* pass_name = alt_name != nullptr
181 ? alt_name
182 : OptimizationPassName(pass);
183 HOptimization* opt = nullptr;
184
185 switch (pass) {
186 //
187 // Analysis passes (kept in most recent for subsequent passes).
188 //
189 case OptimizationPass::kSideEffectsAnalysis:
190 opt = most_recent_side_effects = new (allocator) SideEffectsAnalysis(graph, pass_name);
191 break;
192 case OptimizationPass::kInductionVarAnalysis:
193 opt = most_recent_induction = new (allocator) HInductionVarAnalysis(graph, pass_name);
194 break;
195 //
196 // Passes that need prior analysis.
197 //
198 case OptimizationPass::kGlobalValueNumbering:
199 CHECK(most_recent_side_effects != nullptr);
200 opt = new (allocator) GVNOptimization(graph, *most_recent_side_effects, pass_name);
201 break;
202 case OptimizationPass::kInvariantCodeMotion:
203 CHECK(most_recent_side_effects != nullptr);
204 opt = new (allocator) LICM(graph, *most_recent_side_effects, stats, pass_name);
205 break;
206 case OptimizationPass::kLoopOptimization:
207 CHECK(most_recent_induction != nullptr);
208 opt = new (allocator) HLoopOptimization(
209 graph, *codegen, most_recent_induction, stats, pass_name);
210 break;
211 case OptimizationPass::kBoundsCheckElimination:
212 CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr);
213 opt = new (allocator) BoundsCheckElimination(
214 graph, *most_recent_side_effects, most_recent_induction, pass_name);
215 break;
216 case OptimizationPass::kLoadStoreElimination:
217 CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr);
218 opt = new (allocator) LoadStoreElimination(
219 graph, *most_recent_side_effects, stats, pass_name);
220 break;
221 //
222 // Regular passes.
223 //
224 case OptimizationPass::kConstantFolding:
225 opt = new (allocator) HConstantFolding(graph, pass_name);
226 break;
227 case OptimizationPass::kDeadCodeElimination:
228 opt = new (allocator) HDeadCodeElimination(graph, stats, pass_name);
229 break;
230 case OptimizationPass::kInliner: {
231 CodeItemDataAccessor accessor(*dex_compilation_unit.GetDexFile(),
232 dex_compilation_unit.GetCodeItem());
233 opt = new (allocator) HInliner(graph, // outer_graph
234 graph, // outermost_graph
235 codegen,
236 dex_compilation_unit, // outer_compilation_unit
237 dex_compilation_unit, // outermost_compilation_unit
238 stats,
239 accessor.RegistersSize(),
240 /* total_number_of_instructions= */ 0,
241 /* parent= */ nullptr,
242 /* depth= */ 0,
243 pass_name);
244 break;
245 }
246 case OptimizationPass::kSelectGenerator:
247 opt = new (allocator) HSelectGenerator(graph, stats, pass_name);
248 break;
249 case OptimizationPass::kInstructionSimplifier:
250 opt = new (allocator) InstructionSimplifier(graph, codegen, stats, pass_name);
251 break;
252 case OptimizationPass::kAggressiveInstructionSimplifier:
253 opt = new (allocator) InstructionSimplifier(graph,
254 codegen,
255 stats,
256 pass_name,
257 /* use_all_optimizations_ = */ true);
258 break;
259 case OptimizationPass::kCHAGuardOptimization:
260 opt = new (allocator) CHAGuardOptimization(graph, pass_name);
261 break;
262 case OptimizationPass::kCodeSinking:
263 opt = new (allocator) CodeSinking(graph, stats, pass_name);
264 break;
265 case OptimizationPass::kConstructorFenceRedundancyElimination:
266 opt = new (allocator) ConstructorFenceRedundancyElimination(graph, stats, pass_name);
267 break;
268 case OptimizationPass::kScheduling:
269 opt = new (allocator) HInstructionScheduling(
270 graph, codegen->GetCompilerOptions().GetInstructionSet(), codegen, pass_name);
271 break;
272 //
273 // Arch-specific passes.
274 //
275 #ifdef ART_ENABLE_CODEGEN_arm
276 case OptimizationPass::kInstructionSimplifierArm:
277 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
278 opt = new (allocator) arm::InstructionSimplifierArm(graph, stats);
279 break;
280 #endif
281 #ifdef ART_ENABLE_CODEGEN_arm64
282 case OptimizationPass::kInstructionSimplifierArm64:
283 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
284 opt = new (allocator) arm64::InstructionSimplifierArm64(graph, stats);
285 break;
286 #endif
287 #ifdef ART_ENABLE_CODEGEN_x86
288 case OptimizationPass::kPcRelativeFixupsX86:
289 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
290 opt = new (allocator) x86::PcRelativeFixups(graph, codegen, stats);
291 break;
292 case OptimizationPass::kX86MemoryOperandGeneration:
293 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
294 opt = new (allocator) x86::X86MemoryOperandGeneration(graph, codegen, stats);
295 break;
296 case OptimizationPass::kInstructionSimplifierX86:
297 opt = new (allocator) x86::InstructionSimplifierX86(graph, codegen, stats);
298 break;
299 #endif
300 #ifdef ART_ENABLE_CODEGEN_x86_64
301 case OptimizationPass::kInstructionSimplifierX86_64:
302 opt = new (allocator) x86_64::InstructionSimplifierX86_64(graph, codegen, stats);
303 break;
304 #endif
305 case OptimizationPass::kNone:
306 LOG(FATAL) << "kNone does not represent an actual pass";
307 UNREACHABLE();
308 } // switch
309
310 // Add each next optimization to result vector.
311 CHECK(opt != nullptr);
312 DCHECK_STREQ(pass_name, opt->GetPassName()); // Consistency check.
313 optimizations.push_back(opt);
314 }
315
316 return optimizations;
317 }
318
319 } // namespace art
320