1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include "x86_memory_gen.h"
18*795d594fSAndroid Build Coastguard Worker #include "code_generator.h"
19*795d594fSAndroid Build Coastguard Worker #include "driver/compiler_options.h"
20*795d594fSAndroid Build Coastguard Worker
21*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
22*795d594fSAndroid Build Coastguard Worker namespace x86 {
23*795d594fSAndroid Build Coastguard Worker
24*795d594fSAndroid Build Coastguard Worker /**
25*795d594fSAndroid Build Coastguard Worker * Replace instructions with memory operand forms.
26*795d594fSAndroid Build Coastguard Worker */
27*795d594fSAndroid Build Coastguard Worker class MemoryOperandVisitor final : public HGraphVisitor {
28*795d594fSAndroid Build Coastguard Worker public:
MemoryOperandVisitor(HGraph * graph,bool do_implicit_null_checks)29*795d594fSAndroid Build Coastguard Worker MemoryOperandVisitor(HGraph* graph, bool do_implicit_null_checks)
30*795d594fSAndroid Build Coastguard Worker : HGraphVisitor(graph),
31*795d594fSAndroid Build Coastguard Worker do_implicit_null_checks_(do_implicit_null_checks) {}
32*795d594fSAndroid Build Coastguard Worker
33*795d594fSAndroid Build Coastguard Worker private:
VisitBoundsCheck(HBoundsCheck * check)34*795d594fSAndroid Build Coastguard Worker void VisitBoundsCheck(HBoundsCheck* check) override {
35*795d594fSAndroid Build Coastguard Worker // Replace the length by the array itself, so that we can do compares to memory.
36*795d594fSAndroid Build Coastguard Worker HArrayLength* array_len = check->InputAt(1)->AsArrayLengthOrNull();
37*795d594fSAndroid Build Coastguard Worker
38*795d594fSAndroid Build Coastguard Worker // We only want to replace an ArrayLength.
39*795d594fSAndroid Build Coastguard Worker if (array_len == nullptr) {
40*795d594fSAndroid Build Coastguard Worker return;
41*795d594fSAndroid Build Coastguard Worker }
42*795d594fSAndroid Build Coastguard Worker
43*795d594fSAndroid Build Coastguard Worker HInstruction* array = array_len->InputAt(0);
44*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(array->GetType(), DataType::Type::kReference);
45*795d594fSAndroid Build Coastguard Worker
46*795d594fSAndroid Build Coastguard Worker // Don't apply this optimization when the array is nullptr.
47*795d594fSAndroid Build Coastguard Worker if (array->IsConstant() || (array->IsNullCheck() && array->InputAt(0)->IsConstant())) {
48*795d594fSAndroid Build Coastguard Worker return;
49*795d594fSAndroid Build Coastguard Worker }
50*795d594fSAndroid Build Coastguard Worker
51*795d594fSAndroid Build Coastguard Worker // Is there a null check that could be an implicit check?
52*795d594fSAndroid Build Coastguard Worker if (array->IsNullCheck() && do_implicit_null_checks_) {
53*795d594fSAndroid Build Coastguard Worker // The ArrayLen may generate the implicit null check. Can the
54*795d594fSAndroid Build Coastguard Worker // bounds check do so as well?
55*795d594fSAndroid Build Coastguard Worker if (array_len->GetNextDisregardingMoves() != check) {
56*795d594fSAndroid Build Coastguard Worker // No, it won't. Leave as is.
57*795d594fSAndroid Build Coastguard Worker return;
58*795d594fSAndroid Build Coastguard Worker }
59*795d594fSAndroid Build Coastguard Worker }
60*795d594fSAndroid Build Coastguard Worker
61*795d594fSAndroid Build Coastguard Worker // Can we suppress the ArrayLength and generate at BoundCheck?
62*795d594fSAndroid Build Coastguard Worker if (array_len->HasOnlyOneNonEnvironmentUse()) {
63*795d594fSAndroid Build Coastguard Worker array_len->MarkEmittedAtUseSite();
64*795d594fSAndroid Build Coastguard Worker // We need the ArrayLength just before the BoundsCheck.
65*795d594fSAndroid Build Coastguard Worker array_len->MoveBefore(check);
66*795d594fSAndroid Build Coastguard Worker }
67*795d594fSAndroid Build Coastguard Worker }
68*795d594fSAndroid Build Coastguard Worker
69*795d594fSAndroid Build Coastguard Worker bool do_implicit_null_checks_;
70*795d594fSAndroid Build Coastguard Worker };
71*795d594fSAndroid Build Coastguard Worker
X86MemoryOperandGeneration(HGraph * graph,CodeGenerator * codegen,OptimizingCompilerStats * stats)72*795d594fSAndroid Build Coastguard Worker X86MemoryOperandGeneration::X86MemoryOperandGeneration(HGraph* graph,
73*795d594fSAndroid Build Coastguard Worker CodeGenerator* codegen,
74*795d594fSAndroid Build Coastguard Worker OptimizingCompilerStats* stats)
75*795d594fSAndroid Build Coastguard Worker : HOptimization(graph, kX86MemoryOperandGenerationPassName, stats),
76*795d594fSAndroid Build Coastguard Worker do_implicit_null_checks_(codegen->GetCompilerOptions().GetImplicitNullChecks()) {
77*795d594fSAndroid Build Coastguard Worker }
78*795d594fSAndroid Build Coastguard Worker
Run()79*795d594fSAndroid Build Coastguard Worker bool X86MemoryOperandGeneration::Run() {
80*795d594fSAndroid Build Coastguard Worker MemoryOperandVisitor visitor(graph_, do_implicit_null_checks_);
81*795d594fSAndroid Build Coastguard Worker visitor.VisitInsertionOrder();
82*795d594fSAndroid Build Coastguard Worker return true;
83*795d594fSAndroid Build Coastguard Worker }
84*795d594fSAndroid Build Coastguard Worker
85*795d594fSAndroid Build Coastguard Worker } // namespace x86
86*795d594fSAndroid Build Coastguard Worker } // namespace art
87