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