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