xref: /aosp_15_r20/art/compiler/optimizing/x86_memory_gen.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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