1 /* 2 * Copyright (C) 2015 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 "x86_memory_gen.h" 18 #include "code_generator.h" 19 #include "driver/compiler_options.h" 20 21 namespace art { 22 namespace x86 { 23 24 /** 25 * Replace instructions with memory operand forms. 26 */ 27 class MemoryOperandVisitor : public HGraphVisitor { 28 public: 29 MemoryOperandVisitor(HGraph* graph, bool do_implicit_null_checks) 30 : HGraphVisitor(graph), 31 do_implicit_null_checks_(do_implicit_null_checks) {} 32 33 private: 34 void VisitBoundsCheck(HBoundsCheck* check) OVERRIDE { 35 // Replace the length by the array itself, so that we can do compares to memory. 36 HArrayLength* array_len = check->InputAt(1)->AsArrayLength(); 37 38 // We only want to replace an ArrayLength. 39 if (array_len == nullptr) { 40 return; 41 } 42 43 HInstruction* array = array_len->InputAt(0); 44 DCHECK_EQ(array->GetType(), DataType::Type::kReference); 45 46 // Don't apply this optimization when the array is nullptr. 47 if (array->IsConstant() || (array->IsNullCheck() && array->InputAt(0)->IsConstant())) { 48 return; 49 } 50 51 // Is there a null check that could be an implicit check? 52 if (array->IsNullCheck() && do_implicit_null_checks_) { 53 // The ArrayLen may generate the implicit null check. Can the 54 // bounds check do so as well? 55 if (array_len->GetNextDisregardingMoves() != check) { 56 // No, it won't. Leave as is. 57 return; 58 } 59 } 60 61 // Can we suppress the ArrayLength and generate at BoundCheck? 62 if (array_len->HasOnlyOneNonEnvironmentUse()) { 63 array_len->MarkEmittedAtUseSite(); 64 // We need the ArrayLength just before the BoundsCheck. 65 array_len->MoveBefore(check); 66 } 67 } 68 69 bool do_implicit_null_checks_; 70 }; 71 72 X86MemoryOperandGeneration::X86MemoryOperandGeneration(HGraph* graph, 73 CodeGenerator* codegen, 74 OptimizingCompilerStats* stats) 75 : HOptimization(graph, kX86MemoryOperandGenerationPassName, stats), 76 do_implicit_null_checks_(codegen->GetCompilerOptions().GetImplicitNullChecks()) { 77 } 78 79 void X86MemoryOperandGeneration::Run() { 80 MemoryOperandVisitor visitor(graph_, do_implicit_null_checks_); 81 visitor.VisitInsertionOrder(); 82 } 83 84 } // namespace x86 85 } // namespace art 86