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