blob: 4b0941b4ffe84dcc396ae219c973cd882ba8af48 [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
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#endif
32#if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64)
33#include "x86_memory_gen.h"
34#endif
35
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"
51#include "load_store_analysis.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
59// Decide between default or alternative pass name.
60
Roland Levillain75be2832014-10-17 17:02:00 +010061namespace art {
Aart Bik2ca10eb2017-11-15 15:17:53 -080062
63const char* OptimizationPassName(OptimizationPass pass) {
64 switch (pass) {
65 case OptimizationPass::kSideEffectsAnalysis:
66 return SideEffectsAnalysis::kSideEffectsAnalysisPassName;
67 case OptimizationPass::kInductionVarAnalysis:
68 return HInductionVarAnalysis::kInductionPassName;
69 case OptimizationPass::kLoadStoreAnalysis:
70 return LoadStoreAnalysis::kLoadStoreAnalysisPassName;
71 case OptimizationPass::kGlobalValueNumbering:
72 return GVNOptimization::kGlobalValueNumberingPassName;
73 case OptimizationPass::kInvariantCodeMotion:
74 return LICM::kLoopInvariantCodeMotionPassName;
75 case OptimizationPass::kLoopOptimization:
76 return HLoopOptimization::kLoopOptimizationPassName;
77 case OptimizationPass::kBoundsCheckElimination:
78 return BoundsCheckElimination::kBoundsCheckEliminationPassName;
79 case OptimizationPass::kLoadStoreElimination:
80 return LoadStoreElimination::kLoadStoreEliminationPassName;
81 case OptimizationPass::kConstantFolding:
82 return HConstantFolding::kConstantFoldingPassName;
83 case OptimizationPass::kDeadCodeElimination:
84 return HDeadCodeElimination::kDeadCodeEliminationPassName;
85 case OptimizationPass::kInliner:
86 return HInliner::kInlinerPassName;
Aart Bik2ca10eb2017-11-15 15:17:53 -080087 case OptimizationPass::kSelectGenerator:
88 return HSelectGenerator::kSelectGeneratorPassName;
89 case OptimizationPass::kInstructionSimplifier:
90 return InstructionSimplifier::kInstructionSimplifierPassName;
Aart Bik2ca10eb2017-11-15 15:17:53 -080091 case OptimizationPass::kCHAGuardOptimization:
92 return CHAGuardOptimization::kCHAGuardOptimizationPassName;
93 case OptimizationPass::kCodeSinking:
94 return CodeSinking::kCodeSinkingPassName;
95 case OptimizationPass::kConstructorFenceRedundancyElimination:
96 return ConstructorFenceRedundancyElimination::kCFREPassName;
97 case OptimizationPass::kScheduling:
98 return HInstructionScheduling::kInstructionSchedulingPassName;
99#ifdef ART_ENABLE_CODEGEN_arm
100 case OptimizationPass::kInstructionSimplifierArm:
101 return arm::InstructionSimplifierArm::kInstructionSimplifierArmPassName;
102#endif
103#ifdef ART_ENABLE_CODEGEN_arm64
104 case OptimizationPass::kInstructionSimplifierArm64:
105 return arm64::InstructionSimplifierArm64::kInstructionSimplifierArm64PassName;
106#endif
107#ifdef ART_ENABLE_CODEGEN_mips
108 case OptimizationPass::kPcRelativeFixupsMips:
109 return mips::PcRelativeFixups::kPcRelativeFixupsMipsPassName;
110 case OptimizationPass::kInstructionSimplifierMips:
111 return mips::InstructionSimplifierMips::kInstructionSimplifierMipsPassName;
112#endif
113#ifdef ART_ENABLE_CODEGEN_x86
114 case OptimizationPass::kPcRelativeFixupsX86:
115 return x86::PcRelativeFixups::kPcRelativeFixupsX86PassName;
116#endif
117#if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64)
118 case OptimizationPass::kX86MemoryOperandGeneration:
119 return x86::X86MemoryOperandGeneration::kX86MemoryOperandGenerationPassName;
120#endif
Aart Bik2e148682018-04-18 16:11:12 -0700121 case OptimizationPass::kNone:
122 LOG(FATAL) << "kNone does not represent an actual pass";
123 UNREACHABLE();
Aart Bik2ca10eb2017-11-15 15:17:53 -0800124 }
125}
126
Aart Bik2e148682018-04-18 16:11:12 -0700127#define X(x) if (pass_name == OptimizationPassName((x))) return (x)
Aart Bik2ca10eb2017-11-15 15:17:53 -0800128
Aart Bik2e148682018-04-18 16:11:12 -0700129OptimizationPass OptimizationPassByName(const std::string& pass_name) {
Aart Bik2ca10eb2017-11-15 15:17:53 -0800130 X(OptimizationPass::kBoundsCheckElimination);
131 X(OptimizationPass::kCHAGuardOptimization);
132 X(OptimizationPass::kCodeSinking);
133 X(OptimizationPass::kConstantFolding);
134 X(OptimizationPass::kConstructorFenceRedundancyElimination);
135 X(OptimizationPass::kDeadCodeElimination);
136 X(OptimizationPass::kGlobalValueNumbering);
137 X(OptimizationPass::kInductionVarAnalysis);
138 X(OptimizationPass::kInliner);
139 X(OptimizationPass::kInstructionSimplifier);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800140 X(OptimizationPass::kInvariantCodeMotion);
141 X(OptimizationPass::kLoadStoreAnalysis);
142 X(OptimizationPass::kLoadStoreElimination);
143 X(OptimizationPass::kLoopOptimization);
144 X(OptimizationPass::kScheduling);
145 X(OptimizationPass::kSelectGenerator);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800146 X(OptimizationPass::kSideEffectsAnalysis);
147#ifdef ART_ENABLE_CODEGEN_arm
148 X(OptimizationPass::kInstructionSimplifierArm);
149#endif
150#ifdef ART_ENABLE_CODEGEN_arm64
151 X(OptimizationPass::kInstructionSimplifierArm64);
152#endif
153#ifdef ART_ENABLE_CODEGEN_mips
154 X(OptimizationPass::kPcRelativeFixupsMips);
155 X(OptimizationPass::kInstructionSimplifierMips);
156#endif
157#ifdef ART_ENABLE_CODEGEN_x86
158 X(OptimizationPass::kPcRelativeFixupsX86);
159 X(OptimizationPass::kX86MemoryOperandGeneration);
160#endif
Aart Bik2e148682018-04-18 16:11:12 -0700161 LOG(FATAL) << "Cannot find optimization " << pass_name;
Aart Bik2ca10eb2017-11-15 15:17:53 -0800162 UNREACHABLE();
163}
164
165#undef X
166
167ArenaVector<HOptimization*> ConstructOptimizations(
168 const OptimizationDef definitions[],
169 size_t length,
170 ArenaAllocator* allocator,
171 HGraph* graph,
172 OptimizingCompilerStats* stats,
173 CodeGenerator* codegen,
174 CompilerDriver* driver,
175 const DexCompilationUnit& dex_compilation_unit,
176 VariableSizedHandleScope* handles) {
177 ArenaVector<HOptimization*> optimizations(allocator->Adapter());
178
179 // Some optimizations require SideEffectsAnalysis or HInductionVarAnalysis
180 // instances. This method uses the nearest instance preceeding it in the pass
181 // name list or fails fatally if no such analysis can be found.
182 SideEffectsAnalysis* most_recent_side_effects = nullptr;
183 HInductionVarAnalysis* most_recent_induction = nullptr;
184 LoadStoreAnalysis* most_recent_lsa = nullptr;
185
186 // Loop over the requested optimizations.
187 for (size_t i = 0; i < length; i++) {
Aart Bik2e148682018-04-18 16:11:12 -0700188 OptimizationPass pass = definitions[i].pass;
189 const char* alt_name = definitions[i].pass_name;
190 const char* pass_name = alt_name != nullptr
Aart Bik2ca10eb2017-11-15 15:17:53 -0800191 ? alt_name
192 : OptimizationPassName(pass);
193 HOptimization* opt = nullptr;
194
195 switch (pass) {
196 //
197 // Analysis passes (kept in most recent for subsequent passes).
198 //
199 case OptimizationPass::kSideEffectsAnalysis:
Aart Bik2e148682018-04-18 16:11:12 -0700200 opt = most_recent_side_effects = new (allocator) SideEffectsAnalysis(graph, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800201 break;
202 case OptimizationPass::kInductionVarAnalysis:
Aart Bik2e148682018-04-18 16:11:12 -0700203 opt = most_recent_induction = new (allocator) HInductionVarAnalysis(graph, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800204 break;
205 case OptimizationPass::kLoadStoreAnalysis:
Aart Bik2e148682018-04-18 16:11:12 -0700206 opt = most_recent_lsa = new (allocator) LoadStoreAnalysis(graph, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800207 break;
208 //
209 // Passes that need prior analysis.
210 //
211 case OptimizationPass::kGlobalValueNumbering:
212 CHECK(most_recent_side_effects != nullptr);
Aart Bik2e148682018-04-18 16:11:12 -0700213 opt = new (allocator) GVNOptimization(graph, *most_recent_side_effects, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800214 break;
215 case OptimizationPass::kInvariantCodeMotion:
216 CHECK(most_recent_side_effects != nullptr);
Aart Bik2e148682018-04-18 16:11:12 -0700217 opt = new (allocator) LICM(graph, *most_recent_side_effects, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800218 break;
219 case OptimizationPass::kLoopOptimization:
220 CHECK(most_recent_induction != nullptr);
Aart Bik2e148682018-04-18 16:11:12 -0700221 opt = new (allocator) HLoopOptimization(
Vladimir Markoa0431112018-06-25 09:32:54 +0100222 graph, &codegen->GetCompilerOptions(), most_recent_induction, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800223 break;
224 case OptimizationPass::kBoundsCheckElimination:
225 CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr);
226 opt = new (allocator) BoundsCheckElimination(
Aart Bik2e148682018-04-18 16:11:12 -0700227 graph, *most_recent_side_effects, most_recent_induction, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800228 break;
229 case OptimizationPass::kLoadStoreElimination:
230 CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr);
231 opt = new (allocator) LoadStoreElimination(
Aart Bik2e148682018-04-18 16:11:12 -0700232 graph, *most_recent_side_effects, *most_recent_lsa, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800233 break;
234 //
235 // Regular passes.
236 //
237 case OptimizationPass::kConstantFolding:
Aart Bik2e148682018-04-18 16:11:12 -0700238 opt = new (allocator) HConstantFolding(graph, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800239 break;
240 case OptimizationPass::kDeadCodeElimination:
Aart Bik2e148682018-04-18 16:11:12 -0700241 opt = new (allocator) HDeadCodeElimination(graph, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800242 break;
243 case OptimizationPass::kInliner: {
Mathieu Chartier698ebbc2018-01-05 11:00:42 -0800244 CodeItemDataAccessor accessor(*dex_compilation_unit.GetDexFile(),
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800245 dex_compilation_unit.GetCodeItem());
Aart Bik2ca10eb2017-11-15 15:17:53 -0800246 opt = new (allocator) HInliner(graph, // outer_graph
247 graph, // outermost_graph
248 codegen,
249 dex_compilation_unit, // outer_compilation_unit
250 dex_compilation_unit, // outermost_compilation_unit
251 driver,
252 handles,
253 stats,
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800254 accessor.RegistersSize(),
Aart Bik2ca10eb2017-11-15 15:17:53 -0800255 /* total_number_of_instructions */ 0,
256 /* parent */ nullptr,
257 /* depth */ 0,
Aart Bik2e148682018-04-18 16:11:12 -0700258 pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800259 break;
260 }
Aart Bik2ca10eb2017-11-15 15:17:53 -0800261 case OptimizationPass::kSelectGenerator:
Aart Bik2e148682018-04-18 16:11:12 -0700262 opt = new (allocator) HSelectGenerator(graph, handles, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800263 break;
264 case OptimizationPass::kInstructionSimplifier:
Vladimir Markobb089b62018-06-28 17:30:16 +0100265 opt = new (allocator) InstructionSimplifier(graph, codegen, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800266 break;
Aart Bik2ca10eb2017-11-15 15:17:53 -0800267 case OptimizationPass::kCHAGuardOptimization:
Aart Bik2e148682018-04-18 16:11:12 -0700268 opt = new (allocator) CHAGuardOptimization(graph, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800269 break;
270 case OptimizationPass::kCodeSinking:
Aart Bik2e148682018-04-18 16:11:12 -0700271 opt = new (allocator) CodeSinking(graph, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800272 break;
273 case OptimizationPass::kConstructorFenceRedundancyElimination:
Aart Bik2e148682018-04-18 16:11:12 -0700274 opt = new (allocator) ConstructorFenceRedundancyElimination(graph, stats, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800275 break;
276 case OptimizationPass::kScheduling:
277 opt = new (allocator) HInstructionScheduling(
Vladimir Markoa0431112018-06-25 09:32:54 +0100278 graph, codegen->GetCompilerOptions().GetInstructionSet(), codegen, pass_name);
Aart Bik2ca10eb2017-11-15 15:17:53 -0800279 break;
280 //
281 // Arch-specific passes.
282 //
283#ifdef ART_ENABLE_CODEGEN_arm
284 case OptimizationPass::kInstructionSimplifierArm:
285 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
286 opt = new (allocator) arm::InstructionSimplifierArm(graph, stats);
287 break;
288#endif
289#ifdef ART_ENABLE_CODEGEN_arm64
290 case OptimizationPass::kInstructionSimplifierArm64:
291 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
292 opt = new (allocator) arm64::InstructionSimplifierArm64(graph, stats);
293 break;
294#endif
295#ifdef ART_ENABLE_CODEGEN_mips
296 case OptimizationPass::kPcRelativeFixupsMips:
297 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
298 opt = new (allocator) mips::PcRelativeFixups(graph, codegen, stats);
299 break;
300 case OptimizationPass::kInstructionSimplifierMips:
301 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
302 opt = new (allocator) mips::InstructionSimplifierMips(graph, codegen, stats);
303 break;
304#endif
305#ifdef ART_ENABLE_CODEGEN_x86
306 case OptimizationPass::kPcRelativeFixupsX86:
307 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
308 opt = new (allocator) x86::PcRelativeFixups(graph, codegen, stats);
309 break;
310 case OptimizationPass::kX86MemoryOperandGeneration:
311 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name";
312 opt = new (allocator) x86::X86MemoryOperandGeneration(graph, codegen, stats);
313 break;
314#endif
Aart Bik2e148682018-04-18 16:11:12 -0700315 case OptimizationPass::kNone:
316 LOG(FATAL) << "kNone does not represent an actual pass";
317 UNREACHABLE();
Aart Bik2ca10eb2017-11-15 15:17:53 -0800318 } // switch
319
320 // Add each next optimization to result vector.
321 CHECK(opt != nullptr);
Aart Bik2e148682018-04-18 16:11:12 -0700322 DCHECK_STREQ(pass_name, opt->GetPassName()); // sanity
Aart Bik2ca10eb2017-11-15 15:17:53 -0800323 optimizations.push_back(opt);
324 }
325
326 return optimizations;
327}
328
Roland Levillain75be2832014-10-17 17:02:00 +0100329} // namespace art