144b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames/*
244b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames * Copyright (C) 2015 The Android Open Source Project
344b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames *
444b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames * Licensed under the Apache License, Version 2.0 (the "License");
544b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames * you may not use this file except in compliance with the License.
644b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames * You may obtain a copy of the License at
744b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames *
844b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames *      http://www.apache.org/licenses/LICENSE-2.0
944b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames *
1044b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames * Unless required by applicable law or agreed to in writing, software
1144b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames * distributed under the License is distributed on an "AS IS" BASIS,
1244b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1344b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames * See the License for the specific language governing permissions and
1444b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames * limitations under the License.
1544b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames */
1644b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames
1744b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames#include "instruction_simplifier_arm64.h"
1844b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames
198626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames#include "common_arm64.h"
204a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko#include "instruction_simplifier_shared.h"
21e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames#include "mirror/array-inl.h"
22e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames
2344b9cf937836bb33139123e15ca8b586b5853268Alexandre Ramesnamespace art {
2444b9cf937836bb33139123e15ca8b586b5853268Alexandre Ramesnamespace arm64 {
2544b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames
268626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Ramesusing helpers::CanFitInShifterOperand;
278626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Ramesusing helpers::HasShifterOperand;
288626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Ramesusing helpers::ShifterOperandSupportsExtension;
298626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
30e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Ramesvoid InstructionSimplifierArm64Visitor::TryExtractArrayAccessAddress(HInstruction* access,
31e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames                                                                     HInstruction* array,
32e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames                                                                     HInstruction* index,
33e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames                                                                     int access_size) {
34cd3d0fb5a4c113cfdb610454d133762a2ab0e6deRoland Levillain  if (kEmitCompilerReadBarrier) {
35cd3d0fb5a4c113cfdb610454d133762a2ab0e6deRoland Levillain    // The read barrier instrumentation does not support the
36cd3d0fb5a4c113cfdb610454d133762a2ab0e6deRoland Levillain    // HArm64IntermediateAddress instruction yet.
37cd3d0fb5a4c113cfdb610454d133762a2ab0e6deRoland Levillain    //
38cd3d0fb5a4c113cfdb610454d133762a2ab0e6deRoland Levillain    // TODO: Handle this case properly in the ARM64 code generator and
39cd3d0fb5a4c113cfdb610454d133762a2ab0e6deRoland Levillain    // re-enable this optimization; otherwise, remove this TODO.
40cd3d0fb5a4c113cfdb610454d133762a2ab0e6deRoland Levillain    // b/26601270
41cd3d0fb5a4c113cfdb610454d133762a2ab0e6deRoland Levillain    return;
42cd3d0fb5a4c113cfdb610454d133762a2ab0e6deRoland Levillain  }
43e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  if (index->IsConstant() ||
44e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames      (index->IsBoundsCheck() && index->AsBoundsCheck()->GetIndex()->IsConstant())) {
45e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames    // When the index is a constant all the addressing can be fitted in the
46e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames    // memory access instruction, so do not split the access.
47e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames    return;
48e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  }
49e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  if (access->IsArraySet() &&
50e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames      access->AsArraySet()->GetValue()->GetType() == Primitive::kPrimNot) {
51e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames    // The access may require a runtime call or the original array pointer.
52e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames    return;
53e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  }
54e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames
55e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  // Proceed to extract the base address computation.
56e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  ArenaAllocator* arena = GetGraph()->GetArena();
57e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames
58e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  HIntConstant* offset =
59e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames      GetGraph()->GetIntConstant(mirror::Array::DataOffset(access_size).Uint32Value());
60e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  HArm64IntermediateAddress* address =
61e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames      new (arena) HArm64IntermediateAddress(array, offset, kNoDexPc);
62295abc1a3aec98868544dfd4e0eeab797c3d60c2David Brazdil  address->SetReferenceTypeInfo(array->GetReferenceTypeInfo());
63e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  access->GetBlock()->InsertInstructionBefore(address, access);
64e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  access->ReplaceInput(address, 0);
65e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  // Both instructions must depend on GC to prevent any instruction that can
66e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  // trigger GC to be inserted between the two.
67e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  access->AddSideEffects(SideEffects::DependsOnGC());
68e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  DCHECK(address->GetSideEffects().Includes(SideEffects::DependsOnGC()));
69e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  DCHECK(access->GetSideEffects().Includes(SideEffects::DependsOnGC()));
70e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  // TODO: Code generation for HArrayGet and HArraySet will check whether the input address
71e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  // is an HArm64IntermediateAddress and generate appropriate code.
72e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  // We would like to replace the `HArrayGet` and `HArraySet` with custom instructions (maybe
73e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  // `HArm64Load` and `HArm64Store`). We defer these changes because these new instructions would
74e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  // not bring any advantages yet.
75e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  // Also see the comments in
76e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  // `InstructionCodeGeneratorARM64::VisitArrayGet()` and
77e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  // `InstructionCodeGeneratorARM64::VisitArraySet()`.
78e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  RecordSimplification();
79e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames}
80e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames
818626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Ramesbool InstructionSimplifierArm64Visitor::TryMergeIntoShifterOperand(HInstruction* use,
828626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames                                                                   HInstruction* bitfield_op,
838626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames                                                                   bool do_merge) {
848626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  DCHECK(HasShifterOperand(use));
858626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  DCHECK(use->IsBinaryOperation() || use->IsNeg());
868626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  DCHECK(CanFitInShifterOperand(bitfield_op));
878626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  DCHECK(!bitfield_op->HasEnvironmentUses());
888626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
898626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  Primitive::Type type = use->GetType();
908626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  if (type != Primitive::kPrimInt && type != Primitive::kPrimLong) {
918626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    return false;
928626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  }
938626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
948626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  HInstruction* left;
958626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  HInstruction* right;
968626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  if (use->IsBinaryOperation()) {
978626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    left = use->InputAt(0);
988626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    right = use->InputAt(1);
998626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  } else {
1008626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    DCHECK(use->IsNeg());
1018626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    right = use->AsNeg()->InputAt(0);
1028626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    left = GetGraph()->GetConstant(right->GetType(), 0);
1038626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  }
1048626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  DCHECK(left == bitfield_op || right == bitfield_op);
1058626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
1068626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  if (left == right) {
1078626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    // TODO: Handle special transformations in this situation?
1088626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    // For example should we transform `(x << 1) + (x << 1)` into `(x << 2)`?
1098626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    // Or should this be part of a separate transformation logic?
1108626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    return false;
1118626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  }
1128626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
1138626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  bool is_commutative = use->IsBinaryOperation() && use->AsBinaryOperation()->IsCommutative();
1148626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  HInstruction* other_input;
1158626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  if (bitfield_op == right) {
1168626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    other_input = left;
1178626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  } else {
1188626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    if (is_commutative) {
1198626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames      other_input = right;
1208626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    } else {
1218626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames      return false;
1228626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    }
1238626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  }
1248626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
1258626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  HArm64DataProcWithShifterOp::OpKind op_kind;
1268626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  int shift_amount = 0;
1278626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  HArm64DataProcWithShifterOp::GetOpInfoFromInstruction(bitfield_op, &op_kind, &shift_amount);
1288626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
1298626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  if (HArm64DataProcWithShifterOp::IsExtensionOp(op_kind) &&
1308626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames      !ShifterOperandSupportsExtension(use)) {
1318626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    return false;
1328626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  }
1338626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
1348626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  if (do_merge) {
1358626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    HArm64DataProcWithShifterOp* alu_with_op =
1368626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames        new (GetGraph()->GetArena()) HArm64DataProcWithShifterOp(use,
1378626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames                                                                 other_input,
1388626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames                                                                 bitfield_op->InputAt(0),
1398626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames                                                                 op_kind,
1408626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames                                                                 shift_amount,
1418626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames                                                                 use->GetDexPc());
1428626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    use->GetBlock()->ReplaceAndRemoveInstructionWith(use, alu_with_op);
143d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    if (bitfield_op->GetUses().empty()) {
1448626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames      bitfield_op->GetBlock()->RemoveInstruction(bitfield_op);
1458626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    }
1468626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    RecordSimplification();
1478626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  }
1488626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
1498626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  return true;
1508626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames}
1518626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
1528626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames// Merge a bitfield move instruction into its uses if it can be merged in all of them.
1538626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Ramesbool InstructionSimplifierArm64Visitor::TryMergeIntoUsersShifterOperand(HInstruction* bitfield_op) {
1548626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  DCHECK(CanFitInShifterOperand(bitfield_op));
1558626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
1568626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  if (bitfield_op->HasEnvironmentUses()) {
1578626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    return false;
1588626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  }
1598626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
1608626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  const HUseList<HInstruction*>& uses = bitfield_op->GetUses();
1618626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
1628626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  // Check whether we can merge the instruction in all its users' shifter operand.
163d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  for (const HUseListNode<HInstruction*>& use : uses) {
164d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    HInstruction* user = use.GetUser();
165d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    if (!HasShifterOperand(user)) {
1668626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames      return false;
1678626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    }
168d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    if (!CanMergeIntoShifterOperand(user, bitfield_op)) {
1698626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames      return false;
1708626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    }
1718626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  }
1728626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
1738626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  // Merge the instruction into its uses.
174d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko  for (auto it = uses.begin(), end = uses.end(); it != end; /* ++it below */) {
175d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    HInstruction* user = it->GetUser();
176d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    // Increment `it` now because `*it` will disappear thanks to MergeIntoShifterOperand().
177d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    ++it;
178d59f3b1b7f5c1ab9f0731ff9dc60611e8d9a6edeVladimir Marko    bool merged = MergeIntoShifterOperand(user, bitfield_op);
1798626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    DCHECK(merged);
1808626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  }
1818626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
1828626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  return true;
1838626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames}
1848626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
1859ff0d205fd60cba6753a91f613b198ca2d67f04dKevin Brodskyvoid InstructionSimplifierArm64Visitor::VisitAnd(HAnd* instruction) {
1867fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov  if (TryMergeNegatedInput(instruction)) {
1877fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov    RecordSimplification();
1887fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov  }
1899ff0d205fd60cba6753a91f613b198ca2d67f04dKevin Brodsky}
1909ff0d205fd60cba6753a91f613b198ca2d67f04dKevin Brodsky
191e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Ramesvoid InstructionSimplifierArm64Visitor::VisitArrayGet(HArrayGet* instruction) {
192e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  TryExtractArrayAccessAddress(instruction,
193e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames                               instruction->GetArray(),
194e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames                               instruction->GetIndex(),
195e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames                               Primitive::ComponentSize(instruction->GetType()));
196e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames}
197e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames
198e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Ramesvoid InstructionSimplifierArm64Visitor::VisitArraySet(HArraySet* instruction) {
199e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  TryExtractArrayAccessAddress(instruction,
200e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames                               instruction->GetArray(),
201e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames                               instruction->GetIndex(),
202e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames                               Primitive::ComponentSize(instruction->GetComponentType()));
203e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames}
204e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames
205418318f4d50e0cfc2d54330d7623ee030d4d727dAlexandre Ramesvoid InstructionSimplifierArm64Visitor::VisitMul(HMul* instruction) {
2064a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko  if (TryCombineMultiplyAccumulate(instruction, kArm64)) {
2074a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko    RecordSimplification();
208418318f4d50e0cfc2d54330d7623ee030d4d727dAlexandre Rames  }
209418318f4d50e0cfc2d54330d7623ee030d4d727dAlexandre Rames}
210418318f4d50e0cfc2d54330d7623ee030d4d727dAlexandre Rames
2119ff0d205fd60cba6753a91f613b198ca2d67f04dKevin Brodskyvoid InstructionSimplifierArm64Visitor::VisitOr(HOr* instruction) {
2127fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov  if (TryMergeNegatedInput(instruction)) {
2137fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov    RecordSimplification();
2147fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov  }
2159ff0d205fd60cba6753a91f613b198ca2d67f04dKevin Brodsky}
2169ff0d205fd60cba6753a91f613b198ca2d67f04dKevin Brodsky
2178626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Ramesvoid InstructionSimplifierArm64Visitor::VisitShl(HShl* instruction) {
2188626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  if (instruction->InputAt(1)->IsConstant()) {
2198626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    TryMergeIntoUsersShifterOperand(instruction);
2208626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  }
2218626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames}
2228626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
2238626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Ramesvoid InstructionSimplifierArm64Visitor::VisitShr(HShr* instruction) {
2248626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  if (instruction->InputAt(1)->IsConstant()) {
2258626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    TryMergeIntoUsersShifterOperand(instruction);
2268626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  }
2278626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames}
2288626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
2298626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Ramesvoid InstructionSimplifierArm64Visitor::VisitTypeConversion(HTypeConversion* instruction) {
2308626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  Primitive::Type result_type = instruction->GetResultType();
2318626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  Primitive::Type input_type = instruction->GetInputType();
2328626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
2338626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  if (input_type == result_type) {
2348626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    // We let the arch-independent code handle this.
2358626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    return;
2368626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  }
2378626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
2388626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  if (Primitive::IsIntegralType(result_type) && Primitive::IsIntegralType(input_type)) {
2398626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    TryMergeIntoUsersShifterOperand(instruction);
2408626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  }
2418626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames}
2428626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
2438626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Ramesvoid InstructionSimplifierArm64Visitor::VisitUShr(HUShr* instruction) {
2448626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  if (instruction->InputAt(1)->IsConstant()) {
2458626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames    TryMergeIntoUsersShifterOperand(instruction);
2468626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames  }
2478626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames}
2488626b741716390a0119ffeb88b5b9fcf08e13010Alexandre Rames
2499ff0d205fd60cba6753a91f613b198ca2d67f04dKevin Brodskyvoid InstructionSimplifierArm64Visitor::VisitXor(HXor* instruction) {
2507fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov  if (TryMergeNegatedInput(instruction)) {
2517fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov    RecordSimplification();
2527fc6350f6f1ab04b52b9cd7542e0790528296cbeArtem Serov  }
2539ff0d205fd60cba6753a91f613b198ca2d67f04dKevin Brodsky}
2549ff0d205fd60cba6753a91f613b198ca2d67f04dKevin Brodsky
25544b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames}  // namespace arm64
25644b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames}  // namespace art
257