blob: ec3b8c49046943d61dcb37524903b5e2429426eb [file] [log] [blame]
Roland Levillain75be2832014-10-17 17:02:00 +01001/*
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
Aart Bik2ca10eb2017-11-15 15:17:53 -080019#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
Aart Bik2ca10eb2017-11-15 15:17:53 -080025#ifdef ART_ENABLE_CODEGEN_x86
26#include "pc_relative_fixups_x86.h"
Shalini Salomi Bodapatidd121f62018-10-26 15:03:53 +053027#include "instruction_simplifier_x86.h"
Aart Bik2ca10eb2017-11-15 15:17:53 -080028#endif
29#if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64)
30#include "x86_memory_gen.h"
31#endif
Shalini Salomi Bodapatidd121f62018-10-26 15:03:53 +053032#ifdef ART_ENABLE_CODEGEN_x86_64
33#include "instruction_simplifier_x86_64.h"
34#endif
Aart Bik2ca10eb2017-11-15 15:17:53 -080035
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"
David Sehr9e734c72018-01-04 17:56:19 -080042#include "dex/code_item_accessors-inl.h"
Vladimir Markoa0431112018-06-25 09:32:54 +010043#include "driver/compiler_options.h"
Aart Bik2ca10eb2017-11-15 15:17:53 -080044#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"
Aart Bik2ca10eb2017-11-15 15:17:53 -080051#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
Vladimir Marko0a516052019-10-14 13:00:44 +000060namespace art {
Aart Bik2ca10eb2017-11-15 15:17:53 -080061
62const char* OptimizationPassName(OptimizationPass pass) {
63 switch (pass) {
64 case OptimizationPass::kSideEffectsAnalysis:
65 return SideEffectsAnalysis::kSideEffectsAnalysisPassName;
66 case OptimizationPass::kInductionVarAnalysis:
67 return HInductionVarAnalysis::kInductionPassName;
Aart Bik2ca10eb2017-11-15 15:17:53 -080068 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;
Aart Bik2ca10eb2017-11-15 15:17:53 -080084 case OptimizationPass::kSelectGenerator:
85 return HSelectGenerator::kSelectGeneratorPassName;
86 case OptimizationPass::kInstructionSimplifier:
87 return InstructionSimplifier::kInstructionSimplifierPassName;
Aart Bik2ca10eb2017-11-15 15:17:53 -080088 case OptimizationPass::kCHAGuardOptimization:
89 return CHAGuardOptimization::kCHAGuardOptimizationPassName;
90 case OptimizationPass::kCodeSinking:
91 return CodeSinking::kCodeSinkingPassName;
92 case OptimizationPass::kConstructorFenceRedundancyElimination:
93 return ConstructorFenceRedundancyElimination::kCFREPassName;
94 case OptimizationPass::kScheduling:
95 return HInstructionScheduling::kInstructionSchedulingPassName;
96#ifdef ART_ENABLE_CODEGEN_arm
97 case OptimizationPass::kInstructionSimplifierArm:
98 return arm::InstructionSimplifierArm::kInstructionSimplifierArmPassName;
99#endif
100#ifdef ART_ENABLE_CODEGEN_arm64
101 case OptimizationPass::kInstructionSimplifierArm64:
102 return arm64::InstructionSimplifierArm64::kInstructionSimplifierArm64PassName;
103#endif
Aart Bik2ca10eb2017-11-15 15:17:53 -0800104#ifdef ART_ENABLE_CODEGEN_x86
105 case OptimizationPass::kPcRelativeFixupsX86:
106 return x86::PcRelativeFixups::kPcRelativeFixupsX86PassName;
Shalini Salomi Bodapatidd121f62018-10-26 15:03:53 +0530107 case OptimizationPass::kInstructionSimplifierX86:
108 return x86::InstructionSimplifierX86::kInstructionSimplifierX86PassName;
109#endif
110#ifdef ART_ENABLE_CODEGEN_x86_64
111 case OptimizationPass::kInstructionSimplifierX86_64:
112 return x86_64::InstructionSimplifierX86_64::kInstructionSimplifierX86_64PassName;
Aart Bik2ca10eb2017-11-15 15:17:53 -0800113#endif
114#if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64)
115 case OptimizationPass::kX86MemoryOperandGeneration:
116 return x86::X86MemoryOperandGeneration::kX86MemoryOperandGenerationPassName;
117#endif
Aart Bik2e148682018-04-18 16:11:12 -0700118 case OptimizationPass::kNone:
119 LOG(FATAL) << "kNone does not represent an actual pass";
120 UNREACHABLE();
Aart Bik2ca10eb2017-11-15 15:17:53 -0800121 }
122}
123
Aart Bik2e148682018-04-18 16:11:12 -0700124#define X(x) if (pass_name == OptimizationPassName((x))) return (x)
Aart Bik2ca10eb2017-11-15 15:17:53 -0800125
Aart Bik2e148682018-04-18 16:11:12 -0700126OptimizationPass OptimizationPassByName(const std::string& pass_name) {
Aart Bik2ca10eb2017-11-15 15:17:53 -0800127 X(OptimizationPass::kBoundsCheckElimination);
128 X(OptimizationPass::kCHAGuardOptimization);
129 X(OptimizationPass::kCodeSinking);
130 X(OptimizationPass::kConstantFolding);
131 X(OptimizationPass::kConstructorFenceRedundancyElimination);
132 X(OptimizationPass::kDeadCodeElimination);
133 X(OptimizationPass::kGlobalValueNumbering);
134 X(OptimizationPass::kInductionVarAnalysis);
135 X(OptimizationPass::kInliner);
136 X(OptimizationPass::kInstructionSimplifier);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800137 X(OptimizationPass::kInvariantCodeMotion);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800138 X(OptimizationPass::kLoadStoreElimination);
139 X(OptimizationPass::kLoopOptimization);
140 X(OptimizationPass::kScheduling);
141 X(OptimizationPass::kSelectGenerator);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800142 X(OptimizationPass::kSideEffectsAnalysis);
143#ifdef ART_ENABLE_CODEGEN_arm
144 X(OptimizationPass::kInstructionSimplifierArm);
145#endif
146#ifdef ART_ENABLE_CODEGEN_arm64
147 X(OptimizationPass::kInstructionSimplifierArm64);
148#endif
Aart Bik2ca10eb2017-11-15 15:17:53 -0800149#ifdef ART_ENABLE_CODEGEN_x86
150 X(OptimizationPass::kPcRelativeFixupsX86);
151 X(OptimizationPass::kX86MemoryOperandGeneration);
152#endif
Aart Bik2e148682018-04-18 16:11:12 -0700153 LOG(FATAL) << "Cannot find optimization " << pass_name;
Aart Bik2ca10eb2017-11-15 15:17:53 -0800154 UNREACHABLE();
155}
156
157#undef X
158
159ArenaVector<HOptimization*> ConstructOptimizations(
160 const OptimizationDef definitions[],
161 size_t length,
162 ArenaAllocator* allocator,
163 HGraph* graph,
164 OptimizingCompilerStats* stats,
165 CodeGenerator* codegen,
Vladimir Marko02ca05a2020-05-12 13:58:51 +0100166 const DexCompilationUnit& dex_compilation_unit) {
Aart Bik2ca10eb2017-11-15 15:17:53 -0800167 ArenaVector<HOptimization*> optimizations(allocator->Adapter());
168
169 // Some optimizations require SideEffectsAnalysis or HInductionVarAnalysis
170 // instances. This method uses the nearest instance preceeding it in the pass
171 // name list or fails fatally if no such analysis can be found.
172 SideEffectsAnalysis* most_recent_side_effects = nullptr;
173 HInductionVarAnalysis* most_recent_induction = nullptr;
Aart Bik2ca10eb2017-11-15 15:17:53 -0800174
175 // Loop over the requested optimizations.
176 for (size_t i = 0; i < length; i++) {
Aart Bik2e148682018-04-18 16:11:12 -0700177 OptimizationPass pass = definitions[i].pass;
178 const char* alt_name = definitions[i].pass_name;
179 const char* pass_name = alt_name != nullptr
Aart Bik2ca10eb2017-11-15 15:17:53 -0800180 ? alt_name
181 : OptimizationPassName(pass);
182 HOptimization* opt = nullptr;
183
184 switch (pass) {
185 //
186 // Analysis passes (kept in most recent for subsequent passes).
187 //
188 case OptimizationPass::kSideEffectsAnalysis:
Aart Bik2e148682018-04-18 16:11:12 -0700189 opt = most_recent_side_effects = new (allocator) SideEffectsAnalysis(graph, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800190 break;
191 case OptimizationPass::kInductionVarAnalysis:
Aart Bik2e148682018-04-18 16:11:12 -0700192 opt = most_recent_induction = new (allocator) HInductionVarAnalysis(graph, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800193 break;
Aart Bik2ca10eb2017-11-15 15:17:53 -0800194 //
195 // Passes that need prior analysis.
196 //
197 case OptimizationPass::kGlobalValueNumbering:
198 CHECK(most_recent_side_effects != nullptr);
Aart Bik2e148682018-04-18 16:11:12 -0700199 opt = new (allocator) GVNOptimization(graph, *most_recent_side_effects, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800200 break;
201 case OptimizationPass::kInvariantCodeMotion:
202 CHECK(most_recent_side_effects != nullptr);
Aart Bik2e148682018-04-18 16:11:12 -0700203 opt = new (allocator) LICM(graph, *most_recent_side_effects, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800204 break;
205 case OptimizationPass::kLoopOptimization:
206 CHECK(most_recent_induction != nullptr);
Aart Bik2e148682018-04-18 16:11:12 -0700207 opt = new (allocator) HLoopOptimization(
Artem Serovc8150b52019-07-31 18:28:00 +0100208 graph, *codegen, most_recent_induction, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800209 break;
210 case OptimizationPass::kBoundsCheckElimination:
211 CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr);
212 opt = new (allocator) BoundsCheckElimination(
Aart Bik2e148682018-04-18 16:11:12 -0700213 graph, *most_recent_side_effects, most_recent_induction, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800214 break;
215 case OptimizationPass::kLoadStoreElimination:
216 CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr);
217 opt = new (allocator) LoadStoreElimination(
Vladimir Markoef898422020-06-08 10:26:06 +0100218 graph, *most_recent_side_effects, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800219 break;
220 //
221 // Regular passes.
222 //
223 case OptimizationPass::kConstantFolding:
Aart Bik2e148682018-04-18 16:11:12 -0700224 opt = new (allocator) HConstantFolding(graph, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800225 break;
226 case OptimizationPass::kDeadCodeElimination:
Aart Bik2e148682018-04-18 16:11:12 -0700227 opt = new (allocator) HDeadCodeElimination(graph, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800228 break;
229 case OptimizationPass::kInliner: {
Mathieu Chartier698ebbc2018-01-05 11:00:42 -0800230 CodeItemDataAccessor accessor(*dex_compilation_unit.GetDexFile(),
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800231 dex_compilation_unit.GetCodeItem());
Aart Bik2ca10eb2017-11-15 15:17:53 -0800232 opt = new (allocator) HInliner(graph, // outer_graph
233 graph, // outermost_graph
234 codegen,
235 dex_compilation_unit, // outer_compilation_unit
236 dex_compilation_unit, // outermost_compilation_unit
Aart Bik2ca10eb2017-11-15 15:17:53 -0800237 stats,
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800238 accessor.RegistersSize(),
Andreas Gampe3db70682018-12-26 15:12:03 -0800239 /* total_number_of_instructions= */ 0,
240 /* parent= */ nullptr,
241 /* depth= */ 0,
Aart Bik2e148682018-04-18 16:11:12 -0700242 pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800243 break;
244 }
Aart Bik2ca10eb2017-11-15 15:17:53 -0800245 case OptimizationPass::kSelectGenerator:
Vladimir Marko02ca05a2020-05-12 13:58:51 +0100246 opt = new (allocator) HSelectGenerator(graph, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800247 break;
248 case OptimizationPass::kInstructionSimplifier:
Vladimir Markobb089b62018-06-28 17:30:16 +0100249 opt = new (allocator) InstructionSimplifier(graph, codegen, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800250 break;
Aart Bik2ca10eb2017-11-15 15:17:53 -0800251 case OptimizationPass::kCHAGuardOptimization:
Aart Bik2e148682018-04-18 16:11:12 -0700252 opt = new (allocator) CHAGuardOptimization(graph, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800253 break;
254 case OptimizationPass::kCodeSinking:
Aart Bik2e148682018-04-18 16:11:12 -0700255 opt = new (allocator) CodeSinking(graph, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800256 break;
257 case OptimizationPass::kConstructorFenceRedundancyElimination:
Aart Bik2e148682018-04-18 16:11:12 -0700258 opt = new (allocator) ConstructorFenceRedundancyElimination(graph, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800259 break;
260 case OptimizationPass::kScheduling:
261 opt = new (allocator) HInstructionScheduling(
Vladimir Markoa0431112018-06-25 09:32:54 +0100262 graph, codegen->GetCompilerOptions().GetInstructionSet(), codegen, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800263 break;
264 //
265 // Arch-specific passes.
266 //
267#ifdef ART_ENABLE_CODEGEN_arm
268 case OptimizationPass::kInstructionSimplifierArm:
269 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
270 opt = new (allocator) arm::InstructionSimplifierArm(graph, stats);
271 break;
272#endif
273#ifdef ART_ENABLE_CODEGEN_arm64
274 case OptimizationPass::kInstructionSimplifierArm64:
275 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
276 opt = new (allocator) arm64::InstructionSimplifierArm64(graph, stats);
277 break;
278#endif
Aart Bik2ca10eb2017-11-15 15:17:53 -0800279#ifdef ART_ENABLE_CODEGEN_x86
280 case OptimizationPass::kPcRelativeFixupsX86:
281 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
282 opt = new (allocator) x86::PcRelativeFixups(graph, codegen, stats);
283 break;
284 case OptimizationPass::kX86MemoryOperandGeneration:
285 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
286 opt = new (allocator) x86::X86MemoryOperandGeneration(graph, codegen, stats);
287 break;
Shalini Salomi Bodapatidd121f62018-10-26 15:03:53 +0530288 case OptimizationPass::kInstructionSimplifierX86:
289 opt = new (allocator) x86::InstructionSimplifierX86(graph, codegen, stats);
290 break;
291#endif
292#ifdef ART_ENABLE_CODEGEN_x86_64
293 case OptimizationPass::kInstructionSimplifierX86_64:
294 opt = new (allocator) x86_64::InstructionSimplifierX86_64(graph, codegen, stats);
295 break;
Aart Bik2ca10eb2017-11-15 15:17:53 -0800296#endif
Aart Bik2e148682018-04-18 16:11:12 -0700297 case OptimizationPass::kNone:
298 LOG(FATAL) << "kNone does not represent an actual pass";
299 UNREACHABLE();
Aart Bik2ca10eb2017-11-15 15:17:53 -0800300 } // switch
301
302 // Add each next optimization to result vector.
303 CHECK(opt != nullptr);
Aart Bik2e148682018-04-18 16:11:12 -0700304 DCHECK_STREQ(pass_name, opt->GetPassName()); // sanity
Aart Bik2ca10eb2017-11-15 15:17:53 -0800305 optimizations.push_back(opt);
306 }
307
308 return optimizations;
309}
310
Roland Levillain75be2832014-10-17 17:02:00 +0100311} // namespace art