xref: /aosp_15_r20/art/compiler/optimizing/instruction_simplifier_arm64.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 "instruction_simplifier_arm64.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include "common_arm64.h"
20*795d594fSAndroid Build Coastguard Worker #include "instruction_simplifier.h"
21*795d594fSAndroid Build Coastguard Worker #include "instruction_simplifier_shared.h"
22*795d594fSAndroid Build Coastguard Worker #include "mirror/array-inl.h"
23*795d594fSAndroid Build Coastguard Worker #include "mirror/string.h"
24*795d594fSAndroid Build Coastguard Worker 
25*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
26*795d594fSAndroid Build Coastguard Worker 
27*795d594fSAndroid Build Coastguard Worker using helpers::CanFitInShifterOperand;
28*795d594fSAndroid Build Coastguard Worker using helpers::HasShifterOperand;
29*795d594fSAndroid Build Coastguard Worker using helpers::IsSubRightSubLeftShl;
30*795d594fSAndroid Build Coastguard Worker 
31*795d594fSAndroid Build Coastguard Worker namespace arm64 {
32*795d594fSAndroid Build Coastguard Worker 
33*795d594fSAndroid Build Coastguard Worker using helpers::ShifterOperandSupportsExtension;
34*795d594fSAndroid Build Coastguard Worker 
35*795d594fSAndroid Build Coastguard Worker class InstructionSimplifierArm64Visitor final : public HGraphVisitor {
36*795d594fSAndroid Build Coastguard Worker  public:
InstructionSimplifierArm64Visitor(HGraph * graph,CodeGenerator * codegen,OptimizingCompilerStats * stats)37*795d594fSAndroid Build Coastguard Worker   InstructionSimplifierArm64Visitor(
38*795d594fSAndroid Build Coastguard Worker       HGraph* graph, CodeGenerator* codegen, OptimizingCompilerStats* stats)
39*795d594fSAndroid Build Coastguard Worker       : HGraphVisitor(graph), codegen_(codegen), stats_(stats) {}
40*795d594fSAndroid Build Coastguard Worker 
41*795d594fSAndroid Build Coastguard Worker  private:
RecordSimplification()42*795d594fSAndroid Build Coastguard Worker   void RecordSimplification() {
43*795d594fSAndroid Build Coastguard Worker     MaybeRecordStat(stats_, MethodCompilationStat::kInstructionSimplificationsArch);
44*795d594fSAndroid Build Coastguard Worker   }
45*795d594fSAndroid Build Coastguard Worker 
46*795d594fSAndroid Build Coastguard Worker   bool TryMergeIntoUsersShifterOperand(HInstruction* instruction);
47*795d594fSAndroid Build Coastguard Worker   bool TryMergeIntoShifterOperand(HInstruction* use,
48*795d594fSAndroid Build Coastguard Worker                                   HInstruction* bitfield_op,
49*795d594fSAndroid Build Coastguard Worker                                   bool do_merge);
CanMergeIntoShifterOperand(HInstruction * use,HInstruction * bitfield_op)50*795d594fSAndroid Build Coastguard Worker   bool CanMergeIntoShifterOperand(HInstruction* use, HInstruction* bitfield_op) {
51*795d594fSAndroid Build Coastguard Worker     return TryMergeIntoShifterOperand(use, bitfield_op, /* do_merge= */ false);
52*795d594fSAndroid Build Coastguard Worker   }
MergeIntoShifterOperand(HInstruction * use,HInstruction * bitfield_op)53*795d594fSAndroid Build Coastguard Worker   bool MergeIntoShifterOperand(HInstruction* use, HInstruction* bitfield_op) {
54*795d594fSAndroid Build Coastguard Worker     DCHECK(CanMergeIntoShifterOperand(use, bitfield_op));
55*795d594fSAndroid Build Coastguard Worker     return TryMergeIntoShifterOperand(use, bitfield_op, /* do_merge= */ true);
56*795d594fSAndroid Build Coastguard Worker   }
57*795d594fSAndroid Build Coastguard Worker 
58*795d594fSAndroid Build Coastguard Worker   /**
59*795d594fSAndroid Build Coastguard Worker    * This simplifier uses a special-purpose BB visitor.
60*795d594fSAndroid Build Coastguard Worker    * (1) No need to visit Phi nodes.
61*795d594fSAndroid Build Coastguard Worker    * (2) Since statements can be removed in a "forward" fashion,
62*795d594fSAndroid Build Coastguard Worker    *     the visitor should test if each statement is still there.
63*795d594fSAndroid Build Coastguard Worker    */
VisitBasicBlock(HBasicBlock * block)64*795d594fSAndroid Build Coastguard Worker   void VisitBasicBlock(HBasicBlock* block) override {
65*795d594fSAndroid Build Coastguard Worker     // TODO: fragile iteration, provide more robust iterators?
66*795d594fSAndroid Build Coastguard Worker     for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
67*795d594fSAndroid Build Coastguard Worker       HInstruction* instruction = it.Current();
68*795d594fSAndroid Build Coastguard Worker       if (instruction->IsInBlock()) {
69*795d594fSAndroid Build Coastguard Worker         instruction->Accept(this);
70*795d594fSAndroid Build Coastguard Worker       }
71*795d594fSAndroid Build Coastguard Worker     }
72*795d594fSAndroid Build Coastguard Worker   }
73*795d594fSAndroid Build Coastguard Worker 
74*795d594fSAndroid Build Coastguard Worker   // HInstruction visitors, sorted alphabetically.
75*795d594fSAndroid Build Coastguard Worker   void VisitAnd(HAnd* instruction) override;
76*795d594fSAndroid Build Coastguard Worker   void VisitArrayGet(HArrayGet* instruction) override;
77*795d594fSAndroid Build Coastguard Worker   void VisitArraySet(HArraySet* instruction) override;
78*795d594fSAndroid Build Coastguard Worker   void VisitMul(HMul* instruction) override;
79*795d594fSAndroid Build Coastguard Worker   void VisitOr(HOr* instruction) override;
80*795d594fSAndroid Build Coastguard Worker   void VisitRol(HRol* instruction) override;
81*795d594fSAndroid Build Coastguard Worker   void VisitShl(HShl* instruction) override;
82*795d594fSAndroid Build Coastguard Worker   void VisitShr(HShr* instruction) override;
83*795d594fSAndroid Build Coastguard Worker   void VisitSub(HSub* instruction) override;
84*795d594fSAndroid Build Coastguard Worker   void VisitTypeConversion(HTypeConversion* instruction) override;
85*795d594fSAndroid Build Coastguard Worker   void VisitUShr(HUShr* instruction) override;
86*795d594fSAndroid Build Coastguard Worker   void VisitXor(HXor* instruction) override;
87*795d594fSAndroid Build Coastguard Worker   void VisitVecLoad(HVecLoad* instruction) override;
88*795d594fSAndroid Build Coastguard Worker   void VisitVecStore(HVecStore* instruction) override;
89*795d594fSAndroid Build Coastguard Worker 
90*795d594fSAndroid Build Coastguard Worker   CodeGenerator* codegen_;
91*795d594fSAndroid Build Coastguard Worker   OptimizingCompilerStats* stats_;
92*795d594fSAndroid Build Coastguard Worker };
93*795d594fSAndroid Build Coastguard Worker 
TryMergeIntoShifterOperand(HInstruction * use,HInstruction * bitfield_op,bool do_merge)94*795d594fSAndroid Build Coastguard Worker bool InstructionSimplifierArm64Visitor::TryMergeIntoShifterOperand(HInstruction* use,
95*795d594fSAndroid Build Coastguard Worker                                                                    HInstruction* bitfield_op,
96*795d594fSAndroid Build Coastguard Worker                                                                    bool do_merge) {
97*795d594fSAndroid Build Coastguard Worker   DCHECK(HasShifterOperand(use, InstructionSet::kArm64));
98*795d594fSAndroid Build Coastguard Worker   DCHECK(use->IsBinaryOperation() || use->IsNeg());
99*795d594fSAndroid Build Coastguard Worker   DCHECK(CanFitInShifterOperand(bitfield_op));
100*795d594fSAndroid Build Coastguard Worker   DCHECK(!bitfield_op->HasEnvironmentUses());
101*795d594fSAndroid Build Coastguard Worker 
102*795d594fSAndroid Build Coastguard Worker   DataType::Type type = use->GetType();
103*795d594fSAndroid Build Coastguard Worker   if (type != DataType::Type::kInt32 && type != DataType::Type::kInt64) {
104*795d594fSAndroid Build Coastguard Worker     return false;
105*795d594fSAndroid Build Coastguard Worker   }
106*795d594fSAndroid Build Coastguard Worker 
107*795d594fSAndroid Build Coastguard Worker   HInstruction* left;
108*795d594fSAndroid Build Coastguard Worker   HInstruction* right;
109*795d594fSAndroid Build Coastguard Worker   if (use->IsBinaryOperation()) {
110*795d594fSAndroid Build Coastguard Worker     left = use->InputAt(0);
111*795d594fSAndroid Build Coastguard Worker     right = use->InputAt(1);
112*795d594fSAndroid Build Coastguard Worker   } else {
113*795d594fSAndroid Build Coastguard Worker     DCHECK(use->IsNeg());
114*795d594fSAndroid Build Coastguard Worker     right = use->AsNeg()->InputAt(0);
115*795d594fSAndroid Build Coastguard Worker     left = GetGraph()->GetConstant(right->GetType(), 0);
116*795d594fSAndroid Build Coastguard Worker   }
117*795d594fSAndroid Build Coastguard Worker   DCHECK(left == bitfield_op || right == bitfield_op);
118*795d594fSAndroid Build Coastguard Worker 
119*795d594fSAndroid Build Coastguard Worker   if (left == right) {
120*795d594fSAndroid Build Coastguard Worker     // TODO: Handle special transformations in this situation?
121*795d594fSAndroid Build Coastguard Worker     // For example should we transform `(x << 1) + (x << 1)` into `(x << 2)`?
122*795d594fSAndroid Build Coastguard Worker     // Or should this be part of a separate transformation logic?
123*795d594fSAndroid Build Coastguard Worker     return false;
124*795d594fSAndroid Build Coastguard Worker   }
125*795d594fSAndroid Build Coastguard Worker 
126*795d594fSAndroid Build Coastguard Worker   bool is_commutative = use->IsBinaryOperation() && use->AsBinaryOperation()->IsCommutative();
127*795d594fSAndroid Build Coastguard Worker   HInstruction* other_input;
128*795d594fSAndroid Build Coastguard Worker   if (bitfield_op == right) {
129*795d594fSAndroid Build Coastguard Worker     other_input = left;
130*795d594fSAndroid Build Coastguard Worker   } else {
131*795d594fSAndroid Build Coastguard Worker     if (is_commutative) {
132*795d594fSAndroid Build Coastguard Worker       other_input = right;
133*795d594fSAndroid Build Coastguard Worker     } else {
134*795d594fSAndroid Build Coastguard Worker       return false;
135*795d594fSAndroid Build Coastguard Worker     }
136*795d594fSAndroid Build Coastguard Worker   }
137*795d594fSAndroid Build Coastguard Worker 
138*795d594fSAndroid Build Coastguard Worker   HDataProcWithShifterOp::OpKind op_kind;
139*795d594fSAndroid Build Coastguard Worker   int shift_amount = 0;
140*795d594fSAndroid Build Coastguard Worker   HDataProcWithShifterOp::GetOpInfoFromInstruction(bitfield_op, &op_kind, &shift_amount);
141*795d594fSAndroid Build Coastguard Worker 
142*795d594fSAndroid Build Coastguard Worker   if (HDataProcWithShifterOp::IsExtensionOp(op_kind) && !ShifterOperandSupportsExtension(use)) {
143*795d594fSAndroid Build Coastguard Worker     return false;
144*795d594fSAndroid Build Coastguard Worker   }
145*795d594fSAndroid Build Coastguard Worker 
146*795d594fSAndroid Build Coastguard Worker   if (do_merge) {
147*795d594fSAndroid Build Coastguard Worker     HDataProcWithShifterOp* alu_with_op =
148*795d594fSAndroid Build Coastguard Worker         new (GetGraph()->GetAllocator()) HDataProcWithShifterOp(use,
149*795d594fSAndroid Build Coastguard Worker                                                                 other_input,
150*795d594fSAndroid Build Coastguard Worker                                                                 bitfield_op->InputAt(0),
151*795d594fSAndroid Build Coastguard Worker                                                                 op_kind,
152*795d594fSAndroid Build Coastguard Worker                                                                 shift_amount,
153*795d594fSAndroid Build Coastguard Worker                                                                 use->GetDexPc());
154*795d594fSAndroid Build Coastguard Worker     use->GetBlock()->ReplaceAndRemoveInstructionWith(use, alu_with_op);
155*795d594fSAndroid Build Coastguard Worker     if (bitfield_op->GetUses().empty()) {
156*795d594fSAndroid Build Coastguard Worker       bitfield_op->GetBlock()->RemoveInstruction(bitfield_op);
157*795d594fSAndroid Build Coastguard Worker     }
158*795d594fSAndroid Build Coastguard Worker     RecordSimplification();
159*795d594fSAndroid Build Coastguard Worker   }
160*795d594fSAndroid Build Coastguard Worker 
161*795d594fSAndroid Build Coastguard Worker   return true;
162*795d594fSAndroid Build Coastguard Worker }
163*795d594fSAndroid Build Coastguard Worker 
164*795d594fSAndroid Build Coastguard Worker // Merge a bitfield move instruction into its uses if it can be merged in all of them.
TryMergeIntoUsersShifterOperand(HInstruction * bitfield_op)165*795d594fSAndroid Build Coastguard Worker bool InstructionSimplifierArm64Visitor::TryMergeIntoUsersShifterOperand(HInstruction* bitfield_op) {
166*795d594fSAndroid Build Coastguard Worker   DCHECK(CanFitInShifterOperand(bitfield_op));
167*795d594fSAndroid Build Coastguard Worker 
168*795d594fSAndroid Build Coastguard Worker   if (bitfield_op->HasEnvironmentUses()) {
169*795d594fSAndroid Build Coastguard Worker     return false;
170*795d594fSAndroid Build Coastguard Worker   }
171*795d594fSAndroid Build Coastguard Worker 
172*795d594fSAndroid Build Coastguard Worker   const HUseList<HInstruction*>& uses = bitfield_op->GetUses();
173*795d594fSAndroid Build Coastguard Worker 
174*795d594fSAndroid Build Coastguard Worker   // Check whether we can merge the instruction in all its users' shifter operand.
175*795d594fSAndroid Build Coastguard Worker   for (const HUseListNode<HInstruction*>& use : uses) {
176*795d594fSAndroid Build Coastguard Worker     HInstruction* user = use.GetUser();
177*795d594fSAndroid Build Coastguard Worker     if (!HasShifterOperand(user, InstructionSet::kArm64)) {
178*795d594fSAndroid Build Coastguard Worker       return false;
179*795d594fSAndroid Build Coastguard Worker     }
180*795d594fSAndroid Build Coastguard Worker     if (!CanMergeIntoShifterOperand(user, bitfield_op)) {
181*795d594fSAndroid Build Coastguard Worker       return false;
182*795d594fSAndroid Build Coastguard Worker     }
183*795d594fSAndroid Build Coastguard Worker   }
184*795d594fSAndroid Build Coastguard Worker 
185*795d594fSAndroid Build Coastguard Worker   // Merge the instruction into its uses.
186*795d594fSAndroid Build Coastguard Worker   for (auto it = uses.begin(), end = uses.end(); it != end; /* ++it below */) {
187*795d594fSAndroid Build Coastguard Worker     HInstruction* user = it->GetUser();
188*795d594fSAndroid Build Coastguard Worker     // Increment `it` now because `*it` will disappear thanks to MergeIntoShifterOperand().
189*795d594fSAndroid Build Coastguard Worker     ++it;
190*795d594fSAndroid Build Coastguard Worker     bool merged = MergeIntoShifterOperand(user, bitfield_op);
191*795d594fSAndroid Build Coastguard Worker     DCHECK(merged);
192*795d594fSAndroid Build Coastguard Worker   }
193*795d594fSAndroid Build Coastguard Worker 
194*795d594fSAndroid Build Coastguard Worker   return true;
195*795d594fSAndroid Build Coastguard Worker }
196*795d594fSAndroid Build Coastguard Worker 
VisitAnd(HAnd * instruction)197*795d594fSAndroid Build Coastguard Worker void InstructionSimplifierArm64Visitor::VisitAnd(HAnd* instruction) {
198*795d594fSAndroid Build Coastguard Worker   if (TryMergeNegatedInput(instruction)) {
199*795d594fSAndroid Build Coastguard Worker     RecordSimplification();
200*795d594fSAndroid Build Coastguard Worker   }
201*795d594fSAndroid Build Coastguard Worker }
202*795d594fSAndroid Build Coastguard Worker 
VisitArrayGet(HArrayGet * instruction)203*795d594fSAndroid Build Coastguard Worker void InstructionSimplifierArm64Visitor::VisitArrayGet(HArrayGet* instruction) {
204*795d594fSAndroid Build Coastguard Worker   size_t data_offset = CodeGenerator::GetArrayDataOffset(instruction);
205*795d594fSAndroid Build Coastguard Worker   if (TryExtractArrayAccessAddress(codegen_,
206*795d594fSAndroid Build Coastguard Worker                                    instruction,
207*795d594fSAndroid Build Coastguard Worker                                    instruction->GetArray(),
208*795d594fSAndroid Build Coastguard Worker                                    instruction->GetIndex(),
209*795d594fSAndroid Build Coastguard Worker                                    data_offset)) {
210*795d594fSAndroid Build Coastguard Worker     RecordSimplification();
211*795d594fSAndroid Build Coastguard Worker   }
212*795d594fSAndroid Build Coastguard Worker }
213*795d594fSAndroid Build Coastguard Worker 
VisitArraySet(HArraySet * instruction)214*795d594fSAndroid Build Coastguard Worker void InstructionSimplifierArm64Visitor::VisitArraySet(HArraySet* instruction) {
215*795d594fSAndroid Build Coastguard Worker   size_t access_size = DataType::Size(instruction->GetComponentType());
216*795d594fSAndroid Build Coastguard Worker   size_t data_offset = mirror::Array::DataOffset(access_size).Uint32Value();
217*795d594fSAndroid Build Coastguard Worker   if (TryExtractArrayAccessAddress(codegen_,
218*795d594fSAndroid Build Coastguard Worker                                    instruction,
219*795d594fSAndroid Build Coastguard Worker                                    instruction->GetArray(),
220*795d594fSAndroid Build Coastguard Worker                                    instruction->GetIndex(),
221*795d594fSAndroid Build Coastguard Worker                                    data_offset)) {
222*795d594fSAndroid Build Coastguard Worker     RecordSimplification();
223*795d594fSAndroid Build Coastguard Worker   }
224*795d594fSAndroid Build Coastguard Worker }
225*795d594fSAndroid Build Coastguard Worker 
VisitMul(HMul * instruction)226*795d594fSAndroid Build Coastguard Worker void InstructionSimplifierArm64Visitor::VisitMul(HMul* instruction) {
227*795d594fSAndroid Build Coastguard Worker   if (TryCombineMultiplyAccumulate(instruction, InstructionSet::kArm64)) {
228*795d594fSAndroid Build Coastguard Worker     RecordSimplification();
229*795d594fSAndroid Build Coastguard Worker   }
230*795d594fSAndroid Build Coastguard Worker }
231*795d594fSAndroid Build Coastguard Worker 
VisitOr(HOr * instruction)232*795d594fSAndroid Build Coastguard Worker void InstructionSimplifierArm64Visitor::VisitOr(HOr* instruction) {
233*795d594fSAndroid Build Coastguard Worker   if (TryMergeNegatedInput(instruction)) {
234*795d594fSAndroid Build Coastguard Worker     RecordSimplification();
235*795d594fSAndroid Build Coastguard Worker   }
236*795d594fSAndroid Build Coastguard Worker }
237*795d594fSAndroid Build Coastguard Worker 
VisitRol(HRol * rol)238*795d594fSAndroid Build Coastguard Worker void InstructionSimplifierArm64Visitor::VisitRol(HRol* rol) {
239*795d594fSAndroid Build Coastguard Worker   UnfoldRotateLeft(rol);
240*795d594fSAndroid Build Coastguard Worker   RecordSimplification();
241*795d594fSAndroid Build Coastguard Worker }
242*795d594fSAndroid Build Coastguard Worker 
VisitShl(HShl * instruction)243*795d594fSAndroid Build Coastguard Worker void InstructionSimplifierArm64Visitor::VisitShl(HShl* instruction) {
244*795d594fSAndroid Build Coastguard Worker   if (instruction->InputAt(1)->IsConstant()) {
245*795d594fSAndroid Build Coastguard Worker     TryMergeIntoUsersShifterOperand(instruction);
246*795d594fSAndroid Build Coastguard Worker   }
247*795d594fSAndroid Build Coastguard Worker }
248*795d594fSAndroid Build Coastguard Worker 
VisitShr(HShr * instruction)249*795d594fSAndroid Build Coastguard Worker void InstructionSimplifierArm64Visitor::VisitShr(HShr* instruction) {
250*795d594fSAndroid Build Coastguard Worker   if (instruction->InputAt(1)->IsConstant()) {
251*795d594fSAndroid Build Coastguard Worker     TryMergeIntoUsersShifterOperand(instruction);
252*795d594fSAndroid Build Coastguard Worker   }
253*795d594fSAndroid Build Coastguard Worker }
254*795d594fSAndroid Build Coastguard Worker 
VisitSub(HSub * instruction)255*795d594fSAndroid Build Coastguard Worker void InstructionSimplifierArm64Visitor::VisitSub(HSub* instruction) {
256*795d594fSAndroid Build Coastguard Worker   if (IsSubRightSubLeftShl(instruction)) {
257*795d594fSAndroid Build Coastguard Worker     HInstruction* shl = instruction->GetRight()->InputAt(0);
258*795d594fSAndroid Build Coastguard Worker     if (shl->InputAt(1)->IsConstant() && TryReplaceSubSubWithSubAdd(instruction)) {
259*795d594fSAndroid Build Coastguard Worker       if (TryMergeIntoUsersShifterOperand(shl)) {
260*795d594fSAndroid Build Coastguard Worker         return;
261*795d594fSAndroid Build Coastguard Worker       }
262*795d594fSAndroid Build Coastguard Worker     }
263*795d594fSAndroid Build Coastguard Worker   }
264*795d594fSAndroid Build Coastguard Worker 
265*795d594fSAndroid Build Coastguard Worker   if (TryMergeWithAnd(instruction)) {
266*795d594fSAndroid Build Coastguard Worker     return;
267*795d594fSAndroid Build Coastguard Worker   }
268*795d594fSAndroid Build Coastguard Worker }
269*795d594fSAndroid Build Coastguard Worker 
VisitTypeConversion(HTypeConversion * instruction)270*795d594fSAndroid Build Coastguard Worker void InstructionSimplifierArm64Visitor::VisitTypeConversion(HTypeConversion* instruction) {
271*795d594fSAndroid Build Coastguard Worker   DataType::Type result_type = instruction->GetResultType();
272*795d594fSAndroid Build Coastguard Worker   DataType::Type input_type = instruction->GetInputType();
273*795d594fSAndroid Build Coastguard Worker 
274*795d594fSAndroid Build Coastguard Worker   if (input_type == result_type) {
275*795d594fSAndroid Build Coastguard Worker     // We let the arch-independent code handle this.
276*795d594fSAndroid Build Coastguard Worker     return;
277*795d594fSAndroid Build Coastguard Worker   }
278*795d594fSAndroid Build Coastguard Worker 
279*795d594fSAndroid Build Coastguard Worker   if (DataType::IsIntegralType(result_type) && DataType::IsIntegralType(input_type)) {
280*795d594fSAndroid Build Coastguard Worker     TryMergeIntoUsersShifterOperand(instruction);
281*795d594fSAndroid Build Coastguard Worker   }
282*795d594fSAndroid Build Coastguard Worker }
283*795d594fSAndroid Build Coastguard Worker 
VisitUShr(HUShr * instruction)284*795d594fSAndroid Build Coastguard Worker void InstructionSimplifierArm64Visitor::VisitUShr(HUShr* instruction) {
285*795d594fSAndroid Build Coastguard Worker   if (instruction->InputAt(1)->IsConstant()) {
286*795d594fSAndroid Build Coastguard Worker     TryMergeIntoUsersShifterOperand(instruction);
287*795d594fSAndroid Build Coastguard Worker   }
288*795d594fSAndroid Build Coastguard Worker }
289*795d594fSAndroid Build Coastguard Worker 
VisitXor(HXor * instruction)290*795d594fSAndroid Build Coastguard Worker void InstructionSimplifierArm64Visitor::VisitXor(HXor* instruction) {
291*795d594fSAndroid Build Coastguard Worker   if (TryMergeNegatedInput(instruction)) {
292*795d594fSAndroid Build Coastguard Worker     RecordSimplification();
293*795d594fSAndroid Build Coastguard Worker   }
294*795d594fSAndroid Build Coastguard Worker }
295*795d594fSAndroid Build Coastguard Worker 
VisitVecLoad(HVecLoad * instruction)296*795d594fSAndroid Build Coastguard Worker void InstructionSimplifierArm64Visitor::VisitVecLoad(HVecLoad* instruction) {
297*795d594fSAndroid Build Coastguard Worker   if (!instruction->IsPredicated() && !instruction->IsStringCharAt() &&
298*795d594fSAndroid Build Coastguard Worker       TryExtractVecArrayAccessAddress(instruction, instruction->GetIndex())) {
299*795d594fSAndroid Build Coastguard Worker     RecordSimplification();
300*795d594fSAndroid Build Coastguard Worker   } else if (instruction->IsPredicated()) {
301*795d594fSAndroid Build Coastguard Worker     size_t size = DataType::Size(instruction->GetPackedType());
302*795d594fSAndroid Build Coastguard Worker     size_t offset = mirror::Array::DataOffset(size).Uint32Value();
303*795d594fSAndroid Build Coastguard Worker     if (TryExtractArrayAccessAddress(
304*795d594fSAndroid Build Coastguard Worker             codegen_, instruction, instruction->GetArray(), instruction->GetIndex(), offset)) {
305*795d594fSAndroid Build Coastguard Worker       RecordSimplification();
306*795d594fSAndroid Build Coastguard Worker     }
307*795d594fSAndroid Build Coastguard Worker   }
308*795d594fSAndroid Build Coastguard Worker }
309*795d594fSAndroid Build Coastguard Worker 
VisitVecStore(HVecStore * instruction)310*795d594fSAndroid Build Coastguard Worker void InstructionSimplifierArm64Visitor::VisitVecStore(HVecStore* instruction) {
311*795d594fSAndroid Build Coastguard Worker   if (!instruction->IsPredicated() &&
312*795d594fSAndroid Build Coastguard Worker       TryExtractVecArrayAccessAddress(instruction, instruction->GetIndex())) {
313*795d594fSAndroid Build Coastguard Worker     RecordSimplification();
314*795d594fSAndroid Build Coastguard Worker   } else if (instruction->IsPredicated()) {
315*795d594fSAndroid Build Coastguard Worker     size_t size = DataType::Size(instruction->GetPackedType());
316*795d594fSAndroid Build Coastguard Worker     size_t offset = mirror::Array::DataOffset(size).Uint32Value();
317*795d594fSAndroid Build Coastguard Worker     if (TryExtractArrayAccessAddress(
318*795d594fSAndroid Build Coastguard Worker             codegen_, instruction, instruction->GetArray(), instruction->GetIndex(), offset)) {
319*795d594fSAndroid Build Coastguard Worker       RecordSimplification();
320*795d594fSAndroid Build Coastguard Worker     }
321*795d594fSAndroid Build Coastguard Worker   }
322*795d594fSAndroid Build Coastguard Worker }
323*795d594fSAndroid Build Coastguard Worker 
Run()324*795d594fSAndroid Build Coastguard Worker bool InstructionSimplifierArm64::Run() {
325*795d594fSAndroid Build Coastguard Worker   InstructionSimplifierArm64Visitor visitor(graph_, codegen_, stats_);
326*795d594fSAndroid Build Coastguard Worker   visitor.VisitReversePostOrder();
327*795d594fSAndroid Build Coastguard Worker   return true;
328*795d594fSAndroid Build Coastguard Worker }
329*795d594fSAndroid Build Coastguard Worker 
330*795d594fSAndroid Build Coastguard Worker }  // namespace arm64
331*795d594fSAndroid Build Coastguard Worker }  // namespace art
332