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