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 "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" 42 #include "dex/code_item_accessors-inl.h" 43 #include "driver/dex_compilation_unit.h" 44 #include "gvn.h" 45 #include "induction_var_analysis.h" 46 #include "inliner.h" 47 #include "instruction_simplifier.h" 48 #include "intrinsics.h" 49 #include "licm.h" 50 #include "load_store_analysis.h" 51 #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 60 namespace art { 61 62 const char* OptimizationPassName(OptimizationPass pass) { 63 switch (pass) { 64 case OptimizationPass::kSideEffectsAnalysis: 65 return SideEffectsAnalysis::kSideEffectsAnalysisPassName; 66 case OptimizationPass::kInductionVarAnalysis: 67 return HInductionVarAnalysis::kInductionPassName; 68 case OptimizationPass::kLoadStoreAnalysis: 69 return LoadStoreAnalysis::kLoadStoreAnalysisPassName; 70 case OptimizationPass::kGlobalValueNumbering: 71 return GVNOptimization::kGlobalValueNumberingPassName; 72 case OptimizationPass::kInvariantCodeMotion: 73 return LICM::kLoopInvariantCodeMotionPassName; 74 case OptimizationPass::kLoopOptimization: 75 return HLoopOptimization::kLoopOptimizationPassName; 76 case OptimizationPass::kBoundsCheckElimination: 77 return BoundsCheckElimination::kBoundsCheckEliminationPassName; 78 case OptimizationPass::kLoadStoreElimination: 79 return LoadStoreElimination::kLoadStoreEliminationPassName; 80 case OptimizationPass::kConstantFolding: 81 return HConstantFolding::kConstantFoldingPassName; 82 case OptimizationPass::kDeadCodeElimination: 83 return HDeadCodeElimination::kDeadCodeEliminationPassName; 84 case OptimizationPass::kInliner: 85 return HInliner::kInlinerPassName; 86 case OptimizationPass::kSharpening: 87 return HSharpening::kSharpeningPassName; 88 case OptimizationPass::kSelectGenerator: 89 return HSelectGenerator::kSelectGeneratorPassName; 90 case OptimizationPass::kInstructionSimplifier: 91 return InstructionSimplifier::kInstructionSimplifierPassName; 92 case OptimizationPass::kIntrinsicsRecognizer: 93 return IntrinsicsRecognizer::kIntrinsicsRecognizerPassName; 94 case OptimizationPass::kCHAGuardOptimization: 95 return CHAGuardOptimization::kCHAGuardOptimizationPassName; 96 case OptimizationPass::kCodeSinking: 97 return CodeSinking::kCodeSinkingPassName; 98 case OptimizationPass::kConstructorFenceRedundancyElimination: 99 return ConstructorFenceRedundancyElimination::kCFREPassName; 100 case OptimizationPass::kScheduling: 101 return HInstructionScheduling::kInstructionSchedulingPassName; 102 #ifdef ART_ENABLE_CODEGEN_arm 103 case OptimizationPass::kInstructionSimplifierArm: 104 return arm::InstructionSimplifierArm::kInstructionSimplifierArmPassName; 105 #endif 106 #ifdef ART_ENABLE_CODEGEN_arm64 107 case OptimizationPass::kInstructionSimplifierArm64: 108 return arm64::InstructionSimplifierArm64::kInstructionSimplifierArm64PassName; 109 #endif 110 #ifdef ART_ENABLE_CODEGEN_mips 111 case OptimizationPass::kPcRelativeFixupsMips: 112 return mips::PcRelativeFixups::kPcRelativeFixupsMipsPassName; 113 case OptimizationPass::kInstructionSimplifierMips: 114 return mips::InstructionSimplifierMips::kInstructionSimplifierMipsPassName; 115 #endif 116 #ifdef ART_ENABLE_CODEGEN_x86 117 case OptimizationPass::kPcRelativeFixupsX86: 118 return x86::PcRelativeFixups::kPcRelativeFixupsX86PassName; 119 #endif 120 #if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64) 121 case OptimizationPass::kX86MemoryOperandGeneration: 122 return x86::X86MemoryOperandGeneration::kX86MemoryOperandGenerationPassName; 123 #endif 124 } 125 } 126 127 #define X(x) if (name == OptimizationPassName((x))) return (x) 128 129 OptimizationPass OptimizationPassByName(const std::string& name) { 130 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); 140 X(OptimizationPass::kIntrinsicsRecognizer); 141 X(OptimizationPass::kInvariantCodeMotion); 142 X(OptimizationPass::kLoadStoreAnalysis); 143 X(OptimizationPass::kLoadStoreElimination); 144 X(OptimizationPass::kLoopOptimization); 145 X(OptimizationPass::kScheduling); 146 X(OptimizationPass::kSelectGenerator); 147 X(OptimizationPass::kSharpening); 148 X(OptimizationPass::kSideEffectsAnalysis); 149 #ifdef ART_ENABLE_CODEGEN_arm 150 X(OptimizationPass::kInstructionSimplifierArm); 151 #endif 152 #ifdef ART_ENABLE_CODEGEN_arm64 153 X(OptimizationPass::kInstructionSimplifierArm64); 154 #endif 155 #ifdef ART_ENABLE_CODEGEN_mips 156 X(OptimizationPass::kPcRelativeFixupsMips); 157 X(OptimizationPass::kInstructionSimplifierMips); 158 #endif 159 #ifdef ART_ENABLE_CODEGEN_x86 160 X(OptimizationPass::kPcRelativeFixupsX86); 161 X(OptimizationPass::kX86MemoryOperandGeneration); 162 #endif 163 LOG(FATAL) << "Cannot find optimization " << name; 164 UNREACHABLE(); 165 } 166 167 #undef X 168 169 ArenaVector<HOptimization*> ConstructOptimizations( 170 const OptimizationDef definitions[], 171 size_t length, 172 ArenaAllocator* allocator, 173 HGraph* graph, 174 OptimizingCompilerStats* stats, 175 CodeGenerator* codegen, 176 CompilerDriver* driver, 177 const DexCompilationUnit& dex_compilation_unit, 178 VariableSizedHandleScope* handles) { 179 ArenaVector<HOptimization*> optimizations(allocator->Adapter()); 180 181 // Some optimizations require SideEffectsAnalysis or HInductionVarAnalysis 182 // instances. This method uses the nearest instance preceeding it in the pass 183 // name list or fails fatally if no such analysis can be found. 184 SideEffectsAnalysis* most_recent_side_effects = nullptr; 185 HInductionVarAnalysis* most_recent_induction = nullptr; 186 LoadStoreAnalysis* most_recent_lsa = nullptr; 187 188 // Loop over the requested optimizations. 189 for (size_t i = 0; i < length; i++) { 190 OptimizationPass pass = definitions[i].first; 191 const char* alt_name = definitions[i].second; 192 const char* name = alt_name != nullptr 193 ? alt_name 194 : OptimizationPassName(pass); 195 HOptimization* opt = nullptr; 196 197 switch (pass) { 198 // 199 // Analysis passes (kept in most recent for subsequent passes). 200 // 201 case OptimizationPass::kSideEffectsAnalysis: 202 opt = most_recent_side_effects = new (allocator) SideEffectsAnalysis(graph, name); 203 break; 204 case OptimizationPass::kInductionVarAnalysis: 205 opt = most_recent_induction = new (allocator) HInductionVarAnalysis(graph, name); 206 break; 207 case OptimizationPass::kLoadStoreAnalysis: 208 opt = most_recent_lsa = new (allocator) LoadStoreAnalysis(graph, name); 209 break; 210 // 211 // Passes that need prior analysis. 212 // 213 case OptimizationPass::kGlobalValueNumbering: 214 CHECK(most_recent_side_effects != nullptr); 215 opt = new (allocator) GVNOptimization(graph, *most_recent_side_effects, name); 216 break; 217 case OptimizationPass::kInvariantCodeMotion: 218 CHECK(most_recent_side_effects != nullptr); 219 opt = new (allocator) LICM(graph, *most_recent_side_effects, stats, name); 220 break; 221 case OptimizationPass::kLoopOptimization: 222 CHECK(most_recent_induction != nullptr); 223 opt = new (allocator) HLoopOptimization(graph, driver, most_recent_induction, stats, name); 224 break; 225 case OptimizationPass::kBoundsCheckElimination: 226 CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr); 227 opt = new (allocator) BoundsCheckElimination( 228 graph, *most_recent_side_effects, most_recent_induction, name); 229 break; 230 case OptimizationPass::kLoadStoreElimination: 231 CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr); 232 opt = new (allocator) LoadStoreElimination( 233 graph, *most_recent_side_effects, *most_recent_lsa, stats, name); 234 break; 235 // 236 // Regular passes. 237 // 238 case OptimizationPass::kConstantFolding: 239 opt = new (allocator) HConstantFolding(graph, name); 240 break; 241 case OptimizationPass::kDeadCodeElimination: 242 opt = new (allocator) HDeadCodeElimination(graph, stats, name); 243 break; 244 case OptimizationPass::kInliner: { 245 CodeItemDataAccessor accessor(*dex_compilation_unit.GetDexFile(), 246 dex_compilation_unit.GetCodeItem()); 247 opt = new (allocator) HInliner(graph, // outer_graph 248 graph, // outermost_graph 249 codegen, 250 dex_compilation_unit, // outer_compilation_unit 251 dex_compilation_unit, // outermost_compilation_unit 252 driver, 253 handles, 254 stats, 255 accessor.RegistersSize(), 256 /* total_number_of_instructions */ 0, 257 /* parent */ nullptr, 258 /* depth */ 0, 259 name); 260 break; 261 } 262 case OptimizationPass::kSharpening: 263 opt = new (allocator) HSharpening(graph, codegen, driver, name); 264 break; 265 case OptimizationPass::kSelectGenerator: 266 opt = new (allocator) HSelectGenerator(graph, handles, stats, name); 267 break; 268 case OptimizationPass::kInstructionSimplifier: 269 opt = new (allocator) InstructionSimplifier(graph, codegen, driver, stats, name); 270 break; 271 case OptimizationPass::kIntrinsicsRecognizer: 272 opt = new (allocator) IntrinsicsRecognizer(graph, stats, name); 273 break; 274 case OptimizationPass::kCHAGuardOptimization: 275 opt = new (allocator) CHAGuardOptimization(graph, name); 276 break; 277 case OptimizationPass::kCodeSinking: 278 opt = new (allocator) CodeSinking(graph, stats, name); 279 break; 280 case OptimizationPass::kConstructorFenceRedundancyElimination: 281 opt = new (allocator) ConstructorFenceRedundancyElimination(graph, stats, name); 282 break; 283 case OptimizationPass::kScheduling: 284 opt = new (allocator) HInstructionScheduling( 285 graph, driver->GetInstructionSet(), codegen, name); 286 break; 287 // 288 // Arch-specific passes. 289 // 290 #ifdef ART_ENABLE_CODEGEN_arm 291 case OptimizationPass::kInstructionSimplifierArm: 292 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name"; 293 opt = new (allocator) arm::InstructionSimplifierArm(graph, stats); 294 break; 295 #endif 296 #ifdef ART_ENABLE_CODEGEN_arm64 297 case OptimizationPass::kInstructionSimplifierArm64: 298 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name"; 299 opt = new (allocator) arm64::InstructionSimplifierArm64(graph, stats); 300 break; 301 #endif 302 #ifdef ART_ENABLE_CODEGEN_mips 303 case OptimizationPass::kPcRelativeFixupsMips: 304 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name"; 305 opt = new (allocator) mips::PcRelativeFixups(graph, codegen, stats); 306 break; 307 case OptimizationPass::kInstructionSimplifierMips: 308 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name"; 309 opt = new (allocator) mips::InstructionSimplifierMips(graph, codegen, stats); 310 break; 311 #endif 312 #ifdef ART_ENABLE_CODEGEN_x86 313 case OptimizationPass::kPcRelativeFixupsX86: 314 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name"; 315 opt = new (allocator) x86::PcRelativeFixups(graph, codegen, stats); 316 break; 317 case OptimizationPass::kX86MemoryOperandGeneration: 318 DCHECK(alt_name == nullptr) << "arch-specific pass does not support alternative name"; 319 opt = new (allocator) x86::X86MemoryOperandGeneration(graph, codegen, stats); 320 break; 321 #endif 322 } // switch 323 324 // Add each next optimization to result vector. 325 CHECK(opt != nullptr); 326 DCHECK_STREQ(name, opt->GetPassName()); // sanity 327 optimizations.push_back(opt); 328 } 329 330 return optimizations; 331 } 332 333 } // namespace art 334