• 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_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 "scheduler.h"
59  #include "select_generator.h"
60  #include "sharpening.h"
61  #include "side_effects_analysis.h"
62  #include "write_barrier_elimination.h"
63  
64  // Decide between default or alternative pass name.
65  
66  namespace art HIDDEN {
67  
OptimizationPassName(OptimizationPass pass)68  const char* OptimizationPassName(OptimizationPass pass) {
69    switch (pass) {
70      case OptimizationPass::kSideEffectsAnalysis:
71        return SideEffectsAnalysis::kSideEffectsAnalysisPassName;
72      case OptimizationPass::kInductionVarAnalysis:
73        return HInductionVarAnalysis::kInductionPassName;
74      case OptimizationPass::kGlobalValueNumbering:
75        return GVNOptimization::kGlobalValueNumberingPassName;
76      case OptimizationPass::kInvariantCodeMotion:
77        return LICM::kLoopInvariantCodeMotionPassName;
78      case OptimizationPass::kLoopOptimization:
79        return HLoopOptimization::kLoopOptimizationPassName;
80      case OptimizationPass::kBoundsCheckElimination:
81        return BoundsCheckElimination::kBoundsCheckEliminationPassName;
82      case OptimizationPass::kLoadStoreElimination:
83        return LoadStoreElimination::kLoadStoreEliminationPassName;
84      case OptimizationPass::kConstantFolding:
85        return HConstantFolding::kConstantFoldingPassName;
86      case OptimizationPass::kDeadCodeElimination:
87        return HDeadCodeElimination::kDeadCodeEliminationPassName;
88      case OptimizationPass::kInliner:
89        return HInliner::kInlinerPassName;
90      case OptimizationPass::kSelectGenerator:
91        return HSelectGenerator::kSelectGeneratorPassName;
92      case OptimizationPass::kAggressiveInstructionSimplifier:
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      case OptimizationPass::kWriteBarrierElimination:
104        return WriteBarrierElimination::kWBEPassName;
105  #ifdef ART_ENABLE_CODEGEN_arm
106      case OptimizationPass::kInstructionSimplifierArm:
107        return arm::InstructionSimplifierArm::kInstructionSimplifierArmPassName;
108      case OptimizationPass::kCriticalNativeAbiFixupArm:
109        return arm::CriticalNativeAbiFixupArm::kCriticalNativeAbiFixupArmPassName;
110  #endif
111  #ifdef ART_ENABLE_CODEGEN_arm64
112      case OptimizationPass::kInstructionSimplifierArm64:
113        return arm64::InstructionSimplifierArm64::kInstructionSimplifierArm64PassName;
114  #endif
115  #ifdef ART_ENABLE_CODEGEN_riscv64
116      case OptimizationPass::kCriticalNativeAbiFixupRiscv64:
117        return riscv64::CriticalNativeAbiFixupRiscv64::kCriticalNativeAbiFixupRiscv64PassName;
118      case OptimizationPass::kInstructionSimplifierRiscv64:
119        return riscv64::InstructionSimplifierRiscv64::kInstructionSimplifierRiscv64PassName;
120  #endif
121  #ifdef ART_ENABLE_CODEGEN_x86
122      case OptimizationPass::kPcRelativeFixupsX86:
123        return x86::PcRelativeFixups::kPcRelativeFixupsX86PassName;
124      case OptimizationPass::kInstructionSimplifierX86:
125        return x86::InstructionSimplifierX86::kInstructionSimplifierX86PassName;
126  #endif
127  #ifdef ART_ENABLE_CODEGEN_x86_64
128      case OptimizationPass::kInstructionSimplifierX86_64:
129        return x86_64::InstructionSimplifierX86_64::kInstructionSimplifierX86_64PassName;
130  #endif
131  #if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64)
132      case OptimizationPass::kX86MemoryOperandGeneration:
133        return x86::X86MemoryOperandGeneration::kX86MemoryOperandGenerationPassName;
134  #endif
135      case OptimizationPass::kNone:
136        LOG(FATAL) << "kNone does not represent an actual pass";
137        UNREACHABLE();
138    }
139  }
140  
141  #define X(x) if (pass_name == OptimizationPassName((x))) return (x)
142  
OptimizationPassByName(const std::string & pass_name)143  OptimizationPass OptimizationPassByName(const std::string& pass_name) {
144    X(OptimizationPass::kBoundsCheckElimination);
145    X(OptimizationPass::kCHAGuardOptimization);
146    X(OptimizationPass::kCodeSinking);
147    X(OptimizationPass::kConstantFolding);
148    X(OptimizationPass::kConstructorFenceRedundancyElimination);
149    X(OptimizationPass::kDeadCodeElimination);
150    X(OptimizationPass::kGlobalValueNumbering);
151    X(OptimizationPass::kInductionVarAnalysis);
152    X(OptimizationPass::kInliner);
153    X(OptimizationPass::kInstructionSimplifier);
154    X(OptimizationPass::kInvariantCodeMotion);
155    X(OptimizationPass::kLoadStoreElimination);
156    X(OptimizationPass::kLoopOptimization);
157    X(OptimizationPass::kScheduling);
158    X(OptimizationPass::kSelectGenerator);
159    X(OptimizationPass::kSideEffectsAnalysis);
160  #ifdef ART_ENABLE_CODEGEN_arm
161    X(OptimizationPass::kInstructionSimplifierArm);
162    X(OptimizationPass::kCriticalNativeAbiFixupArm);
163  #endif
164  #ifdef ART_ENABLE_CODEGEN_arm64
165    X(OptimizationPass::kInstructionSimplifierArm64);
166  #endif
167  #ifdef ART_ENABLE_CODEGEN_riscv64
168    X(OptimizationPass::kCriticalNativeAbiFixupRiscv64);
169    X(OptimizationPass::kInstructionSimplifierRiscv64);
170  #endif
171  #ifdef ART_ENABLE_CODEGEN_x86
172    X(OptimizationPass::kPcRelativeFixupsX86);
173    X(OptimizationPass::kX86MemoryOperandGeneration);
174  #endif
175    LOG(FATAL) << "Cannot find optimization " << pass_name;
176    UNREACHABLE();
177  }
178  
179  #undef X
180  
ConstructOptimizations(const OptimizationDef definitions[],size_t length,ArenaAllocator * allocator,HGraph * graph,OptimizingCompilerStats * stats,CodeGenerator * codegen,const DexCompilationUnit & dex_compilation_unit)181  ArenaVector<HOptimization*> ConstructOptimizations(
182      const OptimizationDef definitions[],
183      size_t length,
184      ArenaAllocator* allocator,
185      HGraph* graph,
186      OptimizingCompilerStats* stats,
187      CodeGenerator* codegen,
188      const DexCompilationUnit& dex_compilation_unit) {
189    ArenaVector<HOptimization*> optimizations(allocator->Adapter());
190  
191    // Some optimizations require SideEffectsAnalysis or HInductionVarAnalysis
192    // instances. This method uses the nearest instance preceeding it in the pass
193    // name list or fails fatally if no such analysis can be found.
194    SideEffectsAnalysis* most_recent_side_effects = nullptr;
195    HInductionVarAnalysis* most_recent_induction = nullptr;
196  
197    // Loop over the requested optimizations.
198    for (size_t i = 0; i < length; i++) {
199      OptimizationPass pass = definitions[i].pass;
200      const char* alt_name = definitions[i].pass_name;
201      const char* pass_name = alt_name != nullptr
202          ? alt_name
203          : OptimizationPassName(pass);
204      HOptimization* opt = nullptr;
205  
206      switch (pass) {
207        //
208        // Analysis passes (kept in most recent for subsequent passes).
209        //
210        case OptimizationPass::kSideEffectsAnalysis:
211          opt = most_recent_side_effects = new (allocator) SideEffectsAnalysis(graph, pass_name);
212          break;
213        case OptimizationPass::kInductionVarAnalysis:
214          opt = most_recent_induction =
215              new (allocator) HInductionVarAnalysis(graph, stats, 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, 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        //
239        // Regular passes.
240        //
241        case OptimizationPass::kConstantFolding:
242          opt = new (allocator) HConstantFolding(graph, stats, pass_name);
243          break;
244        case OptimizationPass::kDeadCodeElimination:
245          opt = new (allocator) HDeadCodeElimination(graph, stats, pass_name);
246          break;
247        case OptimizationPass::kInliner: {
248          CodeItemDataAccessor accessor(*dex_compilation_unit.GetDexFile(),
249                                        dex_compilation_unit.GetCodeItem());
250          opt = new (allocator) HInliner(graph,                   // outer_graph
251                                         graph,                   // outermost_graph
252                                         codegen,
253                                         dex_compilation_unit,    // outer_compilation_unit
254                                         dex_compilation_unit,    // outermost_compilation_unit
255                                         stats,
256                                         accessor.RegistersSize(),
257                                         /* total_number_of_instructions= */ 0,
258                                         /* parent= */ nullptr,
259                                         /* caller_environment= */ nullptr,
260                                         /* depth= */ 0,
261                                         /* try_catch_inlining_allowed= */ true,
262                                         pass_name);
263          break;
264        }
265        case OptimizationPass::kSelectGenerator:
266          opt = new (allocator) HSelectGenerator(graph, stats, pass_name);
267          break;
268        case OptimizationPass::kInstructionSimplifier:
269          opt = new (allocator) InstructionSimplifier(graph, codegen, stats, pass_name);
270          break;
271        case OptimizationPass::kAggressiveInstructionSimplifier:
272          opt = new (allocator) InstructionSimplifier(graph,
273                                                      codegen,
274                                                      stats,
275                                                      pass_name,
276                                                      /* use_all_optimizations_ = */ true);
277          break;
278        case OptimizationPass::kCHAGuardOptimization:
279          opt = new (allocator) CHAGuardOptimization(graph, pass_name);
280          break;
281        case OptimizationPass::kCodeSinking:
282          opt = new (allocator) CodeSinking(graph, stats, pass_name);
283          break;
284        case OptimizationPass::kConstructorFenceRedundancyElimination:
285          opt = new (allocator) ConstructorFenceRedundancyElimination(graph, stats, pass_name);
286          break;
287        case OptimizationPass::kLoadStoreElimination:
288          opt = new (allocator) LoadStoreElimination(graph, stats, pass_name);
289          break;
290        case OptimizationPass::kWriteBarrierElimination:
291          opt = new (allocator) WriteBarrierElimination(graph, stats, pass_name);
292          break;
293        case OptimizationPass::kScheduling:
294          opt = new (allocator) HInstructionScheduling(
295              graph, codegen->GetCompilerOptions().GetInstructionSet(), codegen, pass_name);
296          break;
297        //
298        // Arch-specific passes.
299        //
300  #ifdef ART_ENABLE_CODEGEN_arm
301        case OptimizationPass::kInstructionSimplifierArm:
302          DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
303          opt = new (allocator) arm::InstructionSimplifierArm(graph, codegen, stats);
304          break;
305        case OptimizationPass::kCriticalNativeAbiFixupArm:
306          DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
307          opt = new (allocator) arm::CriticalNativeAbiFixupArm(graph, stats);
308          break;
309  #endif
310  #ifdef ART_ENABLE_CODEGEN_arm64
311        case OptimizationPass::kInstructionSimplifierArm64:
312          DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
313          opt = new (allocator) arm64::InstructionSimplifierArm64(graph, codegen, stats);
314          break;
315  #endif
316  #ifdef ART_ENABLE_CODEGEN_riscv64
317        case OptimizationPass::kCriticalNativeAbiFixupRiscv64:
318          DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
319          opt = new (allocator) riscv64::CriticalNativeAbiFixupRiscv64(graph, stats);
320          break;
321        case OptimizationPass::kInstructionSimplifierRiscv64:
322          DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
323          opt = new (allocator) riscv64::InstructionSimplifierRiscv64(graph, stats);
324          break;
325  #endif
326  #ifdef ART_ENABLE_CODEGEN_x86
327        case OptimizationPass::kPcRelativeFixupsX86:
328          DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
329          opt = new (allocator) x86::PcRelativeFixups(graph, codegen, stats);
330          break;
331        case OptimizationPass::kX86MemoryOperandGeneration:
332          DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
333          opt = new (allocator) x86::X86MemoryOperandGeneration(graph, codegen, stats);
334          break;
335        case OptimizationPass::kInstructionSimplifierX86:
336          opt = new (allocator) x86::InstructionSimplifierX86(graph, codegen, stats);
337          break;
338  #endif
339  #ifdef ART_ENABLE_CODEGEN_x86_64
340        case OptimizationPass::kInstructionSimplifierX86_64:
341          opt = new (allocator) x86_64::InstructionSimplifierX86_64(graph, codegen, stats);
342          break;
343  #endif
344        case OptimizationPass::kNone:
345          LOG(FATAL) << "kNone does not represent an actual pass";
346          UNREACHABLE();
347      }  // switch
348  
349      // Add each next optimization to result vector.
350      CHECK(opt != nullptr);
351      DCHECK_STREQ(pass_name, opt->GetPassName());  // Consistency check.
352      optimizations.push_back(opt);
353    }
354  
355    return optimizations;
356  }
357  
358  }  // namespace art
359