/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "instruction_simplifier.h"

#include "art_method-inl.h"
#include "class_linker-inl.h"
#include "class_root-inl.h"
#include "data_type-inl.h"
#include "driver/compiler_options.h"
#include "escape.h"
#include "intrinsics.h"
#include "intrinsics_utils.h"
#include "mirror/class-inl.h"
#include "optimizing/data_type.h"
#include "optimizing/nodes.h"
#include "scoped_thread_state_change-inl.h"
#include "sharpening.h"
#include "string_builder_append.h"

namespace art HIDDEN {

// Whether to run an exhaustive test of individual HInstructions cloning when each instruction
// is replaced with its copy if it is clonable.
static constexpr bool kTestInstructionClonerExhaustively = false;

class InstructionSimplifierVisitor final : public HGraphDelegateVisitor {
 public:
  InstructionSimplifierVisitor(HGraph* graph,
                               CodeGenerator* codegen,
                               OptimizingCompilerStats* stats,
                               bool be_loop_friendly)
      : HGraphDelegateVisitor(graph),
        codegen_(codegen),
        stats_(stats),
        be_loop_friendly_(be_loop_friendly) {}

  bool Run();

 private:
  void RecordSimplification() {
    simplification_occurred_ = true;
    simplifications_at_current_position_++;
    MaybeRecordStat(stats_, MethodCompilationStat::kInstructionSimplifications);
  }

  bool ReplaceRotateWithRor(HBinaryOperation* op, HUShr* ushr, HShl* shl);
  bool TryReplaceWithRotate(HBinaryOperation* instruction);
  bool TryReplaceWithRotateConstantPattern(HBinaryOperation* op, HUShr* ushr, HShl* shl);
  bool TryReplaceWithRotateRegisterNegPattern(HBinaryOperation* op, HUShr* ushr, HShl* shl);
  bool TryReplaceWithRotateRegisterSubPattern(HBinaryOperation* op, HUShr* ushr, HShl* shl);

  bool TryMoveNegOnInputsAfterBinop(HBinaryOperation* binop);
  // `op` should be either HOr or HAnd.
  // De Morgan's laws:
  // ~a & ~b = ~(a | b)  and  ~a | ~b = ~(a & b)
  bool TryDeMorganNegationFactoring(HBinaryOperation* op);
  bool TryHandleAssociativeAndCommutativeOperation(HBinaryOperation* instruction);
  bool TrySubtractionChainSimplification(HBinaryOperation* instruction);
  bool TryCombineVecMultiplyAccumulate(HVecMul* mul);
  void TryToReuseDiv(HRem* rem);

  void VisitShift(HBinaryOperation* shift);
  void VisitEqual(HEqual* equal) override;
  void VisitNotEqual(HNotEqual* equal) override;
  void VisitBooleanNot(HBooleanNot* bool_not) override;
  void VisitInstanceFieldSet(HInstanceFieldSet* equal) override;
  void VisitStaticFieldSet(HStaticFieldSet* equal) override;
  void VisitArraySet(HArraySet* equal) override;
  void VisitTypeConversion(HTypeConversion* instruction) override;
  void VisitNullCheck(HNullCheck* instruction) override;
  void VisitArrayLength(HArrayLength* instruction) override;
  void VisitCheckCast(HCheckCast* instruction) override;
  void VisitAbs(HAbs* instruction) override;
  void VisitAdd(HAdd* instruction) override;
  void VisitAnd(HAnd* instruction) override;
  void VisitCondition(HCondition* instruction) override;
  void VisitGreaterThan(HGreaterThan* condition) override;
  void VisitGreaterThanOrEqual(HGreaterThanOrEqual* condition) override;
  void VisitLessThan(HLessThan* condition) override;
  void VisitLessThanOrEqual(HLessThanOrEqual* condition) override;
  void VisitBelow(HBelow* condition) override;
  void VisitBelowOrEqual(HBelowOrEqual* condition) override;
  void VisitAbove(HAbove* condition) override;
  void VisitAboveOrEqual(HAboveOrEqual* condition) override;
  void VisitDiv(HDiv* instruction) override;
  void VisitRem(HRem* instruction) override;
  void VisitMul(HMul* instruction) override;
  void VisitNeg(HNeg* instruction) override;
  void VisitNot(HNot* instruction) override;
  void VisitOr(HOr* instruction) override;
  void VisitShl(HShl* instruction) override;
  void VisitShr(HShr* instruction) override;
  void VisitSub(HSub* instruction) override;
  void VisitUShr(HUShr* instruction) override;
  void VisitXor(HXor* instruction) override;
  void VisitSelect(HSelect* select) override;
  void VisitIf(HIf* instruction) override;
  void VisitInstanceOf(HInstanceOf* instruction) override;
  void VisitInvoke(HInvoke* invoke) override;
  void VisitDeoptimize(HDeoptimize* deoptimize) override;
  void VisitVecMul(HVecMul* instruction) override;
  void VisitPredicatedInstanceFieldGet(HPredicatedInstanceFieldGet* instruction) override;
  void SimplifySystemArrayCopy(HInvoke* invoke);
  void SimplifyStringEquals(HInvoke* invoke);
  void SimplifyFP2Int(HInvoke* invoke);
  void SimplifyStringCharAt(HInvoke* invoke);
  void SimplifyStringLength(HInvoke* invoke);
  void SimplifyStringIndexOf(HInvoke* invoke);
  void SimplifyNPEOnArgN(HInvoke* invoke, size_t);
  void SimplifyReturnThis(HInvoke* invoke);
  void SimplifyAllocationIntrinsic(HInvoke* invoke);
  void SimplifyVarHandleIntrinsic(HInvoke* invoke);

  bool CanUseKnownBootImageVarHandle(HInvoke* invoke);
  static bool CanEnsureNotNullAt(HInstruction* input, HInstruction* at);

  CodeGenerator* codegen_;
  OptimizingCompilerStats* stats_;
  bool simplification_occurred_ = false;
  int simplifications_at_current_position_ = 0;
  // Prohibit optimizations which can affect HInductionVarAnalysis/HLoopOptimization
  // and prevent loop optimizations:
  //   true - avoid such optimizations.
  //   false - allow such optimizations.
  // Checked by the following optimizations:
  //   - TryToReuseDiv: simplification of Div+Rem into Div+Mul+Sub.
  bool be_loop_friendly_;
  // We ensure we do not loop infinitely. The value should not be too high, since that
  // would allow looping around the same basic block too many times. The value should
  // not be too low either, however, since we want to allow revisiting a basic block
  // with many statements and simplifications at least once.
  static constexpr int kMaxSamePositionSimplifications = 50;
};

bool InstructionSimplifier::Run() {
  if (kTestInstructionClonerExhaustively) {
    CloneAndReplaceInstructionVisitor visitor(graph_);
    visitor.VisitReversePostOrder();
  }

  bool be_loop_friendly = (use_all_optimizations_ == false);

  InstructionSimplifierVisitor visitor(graph_, codegen_, stats_, be_loop_friendly);
  return visitor.Run();
}

bool InstructionSimplifierVisitor::Run() {
  bool didSimplify = false;
  // Iterate in reverse post order to open up more simplifications to users
  // of instructions that got simplified.
  for (HBasicBlock* block : GetGraph()->GetReversePostOrder()) {
    // The simplification of an instruction to another instruction may yield
    // possibilities for other simplifications. So although we perform a reverse
    // post order visit, we sometimes need to revisit an instruction index.
    do {
      simplification_occurred_ = false;
      VisitBasicBlock(block);
      if (simplification_occurred_) {
        didSimplify = true;
      }
    } while (simplification_occurred_ &&
             (simplifications_at_current_position_ < kMaxSamePositionSimplifications));
    simplifications_at_current_position_ = 0;
  }
  return didSimplify;
}

namespace {

bool AreAllBitsSet(HConstant* constant) {
  return Int64FromConstant(constant) == -1;
}

}  // namespace

// Returns true if the code was simplified to use only one negation operation
// after the binary operation instead of one on each of the inputs.
bool InstructionSimplifierVisitor::TryMoveNegOnInputsAfterBinop(HBinaryOperation* binop) {
  DCHECK(binop->IsAdd() || binop->IsSub());
  DCHECK(binop->GetLeft()->IsNeg() && binop->GetRight()->IsNeg());
  HNeg* left_neg = binop->GetLeft()->AsNeg();
  HNeg* right_neg = binop->GetRight()->AsNeg();
  if (!left_neg->HasOnlyOneNonEnvironmentUse() ||
      !right_neg->HasOnlyOneNonEnvironmentUse()) {
    return false;
  }
  // Replace code looking like
  //    NEG tmp1, a
  //    NEG tmp2, b
  //    ADD dst, tmp1, tmp2
  // with
  //    ADD tmp, a, b
  //    NEG dst, tmp
  // Note that we cannot optimize `(-a) + (-b)` to `-(a + b)` for floating-point.
  // When `a` is `-0.0` and `b` is `0.0`, the former expression yields `0.0`,
  // while the later yields `-0.0`.
  if (!DataType::IsIntegralType(binop->GetType())) {
    return false;
  }
  binop->ReplaceInput(left_neg->GetInput(), 0);
  binop->ReplaceInput(right_neg->GetInput(), 1);
  left_neg->GetBlock()->RemoveInstruction(left_neg);
  right_neg->GetBlock()->RemoveInstruction(right_neg);
  HNeg* neg = new (GetGraph()->GetAllocator()) HNeg(binop->GetType(), binop);
  binop->GetBlock()->InsertInstructionBefore(neg, binop->GetNext());
  binop->ReplaceWithExceptInReplacementAtIndex(neg, 0);
  RecordSimplification();
  return true;
}

bool InstructionSimplifierVisitor::TryDeMorganNegationFactoring(HBinaryOperation* op) {
  DCHECK(op->IsAnd() || op->IsOr()) << op->DebugName();
  DataType::Type type = op->GetType();
  HInstruction* left = op->GetLeft();
  HInstruction* right = op->GetRight();

  // We can apply De Morgan's laws if both inputs are Not's and are only used
  // by `op`.
  if (((left->IsNot() && right->IsNot()) ||
       (left->IsBooleanNot() && right->IsBooleanNot())) &&
      left->HasOnlyOneNonEnvironmentUse() &&
      right->HasOnlyOneNonEnvironmentUse()) {
    // Replace code looking like
    //    NOT nota, a
    //    NOT notb, b
    //    AND dst, nota, notb (respectively OR)
    // with
    //    OR or, a, b         (respectively AND)
    //    NOT dest, or
    HInstruction* src_left = left->InputAt(0);
    HInstruction* src_right = right->InputAt(0);
    uint32_t dex_pc = op->GetDexPc();

    // Remove the negations on the inputs.
    left->ReplaceWith(src_left);
    right->ReplaceWith(src_right);
    left->GetBlock()->RemoveInstruction(left);
    right->GetBlock()->RemoveInstruction(right);

    // Replace the `HAnd` or `HOr`.
    HBinaryOperation* hbin;
    if (op->IsAnd()) {
      hbin = new (GetGraph()->GetAllocator()) HOr(type, src_left, src_right, dex_pc);
    } else {
      hbin = new (GetGraph()->GetAllocator()) HAnd(type, src_left, src_right, dex_pc);
    }
    HInstruction* hnot;
    if (left->IsBooleanNot()) {
      hnot = new (GetGraph()->GetAllocator()) HBooleanNot(hbin, dex_pc);
    } else {
      hnot = new (GetGraph()->GetAllocator()) HNot(type, hbin, dex_pc);
    }

    op->GetBlock()->InsertInstructionBefore(hbin, op);
    op->GetBlock()->ReplaceAndRemoveInstructionWith(op, hnot);

    RecordSimplification();
    return true;
  }

  return false;
}

bool InstructionSimplifierVisitor::TryCombineVecMultiplyAccumulate(HVecMul* mul) {
  DataType::Type type = mul->GetPackedType();
  InstructionSet isa = codegen_->GetInstructionSet();
  switch (isa) {
    case InstructionSet::kArm64:
      if (!(type == DataType::Type::kUint8 ||
            type == DataType::Type::kInt8 ||
            type == DataType::Type::kUint16 ||
            type == DataType::Type::kInt16 ||
            type == DataType::Type::kInt32)) {
        return false;
      }
      break;
    default:
      return false;
  }

  ArenaAllocator* allocator = mul->GetBlock()->GetGraph()->GetAllocator();
  if (!mul->HasOnlyOneNonEnvironmentUse()) {
    return false;
  }
  HInstruction* binop = mul->GetUses().front().GetUser();
  if (!binop->IsVecAdd() && !binop->IsVecSub()) {
    return false;
  }

  // Replace code looking like
  //    VECMUL tmp, x, y
  //    VECADD/SUB dst, acc, tmp
  // with
  //    VECMULACC dst, acc, x, y
  // Note that we do not want to (unconditionally) perform the merge when the
  // multiplication has multiple uses and it can be merged in all of them.
  // Multiple uses could happen on the same control-flow path, and we would
  // then increase the amount of work. In the future we could try to evaluate
  // whether all uses are on different control-flow paths (using dominance and
  // reverse-dominance information) and only perform the merge when they are.
  HInstruction* accumulator = nullptr;
  HVecBinaryOperation* vec_binop = binop->AsVecBinaryOperation();
  HInstruction* binop_left = vec_binop->GetLeft();
  HInstruction* binop_right = vec_binop->GetRight();
  // This is always true since the `HVecMul` has only one use (which is checked above).
  DCHECK_NE(binop_left, binop_right);
  if (binop_right == mul) {
    accumulator = binop_left;
  } else {
    DCHECK_EQ(binop_left, mul);
    // Only addition is commutative.
    if (!binop->IsVecAdd()) {
      return false;
    }
    accumulator = binop_right;
  }

  DCHECK(accumulator != nullptr);
  HInstruction::InstructionKind kind =
      binop->IsVecAdd() ? HInstruction::kAdd : HInstruction::kSub;

  bool predicated_simd = vec_binop->IsPredicated();
  if (predicated_simd && !HVecOperation::HaveSamePredicate(vec_binop, mul)) {
    return false;
  }

  HVecMultiplyAccumulate* mulacc =
      new (allocator) HVecMultiplyAccumulate(allocator,
                                             kind,
                                             accumulator,
                                             mul->GetLeft(),
                                             mul->GetRight(),
                                             vec_binop->GetPackedType(),
                                             vec_binop->GetVectorLength(),
                                             vec_binop->GetDexPc());



  vec_binop->GetBlock()->ReplaceAndRemoveInstructionWith(vec_binop, mulacc);
  if (predicated_simd) {
    mulacc->SetGoverningPredicate(vec_binop->GetGoverningPredicate(),
                                  vec_binop->GetPredicationKind());
  }

  DCHECK(!mul->HasUses());
  mul->GetBlock()->RemoveInstruction(mul);
  return true;
}

void InstructionSimplifierVisitor::VisitShift(HBinaryOperation* instruction) {
  DCHECK(instruction->IsShl() || instruction->IsShr() || instruction->IsUShr());
  HInstruction* shift_amount = instruction->GetRight();
  HInstruction* value = instruction->GetLeft();

  int64_t implicit_mask = (value->GetType() == DataType::Type::kInt64)
      ? kMaxLongShiftDistance
      : kMaxIntShiftDistance;

  if (shift_amount->IsConstant()) {
    int64_t cst = Int64FromConstant(shift_amount->AsConstant());
    int64_t masked_cst = cst & implicit_mask;
    if (masked_cst == 0) {
      // Replace code looking like
      //    SHL dst, value, 0
      // with
      //    value
      instruction->ReplaceWith(value);
      instruction->GetBlock()->RemoveInstruction(instruction);
      RecordSimplification();
      return;
    } else if (masked_cst != cst) {
      // Replace code looking like
      //    SHL dst, value, cst
      // where cst exceeds maximum distance with the equivalent
      //    SHL dst, value, cst & implicit_mask
      // (as defined by shift semantics). This ensures other
      // optimizations do not need to special case for such situations.
      DCHECK_EQ(shift_amount->GetType(), DataType::Type::kInt32);
      instruction->ReplaceInput(GetGraph()->GetIntConstant(masked_cst), /* index= */ 1);
      RecordSimplification();
      return;
    }
  }

  // Shift operations implicitly mask the shift amount according to the type width. Get rid of
  // unnecessary And/Or/Xor/Add/Sub/TypeConversion operations on the shift amount that do not
  // affect the relevant bits.
  // Replace code looking like
  //    AND adjusted_shift, shift, <superset of implicit mask>
  //    [OR/XOR/ADD/SUB adjusted_shift, shift, <value not overlapping with implicit mask>]
  //    [<conversion-from-integral-non-64-bit-type> adjusted_shift, shift]
  //    SHL dst, value, adjusted_shift
  // with
  //    SHL dst, value, shift
  if (shift_amount->IsAnd() ||
      shift_amount->IsOr() ||
      shift_amount->IsXor() ||
      shift_amount->IsAdd() ||
      shift_amount->IsSub()) {
    int64_t required_result = shift_amount->IsAnd() ? implicit_mask : 0;
    HBinaryOperation* bin_op = shift_amount->AsBinaryOperation();
    HConstant* mask = bin_op->GetConstantRight();
    if (mask != nullptr && (Int64FromConstant(mask) & implicit_mask) == required_result) {
      instruction->ReplaceInput(bin_op->GetLeastConstantLeft(), 1);
      RecordSimplification();
      return;
    }
  } else if (shift_amount->IsTypeConversion()) {
    DCHECK_NE(shift_amount->GetType(), DataType::Type::kBool);  // We never convert to bool.
    DataType::Type source_type = shift_amount->InputAt(0)->GetType();
    // Non-integral and 64-bit source types require an explicit type conversion.
    if (DataType::IsIntegralType(source_type) && !DataType::Is64BitType(source_type)) {
      instruction->ReplaceInput(shift_amount->AsTypeConversion()->GetInput(), 1);
      RecordSimplification();
      return;
    }
  }
}

static bool IsSubRegBitsMinusOther(HSub* sub, size_t reg_bits, HInstruction* other) {
  return (sub->GetRight() == other &&
          sub->GetLeft()->IsConstant() &&
          (Int64FromConstant(sub->GetLeft()->AsConstant()) & (reg_bits - 1)) == 0);
}

bool InstructionSimplifierVisitor::ReplaceRotateWithRor(HBinaryOperation* op,
                                                        HUShr* ushr,
                                                        HShl* shl) {
  DCHECK(op->IsAdd() || op->IsXor() || op->IsOr()) << op->DebugName();
  HRor* ror =
      new (GetGraph()->GetAllocator()) HRor(ushr->GetType(), ushr->GetLeft(), ushr->GetRight());
  op->GetBlock()->ReplaceAndRemoveInstructionWith(op, ror);
  if (!ushr->HasUses()) {
    ushr->GetBlock()->RemoveInstruction(ushr);
  }
  if (!ushr->GetRight()->HasUses()) {
    ushr->GetRight()->GetBlock()->RemoveInstruction(ushr->GetRight());
  }
  if (!shl->HasUses()) {
    shl->GetBlock()->RemoveInstruction(shl);
  }
  if (!shl->GetRight()->HasUses()) {
    shl->GetRight()->GetBlock()->RemoveInstruction(shl->GetRight());
  }
  RecordSimplification();
  return true;
}

// Try to replace a binary operation flanked by one UShr and one Shl with a bitfield rotation.
bool InstructionSimplifierVisitor::TryReplaceWithRotate(HBinaryOperation* op) {
  DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
  HInstruction* left = op->GetLeft();
  HInstruction* right = op->GetRight();
  // If we have an UShr and a Shl (in either order).
  if ((left->IsUShr() && right->IsShl()) || (left->IsShl() && right->IsUShr())) {
    HUShr* ushr = left->IsUShr() ? left->AsUShr() : right->AsUShr();
    HShl* shl = left->IsShl() ? left->AsShl() : right->AsShl();
    DCHECK(DataType::IsIntOrLongType(ushr->GetType()));
    if (ushr->GetType() == shl->GetType() &&
        ushr->GetLeft() == shl->GetLeft()) {
      if (ushr->GetRight()->IsConstant() && shl->GetRight()->IsConstant()) {
        // Shift distances are both constant, try replacing with Ror if they
        // add up to the register size.
        return TryReplaceWithRotateConstantPattern(op, ushr, shl);
      } else if (ushr->GetRight()->IsSub() || shl->GetRight()->IsSub()) {
        // Shift distances are potentially of the form x and (reg_size - x).
        return TryReplaceWithRotateRegisterSubPattern(op, ushr, shl);
      } else if (ushr->GetRight()->IsNeg() || shl->GetRight()->IsNeg()) {
        // Shift distances are potentially of the form d and -d.
        return TryReplaceWithRotateRegisterNegPattern(op, ushr, shl);
      }
    }
  }
  return false;
}

// Try replacing code looking like (x >>> #rdist OP x << #ldist):
//    UShr dst, x,   #rdist
//    Shl  tmp, x,   #ldist
//    OP   dst, dst, tmp
// or like (x >>> #rdist OP x << #-ldist):
//    UShr dst, x,   #rdist
//    Shl  tmp, x,   #-ldist
//    OP   dst, dst, tmp
// with
//    Ror  dst, x,   #rdist
bool InstructionSimplifierVisitor::TryReplaceWithRotateConstantPattern(HBinaryOperation* op,
                                                                       HUShr* ushr,
                                                                       HShl* shl) {
  DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
  size_t reg_bits = DataType::Size(ushr->GetType()) * kBitsPerByte;
  size_t rdist = Int64FromConstant(ushr->GetRight()->AsConstant());
  size_t ldist = Int64FromConstant(shl->GetRight()->AsConstant());
  if (((ldist + rdist) & (reg_bits - 1)) == 0) {
    ReplaceRotateWithRor(op, ushr, shl);
    return true;
  }
  return false;
}

// Replace code looking like (x >>> -d OP x << d):
//    Neg  neg, d
//    UShr dst, x,   neg
//    Shl  tmp, x,   d
//    OP   dst, dst, tmp
// with
//    Neg  neg, d
//    Ror  dst, x,   neg
// *** OR ***
// Replace code looking like (x >>> d OP x << -d):
//    UShr dst, x,   d
//    Neg  neg, d
//    Shl  tmp, x,   neg
//    OP   dst, dst, tmp
// with
//    Ror  dst, x,   d
bool InstructionSimplifierVisitor::TryReplaceWithRotateRegisterNegPattern(HBinaryOperation* op,
                                                                          HUShr* ushr,
                                                                          HShl* shl) {
  DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
  DCHECK(ushr->GetRight()->IsNeg() || shl->GetRight()->IsNeg());
  bool neg_is_left = shl->GetRight()->IsNeg();
  HNeg* neg = neg_is_left ? shl->GetRight()->AsNeg() : ushr->GetRight()->AsNeg();
  // And the shift distance being negated is the distance being shifted the other way.
  if (neg->InputAt(0) == (neg_is_left ? ushr->GetRight() : shl->GetRight())) {
    ReplaceRotateWithRor(op, ushr, shl);
  }
  return false;
}

// Try replacing code looking like (x >>> d OP x << (#bits - d)):
//    UShr dst, x,     d
//    Sub  ld,  #bits, d
//    Shl  tmp, x,     ld
//    OP   dst, dst,   tmp
// with
//    Ror  dst, x,     d
// *** OR ***
// Replace code looking like (x >>> (#bits - d) OP x << d):
//    Sub  rd,  #bits, d
//    UShr dst, x,     rd
//    Shl  tmp, x,     d
//    OP   dst, dst,   tmp
// with
//    Neg  neg, d
//    Ror  dst, x,     neg
bool InstructionSimplifierVisitor::TryReplaceWithRotateRegisterSubPattern(HBinaryOperation* op,
                                                                          HUShr* ushr,
                                                                          HShl* shl) {
  DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
  DCHECK(ushr->GetRight()->IsSub() || shl->GetRight()->IsSub());
  size_t reg_bits = DataType::Size(ushr->GetType()) * kBitsPerByte;
  HInstruction* shl_shift = shl->GetRight();
  HInstruction* ushr_shift = ushr->GetRight();
  if ((shl_shift->IsSub() && IsSubRegBitsMinusOther(shl_shift->AsSub(), reg_bits, ushr_shift)) ||
      (ushr_shift->IsSub() && IsSubRegBitsMinusOther(ushr_shift->AsSub(), reg_bits, shl_shift))) {
    return ReplaceRotateWithRor(op, ushr, shl);
  }
  return false;
}

void InstructionSimplifierVisitor::VisitNullCheck(HNullCheck* null_check) {
  HInstruction* obj = null_check->InputAt(0);
  if (!obj->CanBeNull()) {
    null_check->ReplaceWith(obj);
    null_check->GetBlock()->RemoveInstruction(null_check);
    if (stats_ != nullptr) {
      stats_->RecordStat(MethodCompilationStat::kRemovedNullCheck);
    }
  }
}

bool InstructionSimplifierVisitor::CanEnsureNotNullAt(HInstruction* input, HInstruction* at) {
  if (!input->CanBeNull()) {
    return true;
  }

  for (const HUseListNode<HInstruction*>& use : input->GetUses()) {
    HInstruction* user = use.GetUser();
    if (user->IsNullCheck() && user->StrictlyDominates(at)) {
      return true;
    }
  }

  return false;
}

// Returns whether doing a type test between the class of `object` against `klass` has
// a statically known outcome. The result of the test is stored in `outcome`.
static bool TypeCheckHasKnownOutcome(ReferenceTypeInfo class_rti,
                                     HInstruction* object,
                                     /*out*/bool* outcome) {
  DCHECK(!object->IsNullConstant()) << "Null constants should be special cased";
  ReferenceTypeInfo obj_rti = object->GetReferenceTypeInfo();
  ScopedObjectAccess soa(Thread::Current());
  if (!obj_rti.IsValid()) {
    // We run the simplifier before the reference type propagation so type info might not be
    // available.
    return false;
  }

  if (!class_rti.IsValid()) {
    // Happens when the loaded class is unresolved.
    if (obj_rti.IsExact()) {
      // outcome == 'true' && obj_rti is valid implies that class_rti is valid.
      // Since that's a contradiction we must not pass this check.
      *outcome = false;
      return true;
    } else {
      // We aren't able to say anything in particular since we don't know the
      // exact type of the object.
      return false;
    }
  }
  DCHECK(class_rti.IsExact());
  if (class_rti.IsSupertypeOf(obj_rti)) {
    *outcome = true;
    return true;
  } else if (obj_rti.IsExact()) {
    // The test failed at compile time so will also fail at runtime.
    *outcome = false;
    return true;
  } else if (!class_rti.IsInterface()
             && !obj_rti.IsInterface()
             && !obj_rti.IsSupertypeOf(class_rti)) {
    // Different type hierarchy. The test will fail.
    *outcome = false;
    return true;
  }
  return false;
}

void InstructionSimplifierVisitor::VisitCheckCast(HCheckCast* check_cast) {
  HInstruction* object = check_cast->InputAt(0);
  if (CanEnsureNotNullAt(object, check_cast)) {
    check_cast->ClearMustDoNullCheck();
  }

  if (object->IsNullConstant()) {
    check_cast->GetBlock()->RemoveInstruction(check_cast);
    MaybeRecordStat(stats_, MethodCompilationStat::kRemovedCheckedCast);
    return;
  }

  // Minor correctness check.
  DCHECK(check_cast->GetTargetClass()->StrictlyDominates(check_cast))
      << "Illegal graph!\n"
      << check_cast->DumpWithArgs();

  // Historical note: The `outcome` was initialized to please Valgrind - the compiler can reorder
  // the return value check with the `outcome` check, b/27651442.
  bool outcome = false;
  if (TypeCheckHasKnownOutcome(check_cast->GetTargetClassRTI(), object, &outcome)) {
    if (outcome) {
      check_cast->GetBlock()->RemoveInstruction(check_cast);
      MaybeRecordStat(stats_, MethodCompilationStat::kRemovedCheckedCast);
      if (check_cast->GetTypeCheckKind() != TypeCheckKind::kBitstringCheck) {
        HLoadClass* load_class = check_cast->GetTargetClass();
        if (!load_class->HasUses() && !load_class->NeedsAccessCheck()) {
          // We cannot rely on DCE to remove the class because the `HLoadClass` thinks it can throw.
          // However, here we know that it cannot because the checkcast was successful, hence
          // the class was already loaded.
          load_class->GetBlock()->RemoveInstruction(load_class);
        }
      }
    } else {
      // TODO Don't do anything for exceptional cases for now. Ideally we should
      // remove all instructions and blocks this instruction dominates and
      // replace it with a manual throw.
    }
  }
}

void InstructionSimplifierVisitor::VisitInstanceOf(HInstanceOf* instruction) {
  HInstruction* object = instruction->InputAt(0);

  bool can_be_null = true;
  if (CanEnsureNotNullAt(object, instruction)) {
    can_be_null = false;
    instruction->ClearMustDoNullCheck();
  }

  HGraph* graph = GetGraph();
  if (object->IsNullConstant()) {
    MaybeRecordStat(stats_, MethodCompilationStat::kRemovedInstanceOf);
    instruction->ReplaceWith(graph->GetIntConstant(0));
    instruction->GetBlock()->RemoveInstruction(instruction);
    RecordSimplification();
    return;
  }

  // Minor correctness check.
  DCHECK(instruction->GetTargetClass()->StrictlyDominates(instruction))
      << "Illegal graph!\n"
      << instruction->DumpWithArgs();

  // Historical note: The `outcome` was initialized to please Valgrind - the compiler can reorder
  // the return value check with the `outcome` check, b/27651442.
  bool outcome = false;
  if (TypeCheckHasKnownOutcome(instruction->GetTargetClassRTI(), object, &outcome)) {
    MaybeRecordStat(stats_, MethodCompilationStat::kRemovedInstanceOf);
    if (outcome && can_be_null) {
      // Type test will succeed, we just need a null test.
      HNotEqual* test = new (graph->GetAllocator()) HNotEqual(graph->GetNullConstant(), object);
      instruction->GetBlock()->InsertInstructionBefore(test, instruction);
      instruction->ReplaceWith(test);
    } else {
      // We've statically determined the result of the instanceof.
      instruction->ReplaceWith(graph->GetIntConstant(outcome));
    }
    RecordSimplification();
    instruction->GetBlock()->RemoveInstruction(instruction);
    if (outcome && instruction->GetTypeCheckKind() != TypeCheckKind::kBitstringCheck) {
      HLoadClass* load_class = instruction->GetTargetClass();
      if (!load_class->HasUses() && !load_class->NeedsAccessCheck()) {
        // We cannot rely on DCE to remove the class because the `HLoadClass`
        // thinks it can throw. However, here we know that it cannot because the
        // instanceof check was successful and we don't need to check the
        // access, hence the class was already loaded.
        load_class->GetBlock()->RemoveInstruction(load_class);
      }
    }
  }
}

void InstructionSimplifierVisitor::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
  if ((instruction->GetValue()->GetType() == DataType::Type::kReference)
      && CanEnsureNotNullAt(instruction->GetValue(), instruction)) {
    instruction->ClearValueCanBeNull();
  }
}

void InstructionSimplifierVisitor::VisitStaticFieldSet(HStaticFieldSet* instruction) {
  if ((instruction->GetValue()->GetType() == DataType::Type::kReference)
      && CanEnsureNotNullAt(instruction->GetValue(), instruction)) {
    instruction->ClearValueCanBeNull();
  }
}

static HCondition* GetOppositeConditionSwapOps(ArenaAllocator* allocator, HInstruction* cond) {
  HInstruction *lhs = cond->InputAt(0);
  HInstruction *rhs = cond->InputAt(1);
  switch (cond->GetKind()) {
    case HInstruction::kEqual:
      return new (allocator) HEqual(rhs, lhs);
    case HInstruction::kNotEqual:
      return new (allocator) HNotEqual(rhs, lhs);
    case HInstruction::kLessThan:
      return new (allocator) HGreaterThan(rhs, lhs);
    case HInstruction::kLessThanOrEqual:
      return new (allocator) HGreaterThanOrEqual(rhs, lhs);
    case HInstruction::kGreaterThan:
      return new (allocator) HLessThan(rhs, lhs);
    case HInstruction::kGreaterThanOrEqual:
      return new (allocator) HLessThanOrEqual(rhs, lhs);
    case HInstruction::kBelow:
      return new (allocator) HAbove(rhs, lhs);
    case HInstruction::kBelowOrEqual:
      return new (allocator) HAboveOrEqual(rhs, lhs);
    case HInstruction::kAbove:
      return new (allocator) HBelow(rhs, lhs);
    case HInstruction::kAboveOrEqual:
      return new (allocator) HBelowOrEqual(rhs, lhs);
    default:
      LOG(FATAL) << "Unknown ConditionType " << cond->GetKind();
      UNREACHABLE();
  }
}

void InstructionSimplifierVisitor::VisitEqual(HEqual* equal) {
  HInstruction* input_const = equal->GetConstantRight();
  if (input_const != nullptr) {
    HInstruction* input_value = equal->GetLeastConstantLeft();
    if ((input_value->GetType() == DataType::Type::kBool) && input_const->IsIntConstant()) {
      HBasicBlock* block = equal->GetBlock();
      // We are comparing the boolean to a constant which is of type int and can
      // be any constant.
      if (input_const->AsIntConstant()->IsTrue()) {
        // Replace (bool_value == true) with bool_value
        equal->ReplaceWith(input_value);
        block->RemoveInstruction(equal);
        RecordSimplification();
      } else if (input_const->AsIntConstant()->IsFalse()) {
        // Replace (bool_value == false) with !bool_value
        equal->ReplaceWith(GetGraph()->InsertOppositeCondition(input_value, equal));
        block->RemoveInstruction(equal);
        RecordSimplification();
      } else {
        // Replace (bool_value == integer_not_zero_nor_one_constant) with false
        equal->ReplaceWith(GetGraph()->GetIntConstant(0));
        block->RemoveInstruction(equal);
        RecordSimplification();
      }
    } else {
      VisitCondition(equal);
    }
  } else {
    VisitCondition(equal);
  }
}

void InstructionSimplifierVisitor::VisitNotEqual(HNotEqual* not_equal) {
  HInstruction* input_const = not_equal->GetConstantRight();
  if (input_const != nullptr) {
    HInstruction* input_value = not_equal->GetLeastConstantLeft();
    if ((input_value->GetType() == DataType::Type::kBool) && input_const->IsIntConstant()) {
      HBasicBlock* block = not_equal->GetBlock();
      // We are comparing the boolean to a constant which is of type int and can
      // be any constant.
      if (input_const->AsIntConstant()->IsTrue()) {
        // Replace (bool_value != true) with !bool_value
        not_equal->ReplaceWith(GetGraph()->InsertOppositeCondition(input_value, not_equal));
        block->RemoveInstruction(not_equal);
        RecordSimplification();
      } else if (input_const->AsIntConstant()->IsFalse()) {
        // Replace (bool_value != false) with bool_value
        not_equal->ReplaceWith(input_value);
        block->RemoveInstruction(not_equal);
        RecordSimplification();
      } else {
        // Replace (bool_value != integer_not_zero_nor_one_constant) with true
        not_equal->ReplaceWith(GetGraph()->GetIntConstant(1));
        block->RemoveInstruction(not_equal);
        RecordSimplification();
      }
    } else {
      VisitCondition(not_equal);
    }
  } else {
    VisitCondition(not_equal);
  }
}

void InstructionSimplifierVisitor::VisitBooleanNot(HBooleanNot* bool_not) {
  HInstruction* input = bool_not->InputAt(0);
  HInstruction* replace_with = nullptr;

  if (input->IsIntConstant()) {
    // Replace !(true/false) with false/true.
    if (input->AsIntConstant()->IsTrue()) {
      replace_with = GetGraph()->GetIntConstant(0);
    } else {
      DCHECK(input->AsIntConstant()->IsFalse()) << input->AsIntConstant()->GetValue();
      replace_with = GetGraph()->GetIntConstant(1);
    }
  } else if (input->IsBooleanNot()) {
    // Replace (!(!bool_value)) with bool_value.
    replace_with = input->InputAt(0);
  } else if (input->IsCondition() &&
             // Don't change FP compares. The definition of compares involving
             // NaNs forces the compares to be done as written by the user.
             !DataType::IsFloatingPointType(input->InputAt(0)->GetType())) {
    // Replace condition with its opposite.
    replace_with = GetGraph()->InsertOppositeCondition(input->AsCondition(), bool_not);
  }

  if (replace_with != nullptr) {
    bool_not->ReplaceWith(replace_with);
    bool_not->GetBlock()->RemoveInstruction(bool_not);
    RecordSimplification();
  }
}

// Constructs a new ABS(x) node in the HIR.
static HInstruction* NewIntegralAbs(ArenaAllocator* allocator,
                                    HInstruction* x,
                                    HInstruction* cursor) {
  DataType::Type type = DataType::Kind(x->GetType());
  DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64);
  HAbs* abs = new (allocator) HAbs(type, x, cursor->GetDexPc());
  cursor->GetBlock()->InsertInstructionBefore(abs, cursor);
  return abs;
}

// Constructs a new MIN/MAX(x, y) node in the HIR.
static HInstruction* NewIntegralMinMax(ArenaAllocator* allocator,
                                       HInstruction* x,
                                       HInstruction* y,
                                       HInstruction* cursor,
                                       bool is_min) {
  DataType::Type type = DataType::Kind(x->GetType());
  DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64);
  HBinaryOperation* minmax = nullptr;
  if (is_min) {
    minmax = new (allocator) HMin(type, x, y, cursor->GetDexPc());
  } else {
    minmax = new (allocator) HMax(type, x, y, cursor->GetDexPc());
  }
  cursor->GetBlock()->InsertInstructionBefore(minmax, cursor);
  return minmax;
}

// Returns true if operands a and b consists of widening type conversions
// (either explicit or implicit) to the given to_type.
static bool AreLowerPrecisionArgs(DataType::Type to_type, HInstruction* a, HInstruction* b) {
  if (a->IsTypeConversion() && a->GetType() == to_type) {
    a = a->InputAt(0);
  }
  if (b->IsTypeConversion() && b->GetType() == to_type) {
    b = b->InputAt(0);
  }
  DataType::Type type1 = a->GetType();
  DataType::Type type2 = b->GetType();
  return (type1 == DataType::Type::kUint8  && type2 == DataType::Type::kUint8) ||
         (type1 == DataType::Type::kInt8   && type2 == DataType::Type::kInt8) ||
         (type1 == DataType::Type::kInt16  && type2 == DataType::Type::kInt16) ||
         (type1 == DataType::Type::kUint16 && type2 == DataType::Type::kUint16) ||
         (type1 == DataType::Type::kInt32  && type2 == DataType::Type::kInt32 &&
          to_type == DataType::Type::kInt64);
}

// Returns an acceptable substitution for "a" on the select
// construct "a <cmp> b ? c : .."  during MIN/MAX recognition.
static HInstruction* AllowInMinMax(IfCondition cmp,
                                   HInstruction* a,
                                   HInstruction* b,
                                   HInstruction* c) {
  int64_t value = 0;
  if (IsInt64AndGet(b, /*out*/ &value) &&
      (((cmp == kCondLT || cmp == kCondLE) && c->IsMax()) ||
       ((cmp == kCondGT || cmp == kCondGE) && c->IsMin()))) {
    HConstant* other = c->AsBinaryOperation()->GetConstantRight();
    if (other != nullptr && a == c->AsBinaryOperation()->GetLeastConstantLeft()) {
      int64_t other_value = Int64FromConstant(other);
      bool is_max = (cmp == kCondLT || cmp == kCondLE);
      // Allow the max for a <  100 ? max(a, -100) : ..
      //    or the min for a > -100 ? min(a,  100) : ..
      if (is_max ? (value >= other_value) : (value <= other_value)) {
        return c;
      }
    }
  }
  return nullptr;
}

// TODO This should really be done by LSE itself since there is significantly
// more information available there.
void InstructionSimplifierVisitor::VisitPredicatedInstanceFieldGet(
    HPredicatedInstanceFieldGet* pred_get) {
  HInstruction* target = pred_get->GetTarget();
  HInstruction* default_val = pred_get->GetDefaultValue();
  if (target->IsNullConstant()) {
    pred_get->ReplaceWith(default_val);
    pred_get->GetBlock()->RemoveInstruction(pred_get);
    RecordSimplification();
    return;
  } else if (!target->CanBeNull()) {
    HInstruction* replace_with = new (GetGraph()->GetAllocator())
        HInstanceFieldGet(pred_get->GetTarget(),
                          pred_get->GetFieldInfo().GetField(),
                          pred_get->GetFieldType(),
                          pred_get->GetFieldOffset(),
                          pred_get->IsVolatile(),
                          pred_get->GetFieldInfo().GetFieldIndex(),
                          pred_get->GetFieldInfo().GetDeclaringClassDefIndex(),
                          pred_get->GetFieldInfo().GetDexFile(),
                          pred_get->GetDexPc());
    if (pred_get->GetType() == DataType::Type::kReference) {
      replace_with->SetReferenceTypeInfoIfValid(pred_get->GetReferenceTypeInfo());
    }
    pred_get->GetBlock()->InsertInstructionBefore(replace_with, pred_get);
    pred_get->ReplaceWith(replace_with);
    pred_get->GetBlock()->RemoveInstruction(pred_get);
    RecordSimplification();
    return;
  }
  if (!target->IsPhi() || !default_val->IsPhi() || default_val->GetBlock() != target->GetBlock()) {
    // The iget has already been reduced. We know the target or the phi
    // selection will differ between the target and default.
    return;
  }
  DCHECK_EQ(default_val->InputCount(), target->InputCount());
  // In the same block both phis only one non-null we can remove the phi from default_val.
  HInstruction* single_value = nullptr;
  auto inputs = target->GetInputs();
  for (auto [input, idx] : ZipCount(MakeIterationRange(inputs))) {
    if (input->CanBeNull()) {
      if (single_value == nullptr) {
        single_value = default_val->InputAt(idx);
      } else if (single_value != default_val->InputAt(idx) &&
                 !single_value->Equals(default_val->InputAt(idx))) {
        // Multiple values are associated with potential nulls, can't combine.
        return;
      }
    }
  }
  DCHECK(single_value != nullptr) << "All target values are non-null but the phi as a whole still"
                                  << " can be null? This should not be possible." << std::endl
                                  << pred_get->DumpWithArgs();
  if (single_value->StrictlyDominates(pred_get)) {
    // Combine all the maybe null values into one.
    pred_get->ReplaceInput(single_value, 0);
    RecordSimplification();
  }
}

void InstructionSimplifierVisitor::VisitSelect(HSelect* select) {
  HInstruction* replace_with = nullptr;
  HInstruction* condition = select->GetCondition();
  HInstruction* true_value = select->GetTrueValue();
  HInstruction* false_value = select->GetFalseValue();

  if (condition->IsBooleanNot()) {
    // Change ((!cond) ? x : y) to (cond ? y : x).
    condition = condition->InputAt(0);
    std::swap(true_value, false_value);
    select->ReplaceInput(false_value, 0);
    select->ReplaceInput(true_value, 1);
    select->ReplaceInput(condition, 2);
    RecordSimplification();
  }

  if (true_value == false_value) {
    // Replace (cond ? x : x) with (x).
    replace_with = true_value;
  } else if (condition->IsIntConstant()) {
    if (condition->AsIntConstant()->IsTrue()) {
      // Replace (true ? x : y) with (x).
      replace_with = true_value;
    } else {
      // Replace (false ? x : y) with (y).
      DCHECK(condition->AsIntConstant()->IsFalse()) << condition->AsIntConstant()->GetValue();
      replace_with = false_value;
    }
  } else if (true_value->IsIntConstant() && false_value->IsIntConstant()) {
    if (true_value->AsIntConstant()->IsTrue() && false_value->AsIntConstant()->IsFalse()) {
      // Replace (cond ? true : false) with (cond).
      replace_with = condition;
    } else if (true_value->AsIntConstant()->IsFalse() && false_value->AsIntConstant()->IsTrue()) {
      // Replace (cond ? false : true) with (!cond).
      replace_with = GetGraph()->InsertOppositeCondition(condition, select);
    }
  } else if (condition->IsCondition()) {
    IfCondition cmp = condition->AsCondition()->GetCondition();
    HInstruction* a = condition->InputAt(0);
    HInstruction* b = condition->InputAt(1);
    DataType::Type t_type = true_value->GetType();
    DataType::Type f_type = false_value->GetType();
    if (DataType::IsIntegralType(t_type) && DataType::Kind(t_type) == DataType::Kind(f_type)) {
      if (cmp == kCondEQ || cmp == kCondNE) {
        // Turns
        // * Select[a, b, EQ(a,b)] / Select[a, b, EQ(b,a)] into a
        // * Select[a, b, NE(a,b)] / Select[a, b, NE(b,a)] into b
        // Note that the order in EQ/NE is irrelevant.
        if ((a == true_value && b == false_value) || (a == false_value && b == true_value)) {
          replace_with = cmp == kCondEQ ? false_value : true_value;
        }
      } else {
        // Test if both values are compatible integral types (resulting MIN/MAX/ABS
        // type will be int or long, like the condition). Replacements are general,
        // but assume conditions prefer constants on the right.

        // Allow a <  100 ? max(a, -100) : ..
        //    or a > -100 ? min(a,  100) : ..
        // to use min/max instead of a to detect nested min/max expressions.
        HInstruction* new_a = AllowInMinMax(cmp, a, b, true_value);
        if (new_a != nullptr) {
          a = new_a;
        }
        // Try to replace typical integral MIN/MAX/ABS constructs.
        if ((cmp == kCondLT || cmp == kCondLE || cmp == kCondGT || cmp == kCondGE) &&
            ((a == true_value && b == false_value) || (b == true_value && a == false_value))) {
          // Found a < b ? a : b (MIN) or a < b ? b : a (MAX)
          //    or a > b ? a : b (MAX) or a > b ? b : a (MIN).
          bool is_min = (cmp == kCondLT || cmp == kCondLE) == (a == true_value);
          replace_with = NewIntegralMinMax(GetGraph()->GetAllocator(), a, b, select, is_min);
        } else if (((cmp == kCondLT || cmp == kCondLE) && true_value->IsNeg()) ||
                   ((cmp == kCondGT || cmp == kCondGE) && false_value->IsNeg())) {
          bool negLeft = (cmp == kCondLT || cmp == kCondLE);
          HInstruction* the_negated = negLeft ? true_value->InputAt(0) : false_value->InputAt(0);
          HInstruction* not_negated = negLeft ? false_value : true_value;
          if (a == the_negated && a == not_negated && IsInt64Value(b, 0)) {
            // Found a < 0 ? -a :  a
            //    or a > 0 ?  a : -a
            // which can be replaced by ABS(a).
            replace_with = NewIntegralAbs(GetGraph()->GetAllocator(), a, select);
          }
        } else if (true_value->IsSub() && false_value->IsSub()) {
          HInstruction* true_sub1 = true_value->InputAt(0);
          HInstruction* true_sub2 = true_value->InputAt(1);
          HInstruction* false_sub1 = false_value->InputAt(0);
          HInstruction* false_sub2 = false_value->InputAt(1);
          if ((((cmp == kCondGT || cmp == kCondGE) &&
                (a == true_sub1 && b == true_sub2 && a == false_sub2 && b == false_sub1)) ||
               ((cmp == kCondLT || cmp == kCondLE) &&
                (a == true_sub2 && b == true_sub1 && a == false_sub1 && b == false_sub2))) &&
              AreLowerPrecisionArgs(t_type, a, b)) {
            // Found a > b ? a - b  : b - a
            //    or a < b ? b - a  : a - b
            // which can be replaced by ABS(a - b) for lower precision operands a, b.
            replace_with = NewIntegralAbs(GetGraph()->GetAllocator(), true_value, select);
          }
        }
      }
    }
  }

  if (replace_with != nullptr) {
    select->ReplaceWith(replace_with);
    select->GetBlock()->RemoveInstruction(select);
    RecordSimplification();
  }
}

void InstructionSimplifierVisitor::VisitIf(HIf* instruction) {
  HInstruction* condition = instruction->InputAt(0);
  if (condition->IsBooleanNot()) {
    // Swap successors if input is negated.
    instruction->ReplaceInput(condition->InputAt(0), 0);
    instruction->GetBlock()->SwapSuccessors();
    RecordSimplification();
  }
}

// TODO(solanes): This optimization should be in ConstantFolding since we are folding to a constant.
// However, we get code size regressions when we do that since we sometimes have a NullCheck between
// HArrayLength and IsNewArray, and said NullCheck is eliminated in InstructionSimplifier. If we run
// ConstantFolding and InstructionSimplifier in lockstep this wouldn't be an issue.
void InstructionSimplifierVisitor::VisitArrayLength(HArrayLength* instruction) {
  HInstruction* input = instruction->InputAt(0);
  // If the array is a NewArray with constant size, replace the array length
  // with the constant instruction. This helps the bounds check elimination phase.
  if (input->IsNewArray()) {
    input = input->AsNewArray()->GetLength();
    if (input->IsIntConstant()) {
      instruction->ReplaceWith(input);
    }
  }
}

void InstructionSimplifierVisitor::VisitArraySet(HArraySet* instruction) {
  HInstruction* value = instruction->GetValue();
  if (value->GetType() != DataType::Type::kReference) {
    return;
  }

  if (CanEnsureNotNullAt(value, instruction)) {
    instruction->ClearValueCanBeNull();
  }

  if (value->IsArrayGet()) {
    if (value->AsArrayGet()->GetArray() == instruction->GetArray()) {
      // If the code is just swapping elements in the array, no need for a type check.
      instruction->ClearTypeCheck();
      return;
    }
  }

  if (value->IsNullConstant()) {
    instruction->ClearTypeCheck();
    return;
  }

  ScopedObjectAccess soa(Thread::Current());
  ReferenceTypeInfo array_rti = instruction->GetArray()->GetReferenceTypeInfo();
  ReferenceTypeInfo value_rti = value->GetReferenceTypeInfo();
  if (!array_rti.IsValid()) {
    return;
  }

  if (value_rti.IsValid() && array_rti.CanArrayHold(value_rti)) {
    instruction->ClearTypeCheck();
    return;
  }

  if (array_rti.IsObjectArray()) {
    if (array_rti.IsExact()) {
      instruction->ClearTypeCheck();
      return;
    }
    instruction->SetStaticTypeOfArrayIsObjectArray();
  }
}

static bool IsTypeConversionLossless(DataType::Type input_type, DataType::Type result_type) {
  // Make sure all implicit conversions have been simplified and no new ones have been introduced.
  DCHECK(!DataType::IsTypeConversionImplicit(input_type, result_type))
      << input_type << "," << result_type;
  // The conversion to a larger type is loss-less with the exception of two cases,
  //   - conversion to the unsigned type Uint16, where we may lose some bits, and
  //   - conversion from float to long, the only FP to integral conversion with smaller FP type.
  // For integral to FP conversions this holds because the FP mantissa is large enough.
  // Note: The size check excludes Uint8 as the result type.
  return DataType::Size(result_type) > DataType::Size(input_type) &&
      result_type != DataType::Type::kUint16 &&
      !(result_type == DataType::Type::kInt64 && input_type == DataType::Type::kFloat32);
}

static bool CanRemoveRedundantAnd(HConstant* and_right,
                                  HConstant* shr_right,
                                  DataType::Type result_type) {
  int64_t and_cst = Int64FromConstant(and_right);
  int64_t shr_cst = Int64FromConstant(shr_right);

  // In the following sequence A is the input value, D is the result:
  // B := A & x
  // C := B >> r
  // D := TypeConv(n-bit type) C

  // The value of D is entirely dependent on the bits [n-1:0] of C, which in turn are dependent
  // on bits [r+n-1:r] of B.
  // Therefore, if the AND does not change bits [r+n-1:r] of A then it will not affect D.
  // This can be checked by ensuring that bits [r+n-1:r] of the AND Constant are 1.

  // For example: return (byte) ((value & 0xff00) >> 8)
  //              return (byte) ((value & 0xff000000) >> 31)

  // The mask sets bits [r+n-1:r] to 1, and all others to 0.
  int64_t mask = DataType::MaxValueOfIntegralType(DataType::ToUnsigned(result_type)) << shr_cst;

  // If the result of a bitwise AND between the mask and the AND constant is the original mask, then
  // the AND does not change bits [r+n-1:r], meaning that it is redundant and can be removed.
  return ((and_cst & mask) == mask);
}

static inline bool TryReplaceFieldOrArrayGetType(HInstruction* maybe_get, DataType::Type new_type) {
  if (maybe_get->IsInstanceFieldGet()) {
    maybe_get->AsInstanceFieldGet()->SetType(new_type);
    return true;
  } else if (maybe_get->IsPredicatedInstanceFieldGet()) {
    maybe_get->AsPredicatedInstanceFieldGet()->SetType(new_type);
    return true;
  } else if (maybe_get->IsStaticFieldGet()) {
    maybe_get->AsStaticFieldGet()->SetType(new_type);
    return true;
  } else if (maybe_get->IsArrayGet() && !maybe_get->AsArrayGet()->IsStringCharAt()) {
    maybe_get->AsArrayGet()->SetType(new_type);
    return true;
  } else {
    return false;
  }
}

// The type conversion is only used for storing into a field/element of the
// same/narrower size.
static bool IsTypeConversionForStoringIntoNoWiderFieldOnly(HTypeConversion* type_conversion) {
  if (type_conversion->HasEnvironmentUses()) {
    return false;
  }
  DataType::Type input_type = type_conversion->GetInputType();
  DataType::Type result_type = type_conversion->GetResultType();
  if (!DataType::IsIntegralType(input_type) ||
      !DataType::IsIntegralType(result_type) ||
      input_type == DataType::Type::kInt64 ||
      result_type == DataType::Type::kInt64) {
    // Type conversion is needed if non-integer types are involved, or 64-bit
    // types are involved, which may use different number of registers.
    return false;
  }
  if (DataType::Size(input_type) >= DataType::Size(result_type)) {
    // Type conversion is not necessary when storing to a field/element of the
    // same/smaller size.
  } else {
    // We do not handle this case here.
    return false;
  }

  // Check if the converted value is only used for storing into heap.
  for (const HUseListNode<HInstruction*>& use : type_conversion->GetUses()) {
    HInstruction* instruction = use.GetUser();
    if (instruction->IsInstanceFieldSet() &&
        instruction->AsInstanceFieldSet()->GetFieldType() == result_type) {
      DCHECK_EQ(instruction->AsInstanceFieldSet()->GetValue(), type_conversion);
      continue;
    }
    if (instruction->IsStaticFieldSet() &&
        instruction->AsStaticFieldSet()->GetFieldType() == result_type) {
      DCHECK_EQ(instruction->AsStaticFieldSet()->GetValue(), type_conversion);
      continue;
    }
    if (instruction->IsArraySet() &&
        instruction->AsArraySet()->GetComponentType() == result_type &&
        // not index use.
        instruction->AsArraySet()->GetIndex() != type_conversion) {
      DCHECK_EQ(instruction->AsArraySet()->GetValue(), type_conversion);
      continue;
    }
    // The use is not as a store value, or the field/element type is not the
    // same as the result_type, keep the type conversion.
    return false;
  }
  // Codegen automatically handles the type conversion during the store.
  return true;
}

void InstructionSimplifierVisitor::VisitTypeConversion(HTypeConversion* instruction) {
  HInstruction* input = instruction->GetInput();
  DataType::Type input_type = input->GetType();
  DataType::Type result_type = instruction->GetResultType();
  if (instruction->IsImplicitConversion()) {
    instruction->ReplaceWith(input);
    instruction->GetBlock()->RemoveInstruction(instruction);
    RecordSimplification();
    return;
  }

  if (input->IsTypeConversion()) {
    HTypeConversion* input_conversion = input->AsTypeConversion();
    HInstruction* original_input = input_conversion->GetInput();
    DataType::Type original_type = original_input->GetType();

    // When the first conversion is lossless, a direct conversion from the original type
    // to the final type yields the same result, even for a lossy second conversion, for
    // example float->double->int or int->double->float.
    bool is_first_conversion_lossless = IsTypeConversionLossless(original_type, input_type);

    // For integral conversions, see if the first conversion loses only bits that the second
    // doesn't need, i.e. the final type is no wider than the intermediate. If so, direct
    // conversion yields the same result, for example long->int->short or int->char->short.
    bool integral_conversions_with_non_widening_second =
        DataType::IsIntegralType(input_type) &&
        DataType::IsIntegralType(original_type) &&
        DataType::IsIntegralType(result_type) &&
        DataType::Size(result_type) <= DataType::Size(input_type);

    if (is_first_conversion_lossless || integral_conversions_with_non_widening_second) {
      // If the merged conversion is implicit, do the simplification unconditionally.
      if (DataType::IsTypeConversionImplicit(original_type, result_type)) {
        instruction->ReplaceWith(original_input);
        instruction->GetBlock()->RemoveInstruction(instruction);
        if (!input_conversion->HasUses()) {
          // Don't wait for DCE.
          input_conversion->GetBlock()->RemoveInstruction(input_conversion);
        }
        RecordSimplification();
        return;
      }
      // Otherwise simplify only if the first conversion has no other use.
      if (input_conversion->HasOnlyOneNonEnvironmentUse()) {
        input_conversion->ReplaceWith(original_input);
        input_conversion->GetBlock()->RemoveInstruction(input_conversion);
        RecordSimplification();
        return;
      }
    }
  } else if (input->IsShr() && DataType::IsIntegralType(result_type) &&
            // Optimization only applies to lossy Type Conversions.
            !IsTypeConversionLossless(input_type, result_type)) {
    DCHECK(DataType::IsIntegralType(input_type));
    HShr* shr_op = input->AsShr();
    HConstant* shr_right = shr_op->GetConstantRight();
    HInstruction* shr_left = shr_op->GetLeastConstantLeft();
    if (shr_right != nullptr && shr_left->IsAnd()) {
      // Optimization needs AND -> SHR -> TypeConversion pattern.
      HAnd* and_op = shr_left->AsAnd();
      HConstant* and_right = and_op->GetConstantRight();
      HInstruction* and_left = and_op->GetLeastConstantLeft();
      if (and_right != nullptr &&
          !DataType::IsUnsignedType(and_left->GetType()) &&
          !DataType::IsUnsignedType(result_type) &&
          !DataType::IsUnsignedType(and_right->GetType()) &&
          (DataType::Size(and_left->GetType()) < 8) &&
          (DataType::Size(result_type) == 1)) {
        // TODO: Support Unsigned Types.
        // TODO: Support Long Types.
        // TODO: Support result types other than byte.
        if (and_op->HasOnlyOneNonEnvironmentUse() &&
            CanRemoveRedundantAnd(and_right, shr_right, result_type)) {
          and_op->ReplaceWith(and_left);
          and_op->GetBlock()->RemoveInstruction(and_op);
          RecordSimplification();
          return;
        }
      }
    }
  } else if (input->IsAnd() && DataType::IsIntegralType(result_type)) {
    DCHECK(DataType::IsIntegralType(input_type));
    HAnd* input_and = input->AsAnd();
    HConstant* constant = input_and->GetConstantRight();
    if (constant != nullptr) {
      int64_t value = Int64FromConstant(constant);
      DCHECK_NE(value, -1);  // "& -1" would have been optimized away in VisitAnd().
      size_t trailing_ones = CTZ(~static_cast<uint64_t>(value));
      if (trailing_ones >= kBitsPerByte * DataType::Size(result_type)) {
        // The `HAnd` is useless, for example in `(byte) (x & 0xff)`, get rid of it.
        HInstruction* original_input = input_and->GetLeastConstantLeft();
        if (DataType::IsTypeConversionImplicit(original_input->GetType(), result_type)) {
          instruction->ReplaceWith(original_input);
          instruction->GetBlock()->RemoveInstruction(instruction);
          RecordSimplification();
          return;
        } else if (input->HasOnlyOneNonEnvironmentUse()) {
          input_and->ReplaceWith(original_input);
          input_and->GetBlock()->RemoveInstruction(input_and);
          RecordSimplification();
          return;
        }
      }
    }
  } else if (input->HasOnlyOneNonEnvironmentUse() &&
             ((input_type == DataType::Type::kInt8 && result_type == DataType::Type::kUint8) ||
              (input_type == DataType::Type::kUint8 && result_type == DataType::Type::kInt8) ||
              (input_type == DataType::Type::kInt16 && result_type == DataType::Type::kUint16) ||
              (input_type == DataType::Type::kUint16 && result_type == DataType::Type::kInt16))) {
    // Try to modify the type of the load to `result_type` and remove the explicit type conversion.
    if (TryReplaceFieldOrArrayGetType(input, result_type)) {
      instruction->ReplaceWith(input);
      instruction->GetBlock()->RemoveInstruction(instruction);
      RecordSimplification();
      return;
    }
  }

  if (IsTypeConversionForStoringIntoNoWiderFieldOnly(instruction)) {
    instruction->ReplaceWith(input);
    instruction->GetBlock()->RemoveInstruction(instruction);
    RecordSimplification();
    return;
  }
}

void InstructionSimplifierVisitor::VisitAbs(HAbs* instruction) {
  HInstruction* input = instruction->GetInput();
  if (DataType::IsZeroExtension(input->GetType(), instruction->GetResultType())) {
    // Zero extension from narrow to wide can never set sign bit in the wider
    // operand, making the subsequent Abs redundant (e.g., abs(b & 0xff) for byte b).
    instruction->ReplaceWith(input);
    instruction->GetBlock()->RemoveInstruction(instruction);
    RecordSimplification();
  }
}

void InstructionSimplifierVisitor::VisitAdd(HAdd* instruction) {
  HConstant* input_cst = instruction->GetConstantRight();
  HInstruction* input_other = instruction->GetLeastConstantLeft();
  bool integral_type = DataType::IsIntegralType(instruction->GetType());
  if ((input_cst != nullptr) && input_cst->IsArithmeticZero()) {
    // Replace code looking like
    //    ADD dst, src, 0
    // with
    //    src
    // Note that we cannot optimize `x + 0.0` to `x` for floating-point. When
    // `x` is `-0.0`, the former expression yields `0.0`, while the later
    // yields `-0.0`.
    if (integral_type) {
      instruction->ReplaceWith(input_other);
      instruction->GetBlock()->RemoveInstruction(instruction);
      RecordSimplification();
      return;
    }
  }

  HInstruction* left = instruction->GetLeft();
  HInstruction* right = instruction->GetRight();
  bool left_is_neg = left->IsNeg();
  bool right_is_neg = right->IsNeg();

  if (left_is_neg && right_is_neg) {
    if (TryMoveNegOnInputsAfterBinop(instruction)) {
      return;
    }
  }

  if (left_is_neg != right_is_neg) {
    HNeg* neg = left_is_neg ? left->AsNeg() : right->AsNeg();
    if (neg->HasOnlyOneNonEnvironmentUse()) {
      // Replace code looking like
      //    NEG tmp, b
      //    ADD dst, a, tmp
      // with
      //    SUB dst, a, b
      // We do not perform the optimization if the input negation has environment
      // uses or multiple non-environment uses as it could lead to worse code. In
      // particular, we do not want the live range of `b` to be extended if we are
      // not sure the initial 'NEG' instruction can be removed.
      HInstruction* other = left_is_neg ? right : left;
      HSub* sub =
          new(GetGraph()->GetAllocator()) HSub(instruction->GetType(), other, neg->GetInput());
      instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, sub);
      RecordSimplification();
      neg->GetBlock()->RemoveInstruction(neg);
      return;
    }
  }

  if (TryReplaceWithRotate(instruction)) {
    return;
  }

  // TryHandleAssociativeAndCommutativeOperation() does not remove its input,
  // so no need to return.
  TryHandleAssociativeAndCommutativeOperation(instruction);

  if ((left->IsSub() || right->IsSub()) &&
      TrySubtractionChainSimplification(instruction)) {
    return;
  }

  if (integral_type) {
    // Replace code patterns looking like
    //    SUB dst1, x, y        SUB dst1, x, y
    //    ADD dst2, dst1, y     ADD dst2, y, dst1
    // with
    //    SUB dst1, x, y
    // ADD instruction is not needed in this case, we may use
    // one of inputs of SUB instead.
    if (left->IsSub() && left->InputAt(1) == right) {
      instruction->ReplaceWith(left->InputAt(0));
      RecordSimplification();
      instruction->GetBlock()->RemoveInstruction(instruction);
      return;
    } else if (right->IsSub() && right->InputAt(1) == left) {
      instruction->ReplaceWith(right->InputAt(0));
      RecordSimplification();
      instruction->GetBlock()->RemoveInstruction(instruction);
      return;
    }
  }
}

void InstructionSimplifierVisitor::VisitAnd(HAnd* instruction) {
  DCHECK(DataType::IsIntegralType(instruction->GetType()));
  HConstant* input_cst = instruction->GetConstantRight();
  HInstruction* input_other = instruction->GetLeastConstantLeft();

  if (input_cst != nullptr) {
    int64_t value = Int64FromConstant(input_cst);
    if (value == -1 ||
        // Similar cases under zero extension.
        (DataType::IsUnsignedType(input_other->GetType()) &&
         ((DataType::MaxValueOfIntegralType(input_other->GetType()) & ~value) == 0))) {
      // Replace code looking like
      //    AND dst, src, 0xFFF...FF
      // with
      //    src
      instruction->ReplaceWith(input_other);
      instruction->GetBlock()->RemoveInstruction(instruction);
      RecordSimplification();
      return;
    }
    if (input_other->IsTypeConversion() &&
        input_other->GetType() == DataType::Type::kInt64 &&
        DataType::IsIntegralType(input_other->InputAt(0)->GetType()) &&
        IsInt<32>(value) &&
        input_other->HasOnlyOneNonEnvironmentUse()) {
      // The AND can be reordered before the TypeConversion. Replace
      //   LongConstant cst, <32-bit-constant-sign-extended-to-64-bits>
      //   TypeConversion<Int64> tmp, src
      //   AND dst, tmp, cst
      // with
      //   IntConstant cst, <32-bit-constant>
      //   AND tmp, src, cst
      //   TypeConversion<Int64> dst, tmp
      // This helps 32-bit targets and does not hurt 64-bit targets.
      // This also simplifies detection of other patterns, such as Uint8 loads.
      HInstruction* new_and_input = input_other->InputAt(0);
      // Implicit conversion Int64->Int64 would have been removed previously.
      DCHECK_NE(new_and_input->GetType(), DataType::Type::kInt64);
      HConstant* new_const = GetGraph()->GetConstant(DataType::Type::kInt32, value);
      HAnd* new_and =
          new (GetGraph()->GetAllocator()) HAnd(DataType::Type::kInt32, new_and_input, new_const);
      instruction->GetBlock()->InsertInstructionBefore(new_and, instruction);
      HTypeConversion* new_conversion =
          new (GetGraph()->GetAllocator()) HTypeConversion(DataType::Type::kInt64, new_and);
      instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, new_conversion);
      input_other->GetBlock()->RemoveInstruction(input_other);
      RecordSimplification();
      // Try to process the new And now, do not wait for the next round of simplifications.
      instruction = new_and;
      input_other = new_and_input;
    }
    // Eliminate And from UShr+And if the And-mask contains all the bits that
    // can be non-zero after UShr. Transform Shr+And to UShr if the And-mask
    // precisely clears the shifted-in sign bits.
    if ((input_other->IsUShr() || input_other->IsShr()) && input_other->InputAt(1)->IsConstant()) {
      size_t reg_bits = (instruction->GetResultType() == DataType::Type::kInt64) ? 64 : 32;
      size_t shift = Int64FromConstant(input_other->InputAt(1)->AsConstant()) & (reg_bits - 1);
      size_t num_tail_bits_set = CTZ(value + 1);
      if ((num_tail_bits_set >= reg_bits - shift) && input_other->IsUShr()) {
        // This AND clears only bits known to be clear, for example "(x >>> 24) & 0xff".
        instruction->ReplaceWith(input_other);
        instruction->GetBlock()->RemoveInstruction(instruction);
        RecordSimplification();
        return;
      }  else if ((num_tail_bits_set == reg_bits - shift) && IsPowerOfTwo(value + 1) &&
          input_other->HasOnlyOneNonEnvironmentUse()) {
        DCHECK(input_other->IsShr());  // For UShr, we would have taken the branch above.
        // Replace SHR+AND with USHR, for example "(x >> 24) & 0xff" -> "x >>> 24".
        HUShr* ushr = new (GetGraph()->GetAllocator()) HUShr(instruction->GetType(),
                                                             input_other->InputAt(0),
                                                             input_other->InputAt(1),
                                                             input_other->GetDexPc());
        instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, ushr);
        input_other->GetBlock()->RemoveInstruction(input_other);
        RecordSimplification();
        return;
      }
    }
    if ((value == 0xff || value == 0xffff) && instruction->GetType() != DataType::Type::kInt64) {
      // Transform AND to a type conversion to Uint8/Uint16. If `input_other` is a field
      // or array Get with only a single use, short-circuit the subsequent simplification
      // of the Get+TypeConversion and change the Get's type to `new_type` instead.
      DataType::Type new_type = (value == 0xff) ? DataType::Type::kUint8 : DataType::Type::kUint16;
      DataType::Type find_type = (value == 0xff) ? DataType::Type::kInt8 : DataType::Type::kInt16;
      if (input_other->GetType() == find_type &&
          input_other->HasOnlyOneNonEnvironmentUse() &&
          TryReplaceFieldOrArrayGetType(input_other, new_type)) {
        instruction->ReplaceWith(input_other);
        instruction->GetBlock()->RemoveInstruction(instruction);
      } else if (DataType::IsTypeConversionImplicit(input_other->GetType(), new_type)) {
        instruction->ReplaceWith(input_other);
        instruction->GetBlock()->RemoveInstruction(instruction);
      } else {
        HTypeConversion* type_conversion = new (GetGraph()->GetAllocator()) HTypeConversion(
            new_type, input_other, instruction->GetDexPc());
        instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, type_conversion);
      }
      RecordSimplification();
      return;
    }
  }

  // We assume that GVN has run before, so we only perform a pointer comparison.
  // If for some reason the values are equal but the pointers are different, we
  // are still correct and only miss an optimization opportunity.
  if (instruction->GetLeft() == instruction->GetRight()) {
    // Replace code looking like
    //    AND dst, src, src
    // with
    //    src
    instruction->ReplaceWith(instruction->GetLeft());
    instruction->GetBlock()->RemoveInstruction(instruction);
    RecordSimplification();
    return;
  }

  if (TryDeMorganNegationFactoring(instruction)) {
    return;
  }

  // TryHandleAssociativeAndCommutativeOperation() does not remove its input,
  // so no need to return.
  TryHandleAssociativeAndCommutativeOperation(instruction);
}

void InstructionSimplifierVisitor::VisitGreaterThan(HGreaterThan* condition) {
  VisitCondition(condition);
}

void InstructionSimplifierVisitor::VisitGreaterThanOrEqual(HGreaterThanOrEqual* condition) {
  VisitCondition(condition);
}

void InstructionSimplifierVisitor::VisitLessThan(HLessThan* condition) {
  VisitCondition(condition);
}

void InstructionSimplifierVisitor::VisitLessThanOrEqual(HLessThanOrEqual* condition) {
  VisitCondition(condition);
}

void InstructionSimplifierVisitor::VisitBelow(HBelow* condition) {
  VisitCondition(condition);
}

void InstructionSimplifierVisitor::VisitBelowOrEqual(HBelowOrEqual* condition) {
  VisitCondition(condition);
}

void InstructionSimplifierVisitor::VisitAbove(HAbove* condition) {
  VisitCondition(condition);
}

void InstructionSimplifierVisitor::VisitAboveOrEqual(HAboveOrEqual* condition) {
  VisitCondition(condition);
}

// Recognize the following pattern:
// obj.getClass() ==/!= Foo.class
// And replace it with a constant value if the type of `obj` is statically known.
static bool RecognizeAndSimplifyClassCheck(HCondition* condition) {
  HInstruction* input_one = condition->InputAt(0);
  HInstruction* input_two = condition->InputAt(1);
  HLoadClass* load_class = input_one->IsLoadClass()
      ? input_one->AsLoadClass()
      : input_two->AsLoadClassOrNull();
  if (load_class == nullptr) {
    return false;
  }

  ReferenceTypeInfo class_rti = load_class->GetLoadedClassRTI();
  if (!class_rti.IsValid()) {
    // Unresolved class.
    return false;
  }

  HInstanceFieldGet* field_get = (load_class == input_one)
      ? input_two->AsInstanceFieldGetOrNull()
      : input_one->AsInstanceFieldGetOrNull();
  if (field_get == nullptr) {
    return false;
  }

  HInstruction* receiver = field_get->InputAt(0);
  ReferenceTypeInfo receiver_type = receiver->GetReferenceTypeInfo();
  if (!receiver_type.IsExact()) {
    return false;
  }

  {
    ScopedObjectAccess soa(Thread::Current());
    ArtField* field = GetClassRoot<mirror::Object>()->GetInstanceField(0);
    DCHECK_EQ(std::string(field->GetName()), "shadow$_klass_");
    if (field_get->GetFieldInfo().GetField() != field) {
      return false;
    }

    // We can replace the compare.
    int value = 0;
    if (receiver_type.IsEqual(class_rti)) {
      value = condition->IsEqual() ? 1 : 0;
    } else {
      value = condition->IsNotEqual() ? 1 : 0;
    }
    condition->ReplaceWith(condition->GetBlock()->GetGraph()->GetIntConstant(value));
    return true;
  }
}

void InstructionSimplifierVisitor::VisitCondition(HCondition* condition) {
  if (condition->IsEqual() || condition->IsNotEqual()) {
    if (RecognizeAndSimplifyClassCheck(condition)) {
      return;
    }
  }

  // Reverse condition if left is constant. Our code generators prefer constant
  // on the right hand side.
  if (condition->GetLeft()->IsConstant() && !condition->GetRight()->IsConstant()) {
    HBasicBlock* block = condition->GetBlock();
    HCondition* replacement =
        GetOppositeConditionSwapOps(block->GetGraph()->GetAllocator(), condition);
    // If it is a fp we must set the opposite bias.
    if (replacement != nullptr) {
      if (condition->IsLtBias()) {
        replacement->SetBias(ComparisonBias::kGtBias);
      } else if (condition->IsGtBias()) {
        replacement->SetBias(ComparisonBias::kLtBias);
      }
      block->ReplaceAndRemoveInstructionWith(condition, replacement);
      RecordSimplification();

      condition = replacement;
    }
  }

  HInstruction* left = condition->GetLeft();
  HInstruction* right = condition->GetRight();

  // Try to fold an HCompare into this HCondition.

  // We can only replace an HCondition which compares a Compare to 0.
  // Both 'dx' and 'jack' generate a compare to 0 when compiling a
  // condition with a long, float or double comparison as input.
  if (!left->IsCompare() || !right->IsConstant() || right->AsIntConstant()->GetValue() != 0) {
    // Conversion is not possible.
    return;
  }

  // Is the Compare only used for this purpose?
  if (!left->GetUses().HasExactlyOneElement()) {
    // Someone else also wants the result of the compare.
    return;
  }

  if (!left->GetEnvUses().empty()) {
    // There is a reference to the compare result in an environment. Do we really need it?
    if (GetGraph()->IsDebuggable()) {
      return;
    }

    // We have to ensure that there are no deopt points in the sequence.
    if (left->HasAnyEnvironmentUseBefore(condition)) {
      return;
    }
  }

  // Clean up any environment uses from the HCompare, if any.
  left->RemoveEnvironmentUsers();

  // We have decided to fold the HCompare into the HCondition. Transfer the information.
  condition->SetBias(left->AsCompare()->GetBias());

  // Replace the operands of the HCondition.
  condition->ReplaceInput(left->InputAt(0), 0);
  condition->ReplaceInput(left->InputAt(1), 1);

  // Remove the HCompare.
  left->GetBlock()->RemoveInstruction(left);

  RecordSimplification();
}

// Return whether x / divisor == x * (1.0f / divisor), for every float x.
static constexpr bool CanDivideByReciprocalMultiplyFloat(int32_t divisor) {
  // True, if the most significant bits of divisor are 0.
  return ((divisor & 0x7fffff) == 0);
}

// Return whether x / divisor == x * (1.0 / divisor), for every double x.
static constexpr bool CanDivideByReciprocalMultiplyDouble(int64_t divisor) {
  // True, if the most significant bits of divisor are 0.
  return ((divisor & ((UINT64_C(1) << 52) - 1)) == 0);
}

void InstructionSimplifierVisitor::VisitDiv(HDiv* instruction) {
  HConstant* input_cst = instruction->GetConstantRight();
  HInstruction* input_other = instruction->GetLeastConstantLeft();
  DataType::Type type = instruction->GetType();

  if ((input_cst != nullptr) && input_cst->IsOne()) {
    // Replace code looking like
    //    DIV dst, src, 1
    // with
    //    src
    instruction->ReplaceWith(input_other);
    instruction->GetBlock()->RemoveInstruction(instruction);
    RecordSimplification();
    return;
  }

  if ((input_cst != nullptr) && input_cst->IsMinusOne()) {
    // Replace code looking like
    //    DIV dst, src, -1
    // with
    //    NEG dst, src
    instruction->GetBlock()->ReplaceAndRemoveInstructionWith(
        instruction, new (GetGraph()->GetAllocator()) HNeg(type, input_other));
    RecordSimplification();
    return;
  }

  if ((input_cst != nullptr) && DataType::IsFloatingPointType(type)) {
    // Try replacing code looking like
    //    DIV dst, src, constant
    // with
    //    MUL dst, src, 1 / constant
    HConstant* reciprocal = nullptr;
    if (type == DataType::Type::kFloat64) {
      double value = input_cst->AsDoubleConstant()->GetValue();
      if (CanDivideByReciprocalMultiplyDouble(bit_cast<int64_t, double>(value))) {
        reciprocal = GetGraph()->GetDoubleConstant(1.0 / value);
      }
    } else {
      DCHECK_EQ(type, DataType::Type::kFloat32);
      float value = input_cst->AsFloatConstant()->GetValue();
      if (CanDivideByReciprocalMultiplyFloat(bit_cast<int32_t, float>(value))) {
        reciprocal = GetGraph()->GetFloatConstant(1.0f / value);
      }
    }

    if (reciprocal != nullptr) {
      instruction->GetBlock()->ReplaceAndRemoveInstructionWith(
          instruction, new (GetGraph()->GetAllocator()) HMul(type, input_other, reciprocal));
      RecordSimplification();
      return;
    }
  }
}


// Search HDiv having the specified dividend and divisor which is in the specified basic block.
// Return nullptr if nothing has been found.
static HDiv* FindDivWithInputsInBasicBlock(HInstruction* dividend,
                                           HInstruction* divisor,
                                           HBasicBlock* basic_block) {
  for (const HUseListNode<HInstruction*>& use : dividend->GetUses()) {
    HInstruction* user = use.GetUser();
    if (user->GetBlock() == basic_block &&
        user->IsDiv() &&
        user->InputAt(0) == dividend &&
        user->InputAt(1) == divisor) {
      return user->AsDiv();
    }
  }
  return nullptr;
}

// If there is Div with the same inputs as Rem and in the same basic block, it can be reused.
// Rem is replaced with Mul+Sub which use the found Div.
void InstructionSimplifierVisitor::TryToReuseDiv(HRem* rem) {
  // As the optimization replaces Rem with Mul+Sub they prevent some loop optimizations
  // if the Rem is in a loop.
  // Check if it is allowed to optimize such Rems.
  if (rem->IsInLoop() && be_loop_friendly_) {
    return;
  }
  DataType::Type type = rem->GetResultType();
  if (!DataType::IsIntOrLongType(type)) {
    return;
  }

  HBasicBlock* basic_block = rem->GetBlock();
  HInstruction* dividend = rem->GetLeft();
  HInstruction* divisor = rem->GetRight();

  if (divisor->IsConstant()) {
    HConstant* input_cst = rem->GetConstantRight();
    DCHECK(input_cst->IsIntConstant() || input_cst->IsLongConstant());
    int64_t cst_value = Int64FromConstant(input_cst);
    if (cst_value == std::numeric_limits<int64_t>::min() || IsPowerOfTwo(std::abs(cst_value))) {
      // Such cases are usually handled in the code generator because they don't need Div at all.
      return;
    }
  }

  HDiv* quotient = FindDivWithInputsInBasicBlock(dividend, divisor, basic_block);
  if (quotient == nullptr) {
    return;
  }
  if (!quotient->StrictlyDominates(rem)) {
    quotient->MoveBefore(rem);
  }

  ArenaAllocator* allocator = GetGraph()->GetAllocator();
  HInstruction* mul = new (allocator) HMul(type, quotient, divisor);
  basic_block->InsertInstructionBefore(mul, rem);
  HInstruction* sub = new (allocator) HSub(type, dividend, mul);
  basic_block->InsertInstructionBefore(sub, rem);
  rem->ReplaceWith(sub);
  basic_block->RemoveInstruction(rem);
  RecordSimplification();
}

void InstructionSimplifierVisitor::VisitRem(HRem* rem) {
  TryToReuseDiv(rem);
}

void InstructionSimplifierVisitor::VisitMul(HMul* instruction) {
  HConstant* input_cst = instruction->GetConstantRight();
  HInstruction* input_other = instruction->GetLeastConstantLeft();
  DataType::Type type = instruction->GetType();
  HBasicBlock* block = instruction->GetBlock();
  ArenaAllocator* allocator = GetGraph()->GetAllocator();

  if (input_cst == nullptr) {
    return;
  }

  if (input_cst->IsOne()) {
    // Replace code looking like
    //    MUL dst, src, 1
    // with
    //    src
    instruction->ReplaceWith(input_other);
    instruction->GetBlock()->RemoveInstruction(instruction);
    RecordSimplification();
    return;
  }

  if (input_cst->IsMinusOne() &&
      (DataType::IsFloatingPointType(type) || DataType::IsIntOrLongType(type))) {
    // Replace code looking like
    //    MUL dst, src, -1
    // with
    //    NEG dst, src
    HNeg* neg = new (allocator) HNeg(type, input_other);
    block->ReplaceAndRemoveInstructionWith(instruction, neg);
    RecordSimplification();
    return;
  }

  if (DataType::IsFloatingPointType(type) &&
      ((input_cst->IsFloatConstant() && input_cst->AsFloatConstant()->GetValue() == 2.0f) ||
       (input_cst->IsDoubleConstant() && input_cst->AsDoubleConstant()->GetValue() == 2.0))) {
    // Replace code looking like
    //    FP_MUL dst, src, 2.0
    // with
    //    FP_ADD dst, src, src
    // The 'int' and 'long' cases are handled below.
    block->ReplaceAndRemoveInstructionWith(instruction,
                                           new (allocator) HAdd(type, input_other, input_other));
    RecordSimplification();
    return;
  }

  if (DataType::IsIntOrLongType(type)) {
    int64_t factor = Int64FromConstant(input_cst);
    // Even though constant propagation also takes care of the zero case, other
    // optimizations can lead to having a zero multiplication.
    if (factor == 0) {
      // Replace code looking like
      //    MUL dst, src, 0
      // with
      //    0
      instruction->ReplaceWith(input_cst);
      instruction->GetBlock()->RemoveInstruction(instruction);
      RecordSimplification();
      return;
    } else if (IsPowerOfTwo(factor)) {
      // Replace code looking like
      //    MUL dst, src, pow_of_2
      // with
      //    SHL dst, src, log2(pow_of_2)
      HIntConstant* shift = GetGraph()->GetIntConstant(WhichPowerOf2(factor));
      HShl* shl = new (allocator) HShl(type, input_other, shift);
      block->ReplaceAndRemoveInstructionWith(instruction, shl);
      RecordSimplification();
      return;
    } else if (IsPowerOfTwo(factor - 1)) {
      // Transform code looking like
      //    MUL dst, src, (2^n + 1)
      // into
      //    SHL tmp, src, n
      //    ADD dst, src, tmp
      HShl* shl = new (allocator) HShl(type,
                                       input_other,
                                       GetGraph()->GetIntConstant(WhichPowerOf2(factor - 1)));
      HAdd* add = new (allocator) HAdd(type, input_other, shl);

      block->InsertInstructionBefore(shl, instruction);
      block->ReplaceAndRemoveInstructionWith(instruction, add);
      RecordSimplification();
      return;
    } else if (IsPowerOfTwo(factor + 1)) {
      // Transform code looking like
      //    MUL dst, src, (2^n - 1)
      // into
      //    SHL tmp, src, n
      //    SUB dst, tmp, src
      HShl* shl = new (allocator) HShl(type,
                                       input_other,
                                       GetGraph()->GetIntConstant(WhichPowerOf2(factor + 1)));
      HSub* sub = new (allocator) HSub(type, shl, input_other);

      block->InsertInstructionBefore(shl, instruction);
      block->ReplaceAndRemoveInstructionWith(instruction, sub);
      RecordSimplification();
      return;
    }
  }

  // TryHandleAssociativeAndCommutativeOperation() does not remove its input,
  // so no need to return.
  TryHandleAssociativeAndCommutativeOperation(instruction);
}

void InstructionSimplifierVisitor::VisitNeg(HNeg* instruction) {
  HInstruction* input = instruction->GetInput();
  if (input->IsNeg()) {
    // Replace code looking like
    //    NEG tmp, src
    //    NEG dst, tmp
    // with
    //    src
    HNeg* previous_neg = input->AsNeg();
    instruction->ReplaceWith(previous_neg->GetInput());
    instruction->GetBlock()->RemoveInstruction(instruction);
    // We perform the optimization even if the input negation has environment
    // uses since it allows removing the current instruction. But we only delete
    // the input negation only if it is does not have any uses left.
    if (!previous_neg->HasUses()) {
      previous_neg->GetBlock()->RemoveInstruction(previous_neg);
    }
    RecordSimplification();
    return;
  }

  if (input->IsSub() && input->HasOnlyOneNonEnvironmentUse() &&
      !DataType::IsFloatingPointType(input->GetType())) {
    // Replace code looking like
    //    SUB tmp, a, b
    //    NEG dst, tmp
    // with
    //    SUB dst, b, a
    // We do not perform the optimization if the input subtraction has
    // environment uses or multiple non-environment uses as it could lead to
    // worse code. In particular, we do not want the live ranges of `a` and `b`
    // to be extended if we are not sure the initial 'SUB' instruction can be
    // removed.
    // We do not perform optimization for fp because we could lose the sign of zero.
    HSub* sub = input->AsSub();
    HSub* new_sub = new (GetGraph()->GetAllocator()) HSub(
        instruction->GetType(), sub->GetRight(), sub->GetLeft());
    instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, new_sub);
    if (!sub->HasUses()) {
      sub->GetBlock()->RemoveInstruction(sub);
    }
    RecordSimplification();
  }
}

void InstructionSimplifierVisitor::VisitNot(HNot* instruction) {
  HInstruction* input = instruction->GetInput();
  if (input->IsNot()) {
    // Replace code looking like
    //    NOT tmp, src
    //    NOT dst, tmp
    // with
    //    src
    // We perform the optimization even if the input negation has environment
    // uses since it allows removing the current instruction. But we only delete
    // the input negation only if it is does not have any uses left.
    HNot* previous_not = input->AsNot();
    instruction->ReplaceWith(previous_not->GetInput());
    instruction->GetBlock()->RemoveInstruction(instruction);
    if (!previous_not->HasUses()) {
      previous_not->GetBlock()->RemoveInstruction(previous_not);
    }
    RecordSimplification();
  }
}

void InstructionSimplifierVisitor::VisitOr(HOr* instruction) {
  HConstant* input_cst = instruction->GetConstantRight();
  HInstruction* input_other = instruction->GetLeastConstantLeft();

  if ((input_cst != nullptr) && input_cst->IsZeroBitPattern()) {
    // Replace code looking like
    //    OR dst, src, 0
    // with
    //    src
    instruction->ReplaceWith(input_other);
    instruction->GetBlock()->RemoveInstruction(instruction);
    RecordSimplification();
    return;
  }

  // We assume that GVN has run before, so we only perform a pointer comparison.
  // If for some reason the values are equal but the pointers are different, we
  // are still correct and only miss an optimization opportunity.
  if (instruction->GetLeft() == instruction->GetRight()) {
    // Replace code looking like
    //    OR dst, src, src
    // with
    //    src
    instruction->ReplaceWith(instruction->GetLeft());
    instruction->GetBlock()->RemoveInstruction(instruction);
    RecordSimplification();
    return;
  }

  if (TryDeMorganNegationFactoring(instruction)) return;

  if (TryReplaceWithRotate(instruction)) {
    return;
  }

  // TryHandleAssociativeAndCommutativeOperation() does not remove its input,
  // so no need to return.
  TryHandleAssociativeAndCommutativeOperation(instruction);
}

void InstructionSimplifierVisitor::VisitShl(HShl* instruction) {
  VisitShift(instruction);
}

void InstructionSimplifierVisitor::VisitShr(HShr* instruction) {
  VisitShift(instruction);
}

void InstructionSimplifierVisitor::VisitSub(HSub* instruction) {
  HConstant* input_cst = instruction->GetConstantRight();
  HInstruction* input_other = instruction->GetLeastConstantLeft();

  DataType::Type type = instruction->GetType();
  if (DataType::IsFloatingPointType(type)) {
    return;
  }

  if ((input_cst != nullptr) && input_cst->IsArithmeticZero()) {
    // Replace code looking like
    //    SUB dst, src, 0
    // with
    //    src
    // Note that we cannot optimize `x - 0.0` to `x` for floating-point. When
    // `x` is `-0.0`, the former expression yields `0.0`, while the later
    // yields `-0.0`.
    instruction->ReplaceWith(input_other);
    instruction->GetBlock()->RemoveInstruction(instruction);
    RecordSimplification();
    return;
  }

  HBasicBlock* block = instruction->GetBlock();
  ArenaAllocator* allocator = GetGraph()->GetAllocator();

  HInstruction* left = instruction->GetLeft();
  HInstruction* right = instruction->GetRight();
  if (left->IsConstant()) {
    if (Int64FromConstant(left->AsConstant()) == 0) {
      // Replace code looking like
      //    SUB dst, 0, src
      // with
      //    NEG dst, src
      // Note that we cannot optimize `0.0 - x` to `-x` for floating-point. When
      // `x` is `0.0`, the former expression yields `0.0`, while the later
      // yields `-0.0`.
      HNeg* neg = new (allocator) HNeg(type, right);
      block->ReplaceAndRemoveInstructionWith(instruction, neg);
      RecordSimplification();
      return;
    }
  }

  if (left->IsNeg() && right->IsNeg()) {
    if (TryMoveNegOnInputsAfterBinop(instruction)) {
      return;
    }
  }

  if (right->IsNeg() && right->HasOnlyOneNonEnvironmentUse()) {
    // Replace code looking like
    //    NEG tmp, b
    //    SUB dst, a, tmp
    // with
    //    ADD dst, a, b
    HAdd* add = new(GetGraph()->GetAllocator()) HAdd(type, left, right->AsNeg()->GetInput());
    instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, add);
    RecordSimplification();
    right->GetBlock()->RemoveInstruction(right);
    return;
  }

  if (left->IsNeg() && left->HasOnlyOneNonEnvironmentUse()) {
    // Replace code looking like
    //    NEG tmp, a
    //    SUB dst, tmp, b
    // with
    //    ADD tmp, a, b
    //    NEG dst, tmp
    // The second version is not intrinsically better, but enables more
    // transformations.
    HAdd* add = new(GetGraph()->GetAllocator()) HAdd(type, left->AsNeg()->GetInput(), right);
    instruction->GetBlock()->InsertInstructionBefore(add, instruction);
    HNeg* neg = new (GetGraph()->GetAllocator()) HNeg(instruction->GetType(), add);
    instruction->GetBlock()->InsertInstructionBefore(neg, instruction);
    instruction->ReplaceWith(neg);
    instruction->GetBlock()->RemoveInstruction(instruction);
    RecordSimplification();
    left->GetBlock()->RemoveInstruction(left);
    return;
  }

  if (TrySubtractionChainSimplification(instruction)) {
    return;
  }

  if (left->IsAdd()) {
    // Cases (x + y) - y = x, and (x + y) - x = y.
    // Replace code patterns looking like
    //    ADD dst1, x, y        ADD dst1, x, y
    //    SUB dst2, dst1, y     SUB dst2, dst1, x
    // with
    //    ADD dst1, x, y
    // SUB instruction is not needed in this case, we may use
    // one of inputs of ADD instead.
    // It is applicable to integral types only.
    HAdd* add = left->AsAdd();
    DCHECK(DataType::IsIntegralType(type));
    if (add->GetRight() == right) {
      instruction->ReplaceWith(add->GetLeft());
      RecordSimplification();
      instruction->GetBlock()->RemoveInstruction(instruction);
      return;
    } else if (add->GetLeft() == right) {
      instruction->ReplaceWith(add->GetRight());
      RecordSimplification();
      instruction->GetBlock()->RemoveInstruction(instruction);
      return;
    }
  } else if (right->IsAdd()) {
    // Cases y - (x + y) = -x, and  x - (x + y) = -y.
    // Replace code patterns looking like
    //    ADD dst1, x, y        ADD dst1, x, y
    //    SUB dst2, y, dst1     SUB dst2, x, dst1
    // with
    //    ADD dst1, x, y        ADD dst1, x, y
    //    NEG x                 NEG y
    // SUB instruction is not needed in this case, we may use
    // one of inputs of ADD instead with a NEG.
    // It is applicable to integral types only.
    HAdd* add = right->AsAdd();
    DCHECK(DataType::IsIntegralType(type));
    if (add->GetRight() == left) {
      HNeg* neg = new (GetGraph()->GetAllocator()) HNeg(add->GetType(), add->GetLeft());
      instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, neg);
      RecordSimplification();
      return;
    } else if (add->GetLeft() == left) {
      HNeg* neg = new (GetGraph()->GetAllocator()) HNeg(add->GetType(), add->GetRight());
      instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, neg);
      RecordSimplification();
      return;
    }
  } else if (left->IsSub()) {
    // Case (x - y) - x = -y.
    // Replace code patterns looking like
    //    SUB dst1, x, y
    //    SUB dst2, dst1, x
    // with
    //    SUB dst1, x, y
    //    NEG y
    // The second SUB is not needed in this case, we may use the second input of the first SUB
    // instead with a NEG.
    // It is applicable to integral types only.
    HSub* sub = left->AsSub();
    DCHECK(DataType::IsIntegralType(type));
    if (sub->GetLeft() == right) {
      HNeg* neg = new (GetGraph()->GetAllocator()) HNeg(sub->GetType(), sub->GetRight());
      instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, neg);
      RecordSimplification();
      return;
    }
  } else if (right->IsSub()) {
    // Case x - (x - y) = y.
    // Replace code patterns looking like
    //    SUB dst1, x, y
    //    SUB dst2, x, dst1
    // with
    //    SUB dst1, x, y
    // The second SUB is not needed in this case, we may use the second input of the first SUB.
    // It is applicable to integral types only.
    HSub* sub = right->AsSub();
    DCHECK(DataType::IsIntegralType(type));
    if (sub->GetLeft() == left) {
      instruction->ReplaceWith(sub->GetRight());
      RecordSimplification();
      instruction->GetBlock()->RemoveInstruction(instruction);
      return;
    }
  }
}

void InstructionSimplifierVisitor::VisitUShr(HUShr* instruction) {
  VisitShift(instruction);
}

void InstructionSimplifierVisitor::VisitXor(HXor* instruction) {
  HConstant* input_cst = instruction->GetConstantRight();
  HInstruction* input_other = instruction->GetLeastConstantLeft();

  if ((input_cst != nullptr) && input_cst->IsZeroBitPattern()) {
    // Replace code looking like
    //    XOR dst, src, 0
    // with
    //    src
    instruction->ReplaceWith(input_other);
    instruction->GetBlock()->RemoveInstruction(instruction);
    RecordSimplification();
    return;
  }

  if ((input_cst != nullptr) && input_cst->IsOne()
      && input_other->GetType() == DataType::Type::kBool) {
    // Replace code looking like
    //    XOR dst, src, 1
    // with
    //    BOOLEAN_NOT dst, src
    HBooleanNot* boolean_not = new (GetGraph()->GetAllocator()) HBooleanNot(input_other);
    instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, boolean_not);
    RecordSimplification();
    return;
  }

  if ((input_cst != nullptr) && AreAllBitsSet(input_cst)) {
    // Replace code looking like
    //    XOR dst, src, 0xFFF...FF
    // with
    //    NOT dst, src
    HNot* bitwise_not = new (GetGraph()->GetAllocator()) HNot(instruction->GetType(), input_other);
    instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, bitwise_not);
    RecordSimplification();
    return;
  }

  HInstruction* left = instruction->GetLeft();
  HInstruction* right = instruction->GetRight();
  if (((left->IsNot() && right->IsNot()) ||
       (left->IsBooleanNot() && right->IsBooleanNot())) &&
      left->HasOnlyOneNonEnvironmentUse() &&
      right->HasOnlyOneNonEnvironmentUse()) {
    // Replace code looking like
    //    NOT nota, a
    //    NOT notb, b
    //    XOR dst, nota, notb
    // with
    //    XOR dst, a, b
    instruction->ReplaceInput(left->InputAt(0), 0);
    instruction->ReplaceInput(right->InputAt(0), 1);
    left->GetBlock()->RemoveInstruction(left);
    right->GetBlock()->RemoveInstruction(right);
    RecordSimplification();
    return;
  }

  if (TryReplaceWithRotate(instruction)) {
    return;
  }

  // TryHandleAssociativeAndCommutativeOperation() does not remove its input,
  // so no need to return.
  TryHandleAssociativeAndCommutativeOperation(instruction);
}

void InstructionSimplifierVisitor::SimplifyStringEquals(HInvoke* instruction) {
  HInstruction* argument = instruction->InputAt(1);
  HInstruction* receiver = instruction->InputAt(0);
  if (receiver == argument) {
    // Because String.equals is an instance call, the receiver is
    // a null check if we don't know it's null. The argument however, will
    // be the actual object. So we cannot end up in a situation where both
    // are equal but could be null.
    DCHECK(CanEnsureNotNullAt(argument, instruction));
    instruction->ReplaceWith(GetGraph()->GetIntConstant(1));
    instruction->GetBlock()->RemoveInstruction(instruction);
  } else {
    StringEqualsOptimizations optimizations(instruction);
    if (CanEnsureNotNullAt(argument, instruction)) {
      optimizations.SetArgumentNotNull();
    }
    ScopedObjectAccess soa(Thread::Current());
    ReferenceTypeInfo argument_rti = argument->GetReferenceTypeInfo();
    if (argument_rti.IsValid() && argument_rti.IsStringClass()) {
      optimizations.SetArgumentIsString();
    }
  }
}

static bool IsArrayLengthOf(HInstruction* potential_length, HInstruction* potential_array) {
  if (potential_length->IsArrayLength()) {
    return potential_length->InputAt(0) == potential_array;
  }

  if (potential_array->IsNewArray()) {
    return potential_array->AsNewArray()->GetLength() == potential_length;
  }

  return false;
}

void InstructionSimplifierVisitor::SimplifySystemArrayCopy(HInvoke* instruction) {
  HInstruction* source = instruction->InputAt(0);
  HInstruction* destination = instruction->InputAt(2);
  HInstruction* count = instruction->InputAt(4);
  SystemArrayCopyOptimizations optimizations(instruction);
  if (CanEnsureNotNullAt(source, instruction)) {
    optimizations.SetSourceIsNotNull();
  }
  if (CanEnsureNotNullAt(destination, instruction)) {
    optimizations.SetDestinationIsNotNull();
  }
  if (destination == source) {
    optimizations.SetDestinationIsSource();
  }

  if (IsArrayLengthOf(count, source)) {
    optimizations.SetCountIsSourceLength();
  }

  if (IsArrayLengthOf(count, destination)) {
    optimizations.SetCountIsDestinationLength();
  }

  {
    ScopedObjectAccess soa(Thread::Current());
    DataType::Type source_component_type = DataType::Type::kVoid;
    DataType::Type destination_component_type = DataType::Type::kVoid;
    ReferenceTypeInfo destination_rti = destination->GetReferenceTypeInfo();
    if (destination_rti.IsValid()) {
      if (destination_rti.IsObjectArray()) {
        if (destination_rti.IsExact()) {
          optimizations.SetDoesNotNeedTypeCheck();
        }
        optimizations.SetDestinationIsTypedObjectArray();
      }
      if (destination_rti.IsPrimitiveArrayClass()) {
        destination_component_type = DataTypeFromPrimitive(
            destination_rti.GetTypeHandle()->GetComponentType()->GetPrimitiveType());
        optimizations.SetDestinationIsPrimitiveArray();
      } else if (destination_rti.IsNonPrimitiveArrayClass()) {
        optimizations.SetDestinationIsNonPrimitiveArray();
      }
    }
    ReferenceTypeInfo source_rti = source->GetReferenceTypeInfo();
    if (source_rti.IsValid()) {
      if (destination_rti.IsValid() && destination_rti.CanArrayHoldValuesOf(source_rti)) {
        optimizations.SetDoesNotNeedTypeCheck();
      }
      if (source_rti.IsPrimitiveArrayClass()) {
        optimizations.SetSourceIsPrimitiveArray();
        source_component_type = DataTypeFromPrimitive(
            source_rti.GetTypeHandle()->GetComponentType()->GetPrimitiveType());
      } else if (source_rti.IsNonPrimitiveArrayClass()) {
        optimizations.SetSourceIsNonPrimitiveArray();
      }
    }
    // For primitive arrays, use their optimized ArtMethod implementations.
    if ((source_component_type != DataType::Type::kVoid) &&
        (source_component_type == destination_component_type)) {
      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
      PointerSize image_size = class_linker->GetImagePointerSize();
      HInvokeStaticOrDirect* invoke = instruction->AsInvokeStaticOrDirect();
      ObjPtr<mirror::Class> system = invoke->GetResolvedMethod()->GetDeclaringClass();
      ArtMethod* method = nullptr;
      switch (source_component_type) {
        case DataType::Type::kBool:
          method = system->FindClassMethod("arraycopy", "([ZI[ZII)V", image_size);
          break;
        case DataType::Type::kInt8:
          method = system->FindClassMethod("arraycopy", "([BI[BII)V", image_size);
          break;
        case DataType::Type::kUint16:
          method = system->FindClassMethod("arraycopy", "([CI[CII)V", image_size);
          break;
        case DataType::Type::kInt16:
          method = system->FindClassMethod("arraycopy", "([SI[SII)V", image_size);
          break;
        case DataType::Type::kInt32:
          method = system->FindClassMethod("arraycopy", "([II[III)V", image_size);
          break;
        case DataType::Type::kFloat32:
          method = system->FindClassMethod("arraycopy", "([FI[FII)V", image_size);
          break;
        case DataType::Type::kInt64:
          method = system->FindClassMethod("arraycopy", "([JI[JII)V", image_size);
          break;
        case DataType::Type::kFloat64:
          method = system->FindClassMethod("arraycopy", "([DI[DII)V", image_size);
          break;
        default:
          LOG(FATAL) << "Unreachable";
      }
      DCHECK(method != nullptr);
      DCHECK(method->IsStatic());
      DCHECK(method->GetDeclaringClass() == system);
      invoke->SetResolvedMethod(method, !codegen_->GetGraph()->IsDebuggable());
      // Sharpen the new invoke. Note that we do not update the dex method index of
      // the invoke, as we would need to look it up in the current dex file, and it
      // is unlikely that it exists. The most usual situation for such typed
      // arraycopy methods is a direct pointer to the boot image.
      invoke->SetDispatchInfo(HSharpening::SharpenLoadMethod(
          method,
          /* has_method_id= */ true,
          /* for_interface_call= */ false,
          codegen_));
    }
  }
}

void InstructionSimplifierVisitor::SimplifyFP2Int(HInvoke* invoke) {
  DCHECK(invoke->IsInvokeStaticOrDirect());
  uint32_t dex_pc = invoke->GetDexPc();
  HInstruction* x = invoke->InputAt(0);
  DataType::Type type = x->GetType();
  // Set proper bit pattern for NaN and replace intrinsic with raw version.
  HInstruction* nan;
  if (type == DataType::Type::kFloat64) {
    nan = GetGraph()->GetLongConstant(0x7ff8000000000000L);
    invoke->SetIntrinsic(Intrinsics::kDoubleDoubleToRawLongBits,
                         kNeedsEnvironment,
                         kNoSideEffects,
                         kNoThrow);
  } else {
    DCHECK_EQ(type, DataType::Type::kFloat32);
    nan = GetGraph()->GetIntConstant(0x7fc00000);
    invoke->SetIntrinsic(Intrinsics::kFloatFloatToRawIntBits,
                         kNeedsEnvironment,
                         kNoSideEffects,
                         kNoThrow);
  }
  // Test IsNaN(x), which is the same as x != x.
  HCondition* condition = new (GetGraph()->GetAllocator()) HNotEqual(x, x, dex_pc);
  condition->SetBias(ComparisonBias::kLtBias);
  invoke->GetBlock()->InsertInstructionBefore(condition, invoke->GetNext());
  // Select between the two.
  HInstruction* select = new (GetGraph()->GetAllocator()) HSelect(condition, nan, invoke, dex_pc);
  invoke->GetBlock()->InsertInstructionBefore(select, condition->GetNext());
  invoke->ReplaceWithExceptInReplacementAtIndex(select, 0);  // false at index 0
}

void InstructionSimplifierVisitor::SimplifyStringCharAt(HInvoke* invoke) {
  HInstruction* str = invoke->InputAt(0);
  HInstruction* index = invoke->InputAt(1);
  uint32_t dex_pc = invoke->GetDexPc();
  ArenaAllocator* allocator = GetGraph()->GetAllocator();
  // We treat String as an array to allow DCE and BCE to seamlessly work on strings,
  // so create the HArrayLength, HBoundsCheck and HArrayGet.
  HArrayLength* length = new (allocator) HArrayLength(str, dex_pc, /* is_string_length= */ true);
  invoke->GetBlock()->InsertInstructionBefore(length, invoke);
  HBoundsCheck* bounds_check = new (allocator) HBoundsCheck(
      index, length, dex_pc, /* is_string_char_at= */ true);
  invoke->GetBlock()->InsertInstructionBefore(bounds_check, invoke);
  HArrayGet* array_get = new (allocator) HArrayGet(str,
                                                   bounds_check,
                                                   DataType::Type::kUint16,
                                                   SideEffects::None(),  // Strings are immutable.
                                                   dex_pc,
                                                   /* is_string_char_at= */ true);
  invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, array_get);
  bounds_check->CopyEnvironmentFrom(invoke->GetEnvironment());
  GetGraph()->SetHasBoundsChecks(true);
}

void InstructionSimplifierVisitor::SimplifyStringLength(HInvoke* invoke) {
  HInstruction* str = invoke->InputAt(0);
  uint32_t dex_pc = invoke->GetDexPc();
  // We treat String as an array to allow DCE and BCE to seamlessly work on strings,
  // so create the HArrayLength.
  HArrayLength* length =
      new (GetGraph()->GetAllocator()) HArrayLength(str, dex_pc, /* is_string_length= */ true);
  invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, length);
}

void InstructionSimplifierVisitor::SimplifyStringIndexOf(HInvoke* invoke) {
  DCHECK(invoke->GetIntrinsic() == Intrinsics::kStringIndexOf ||
         invoke->GetIntrinsic() == Intrinsics::kStringIndexOfAfter);
  if (invoke->InputAt(0)->IsLoadString()) {
    HLoadString* load_string = invoke->InputAt(0)->AsLoadString();
    const DexFile& dex_file = load_string->GetDexFile();
    uint32_t utf16_length;
    const char* data =
        dex_file.StringDataAndUtf16LengthByIdx(load_string->GetStringIndex(), &utf16_length);
    if (utf16_length == 0) {
      invoke->ReplaceWith(GetGraph()->GetIntConstant(-1));
      invoke->GetBlock()->RemoveInstruction(invoke);
      RecordSimplification();
      return;
    }
    if (utf16_length == 1 && invoke->GetIntrinsic() == Intrinsics::kStringIndexOf) {
      // Simplify to HSelect(HEquals(., load_string.charAt(0)), 0, -1).
      // If the sought character is supplementary, this gives the correct result, i.e. -1.
      uint32_t c = GetUtf16FromUtf8(&data);
      DCHECK_EQ(GetTrailingUtf16Char(c), 0u);
      DCHECK_EQ(GetLeadingUtf16Char(c), c);
      uint32_t dex_pc = invoke->GetDexPc();
      ArenaAllocator* allocator = GetGraph()->GetAllocator();
      HEqual* equal =
          new (allocator) HEqual(invoke->InputAt(1), GetGraph()->GetIntConstant(c), dex_pc);
      invoke->GetBlock()->InsertInstructionBefore(equal, invoke);
      HSelect* result = new (allocator) HSelect(equal,
                                                GetGraph()->GetIntConstant(0),
                                                GetGraph()->GetIntConstant(-1),
                                                dex_pc);
      invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, result);
      RecordSimplification();
      return;
    }
  }
}

// This method should only be used on intrinsics whose sole way of throwing an
// exception is raising a NPE when the nth argument is null. If that argument
// is provably non-null, we can clear the flag.
void InstructionSimplifierVisitor::SimplifyNPEOnArgN(HInvoke* invoke, size_t n) {
  HInstruction* arg = invoke->InputAt(n);
  if (invoke->CanThrow() && !arg->CanBeNull()) {
    invoke->SetCanThrow(false);
  }
}

// Methods that return "this" can replace the returned value with the receiver.
void InstructionSimplifierVisitor::SimplifyReturnThis(HInvoke* invoke) {
  if (invoke->HasUses()) {
    HInstruction* receiver = invoke->InputAt(0);
    invoke->ReplaceWith(receiver);
    RecordSimplification();
  }
}

// Helper method for StringBuffer escape analysis.
static bool NoEscapeForStringBufferReference(HInstruction* reference, HInstruction* user) {
  if (user->IsInvokeStaticOrDirect()) {
    // Any constructor on StringBuffer is okay.
    return user->AsInvokeStaticOrDirect()->GetResolvedMethod() != nullptr &&
           user->AsInvokeStaticOrDirect()->GetResolvedMethod()->IsConstructor() &&
           user->InputAt(0) == reference;
  } else if (user->IsInvokeVirtual()) {
    switch (user->AsInvokeVirtual()->GetIntrinsic()) {
      case Intrinsics::kStringBufferLength:
      case Intrinsics::kStringBufferToString:
        DCHECK_EQ(user->InputAt(0), reference);
        return true;
      case Intrinsics::kStringBufferAppend:
        // Returns "this", so only okay if no further uses.
        DCHECK_EQ(user->InputAt(0), reference);
        DCHECK_NE(user->InputAt(1), reference);
        return !user->HasUses();
      default:
        break;
    }
  }
  return false;
}

static bool TryReplaceStringBuilderAppend(HInvoke* invoke) {
  DCHECK_EQ(invoke->GetIntrinsic(), Intrinsics::kStringBuilderToString);
  if (invoke->CanThrowIntoCatchBlock()) {
    return false;
  }

  HBasicBlock* block = invoke->GetBlock();
  HInstruction* sb = invoke->InputAt(0);

  // We support only a new StringBuilder, otherwise we cannot ensure that
  // the StringBuilder data does not need to be populated for other users.
  if (!sb->IsNewInstance()) {
    return false;
  }

  // For now, we support only single-block recognition.
  // (Ternary operators feeding the append could be implemented.)
  for (const HUseListNode<HInstruction*>& use : sb->GetUses()) {
    if (use.GetUser()->GetBlock() != block) {
      return false;
    }
    // The append pattern uses the StringBuilder only as the first argument.
    if (use.GetIndex() != 0u) {
      return false;
    }
  }

  // Collect args and check for unexpected uses.
  // We expect one call to a constructor with no arguments, one constructor fence (unless
  // eliminated), some number of append calls and one call to StringBuilder.toString().
  bool seen_constructor = false;
  bool seen_constructor_fence = false;
  bool seen_to_string = false;
  uint32_t format = 0u;
  uint32_t num_args = 0u;
  bool has_fp_args = false;
  HInstruction* args[StringBuilderAppend::kMaxArgs];  // Added in reverse order.
  for (HBackwardInstructionIterator iter(block->GetInstructions()); !iter.Done(); iter.Advance()) {
    HInstruction* user = iter.Current();
    // Instructions of interest apply to `sb`, skip those that do not involve `sb`.
    if (user->InputCount() == 0u || user->InputAt(0u) != sb) {
      continue;
    }
    // We visit the uses in reverse order, so the StringBuilder.toString() must come first.
    if (!seen_to_string) {
      if (user == invoke) {
        seen_to_string = true;
        continue;
      } else {
        return false;
      }
    }
    // Then we should see the arguments.
    if (user->IsInvokeVirtual()) {
      HInvokeVirtual* as_invoke_virtual = user->AsInvokeVirtual();
      DCHECK(!seen_constructor);
      DCHECK(!seen_constructor_fence);
      StringBuilderAppend::Argument arg;
      switch (as_invoke_virtual->GetIntrinsic()) {
        case Intrinsics::kStringBuilderAppendObject:
          // TODO: Unimplemented, needs to call String.valueOf().
          return false;
        case Intrinsics::kStringBuilderAppendString:
          arg = StringBuilderAppend::Argument::kString;
          break;
        case Intrinsics::kStringBuilderAppendCharArray:
          // TODO: Unimplemented, StringBuilder.append(char[]) can throw NPE and we would
          // not have the correct stack trace for it.
          return false;
        case Intrinsics::kStringBuilderAppendBoolean:
          arg = StringBuilderAppend::Argument::kBoolean;
          break;
        case Intrinsics::kStringBuilderAppendChar:
          arg = StringBuilderAppend::Argument::kChar;
          break;
        case Intrinsics::kStringBuilderAppendInt:
          arg = StringBuilderAppend::Argument::kInt;
          break;
        case Intrinsics::kStringBuilderAppendLong:
          arg = StringBuilderAppend::Argument::kLong;
          break;
        case Intrinsics::kStringBuilderAppendFloat:
          arg = StringBuilderAppend::Argument::kFloat;
          has_fp_args = true;
          break;
        case Intrinsics::kStringBuilderAppendDouble:
          arg = StringBuilderAppend::Argument::kDouble;
          has_fp_args = true;
          break;
        case Intrinsics::kStringBuilderAppendCharSequence: {
          ReferenceTypeInfo rti = user->AsInvokeVirtual()->InputAt(1)->GetReferenceTypeInfo();
          if (!rti.IsValid()) {
            return false;
          }
          ScopedObjectAccess soa(Thread::Current());
          Handle<mirror::Class> input_type = rti.GetTypeHandle();
          DCHECK(input_type != nullptr);
          if (input_type.Get() == GetClassRoot<mirror::String>()) {
            arg = StringBuilderAppend::Argument::kString;
          } else {
            // TODO: Check and implement for StringBuilder. We could find the StringBuilder's
            // internal char[] inconsistent with the length, or the string compression
            // of the result could be compromised with a concurrent modification, and
            // we would need to throw appropriate exceptions.
            return false;
          }
          break;
        }
        default: {
          return false;
        }
      }
      // Uses of the append return value should have been replaced with the first input.
      DCHECK(!as_invoke_virtual->HasUses());
      DCHECK(!as_invoke_virtual->HasEnvironmentUses());
      if (num_args == StringBuilderAppend::kMaxArgs) {
        return false;
      }
      format = (format << StringBuilderAppend::kBitsPerArg) | static_cast<uint32_t>(arg);
      args[num_args] = as_invoke_virtual->InputAt(1u);
      ++num_args;
    } else if (user->IsInvokeStaticOrDirect() &&
               user->AsInvokeStaticOrDirect()->GetResolvedMethod() != nullptr &&
               user->AsInvokeStaticOrDirect()->GetResolvedMethod()->IsConstructor() &&
               user->AsInvokeStaticOrDirect()->GetNumberOfArguments() == 1u) {
      // After arguments, we should see the constructor.
      // We accept only the constructor with no extra arguments.
      DCHECK(!seen_constructor);
      DCHECK(!seen_constructor_fence);
      seen_constructor = true;
    } else if (user->IsConstructorFence()) {
      // The last use we see is the constructor fence.
      DCHECK(seen_constructor);
      DCHECK(!seen_constructor_fence);
      seen_constructor_fence = true;
    } else {
      return false;
    }
  }

  if (num_args == 0u) {
    return false;
  }

  // Check environment uses.
  for (const HUseListNode<HEnvironment*>& use : sb->GetEnvUses()) {
    HInstruction* holder = use.GetUser()->GetHolder();
    if (holder->GetBlock() != block) {
      return false;
    }
    // Accept only calls on the StringBuilder (which shall all be removed).
    // TODO: Carve-out for const-string? Or rely on environment pruning (to be implemented)?
    if (holder->InputCount() == 0 || holder->InputAt(0) != sb) {
      return false;
    }
  }

  // Create replacement instruction.
  HIntConstant* fmt = block->GetGraph()->GetIntConstant(static_cast<int32_t>(format));
  ArenaAllocator* allocator = block->GetGraph()->GetAllocator();
  HStringBuilderAppend* append = new (allocator) HStringBuilderAppend(
      fmt, num_args, has_fp_args, allocator, invoke->GetDexPc());
  append->SetReferenceTypeInfoIfValid(invoke->GetReferenceTypeInfo());
  for (size_t i = 0; i != num_args; ++i) {
    append->SetArgumentAt(i, args[num_args - 1u - i]);
  }
  block->InsertInstructionBefore(append, invoke);
  DCHECK(!invoke->CanBeNull());
  DCHECK(!append->CanBeNull());
  invoke->ReplaceWith(append);
  // Copy environment, except for the StringBuilder uses.
  for (HEnvironment* env = invoke->GetEnvironment(); env != nullptr; env = env->GetParent()) {
    for (size_t i = 0, size = env->Size(); i != size; ++i) {
      if (env->GetInstructionAt(i) == sb) {
        env->RemoveAsUserOfInput(i);
        env->SetRawEnvAt(i, /*instruction=*/ nullptr);
      }
    }
  }
  append->CopyEnvironmentFrom(invoke->GetEnvironment());
  // Remove the old instruction.
  block->RemoveInstruction(invoke);
  // Remove the StringBuilder's uses and StringBuilder.
  while (sb->HasNonEnvironmentUses()) {
    block->RemoveInstruction(sb->GetUses().front().GetUser());
  }
  DCHECK(!sb->HasEnvironmentUses());
  block->RemoveInstruction(sb);
  return true;
}

// Certain allocation intrinsics are not removed by dead code elimination
// because of potentially throwing an OOM exception or other side effects.
// This method removes such intrinsics when special circumstances allow.
void InstructionSimplifierVisitor::SimplifyAllocationIntrinsic(HInvoke* invoke) {
  if (!invoke->HasUses()) {
    // Instruction has no uses. If unsynchronized, we can remove right away, safely ignoring
    // the potential OOM of course. Otherwise, we must ensure the receiver object of this
    // call does not escape since only thread-local synchronization may be removed.
    bool is_synchronized = invoke->GetIntrinsic() == Intrinsics::kStringBufferToString;
    HInstruction* receiver = invoke->InputAt(0);
    if (!is_synchronized || DoesNotEscape(receiver, NoEscapeForStringBufferReference)) {
      invoke->GetBlock()->RemoveInstruction(invoke);
      RecordSimplification();
    }
  } else if (invoke->GetIntrinsic() == Intrinsics::kStringBuilderToString &&
             TryReplaceStringBuilderAppend(invoke)) {
    RecordSimplification();
  }
}

void InstructionSimplifierVisitor::SimplifyVarHandleIntrinsic(HInvoke* invoke) {
  DCHECK(invoke->IsInvokePolymorphic());
  VarHandleOptimizations optimizations(invoke);

  if (optimizations.GetDoNotIntrinsify()) {
    // Preceding static checks disabled intrinsic, so no need to analyze further.
    return;
  }

  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
  if (expected_coordinates_count != 0u) {
    HInstruction* object = invoke->InputAt(1);
    // The following has been ensured by static checks in the instruction builder.
    DCHECK(object->GetType() == DataType::Type::kReference);
    // Re-check for null constant, as this might have changed after the inliner.
    if (object->IsNullConstant()) {
      optimizations.SetDoNotIntrinsify();
      return;
    }
    // Test whether we can avoid the null check on the object.
    if (CanEnsureNotNullAt(object, invoke)) {
      optimizations.SetSkipObjectNullCheck();
    }
  }

  if (CanUseKnownBootImageVarHandle(invoke)) {
    optimizations.SetUseKnownBootImageVarHandle();
  }
}

bool InstructionSimplifierVisitor::CanUseKnownBootImageVarHandle(HInvoke* invoke) {
  // If the `VarHandle` comes from a static final field of an initialized class in
  // the boot image, we can do the checks at compile time. We do this optimization only
  // for AOT and only for field handles when we can avoid all checks. This avoids the
  // possibility of the code concurrently messing with the `VarHandle` using reflection,
  // we simply perform the operation with the `VarHandle` as seen at compile time.
  // TODO: Extend this to arrays to support the `AtomicIntegerArray` class.
  const CompilerOptions& compiler_options = codegen_->GetCompilerOptions();
  if (!compiler_options.IsAotCompiler()) {
    return false;
  }
  size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
  if (expected_coordinates_count == 2u) {
    return false;
  }
  HInstruction* var_handle_instruction = invoke->InputAt(0);
  if (var_handle_instruction->IsNullCheck()) {
    var_handle_instruction = var_handle_instruction->InputAt(0);
  }
  if (!var_handle_instruction->IsStaticFieldGet()) {
    return false;
  }
  ArtField* field = var_handle_instruction->AsStaticFieldGet()->GetFieldInfo().GetField();
  DCHECK(field->IsStatic());
  if (!field->IsFinal()) {
    return false;
  }
  ScopedObjectAccess soa(Thread::Current());
  ObjPtr<mirror::Class> declaring_class = field->GetDeclaringClass();
  if (!declaring_class->IsVisiblyInitialized()) {
    // During AOT compilation, dex2oat ensures that initialized classes are visibly initialized.
    DCHECK(!declaring_class->IsInitialized());
    return false;
  }
  HInstruction* load_class = var_handle_instruction->InputAt(0);
  if (kIsDebugBuild) {
    bool is_in_boot_image = false;
    if (Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(declaring_class)) {
      is_in_boot_image = true;
    } else if (compiler_options.IsBootImage() || compiler_options.IsBootImageExtension()) {
      std::string storage;
      const char* descriptor = declaring_class->GetDescriptor(&storage);
      is_in_boot_image = compiler_options.IsImageClass(descriptor);
    }
    CHECK_EQ(is_in_boot_image,
             load_class->IsLoadClass() && load_class->AsLoadClass()->IsInBootImage());
  }
  if (!load_class->IsLoadClass() || !load_class->AsLoadClass()->IsInBootImage()) {
    return false;
  }

  // Get the `VarHandle` object and check its class.
  ObjPtr<mirror::Class> expected_var_handle_class;
  switch (expected_coordinates_count) {
    case 0:
      expected_var_handle_class = GetClassRoot<mirror::StaticFieldVarHandle>();
      break;
    default:
      DCHECK_EQ(expected_coordinates_count, 1u);
      expected_var_handle_class = GetClassRoot<mirror::FieldVarHandle>();
      break;
  }
  ObjPtr<mirror::Object> var_handle_object = field->GetObject(declaring_class);
  if (var_handle_object == nullptr || var_handle_object->GetClass() != expected_var_handle_class) {
    return false;
  }
  ObjPtr<mirror::VarHandle> var_handle = ObjPtr<mirror::VarHandle>::DownCast(var_handle_object);

  // Check access mode.
  mirror::VarHandle::AccessMode access_mode =
      mirror::VarHandle::GetAccessModeByIntrinsic(invoke->GetIntrinsic());
  if (!var_handle->IsAccessModeSupported(access_mode)) {
    return false;
  }

  // Check argument types.
  ObjPtr<mirror::Class> var_type = var_handle->GetVarType();
  mirror::VarHandle::AccessModeTemplate access_mode_template =
      mirror::VarHandle::GetAccessModeTemplate(access_mode);
  // Note: The data type of input arguments does not need to match the type from shorty
  // due to implicit conversions or avoiding unnecessary conversions before narrow stores.
  DataType::Type type = (access_mode_template == mirror::VarHandle::AccessModeTemplate::kGet)
      ? invoke->GetType()
      : GetDataTypeFromShorty(invoke, invoke->GetNumberOfArguments() - 1u);
  if (type != DataTypeFromPrimitive(var_type->GetPrimitiveType())) {
    return false;
  }
  if (type == DataType::Type::kReference) {
    uint32_t arguments_start = /* VarHandle object */ 1u + expected_coordinates_count;
    uint32_t number_of_arguments = invoke->GetNumberOfArguments();
    for (size_t arg_index = arguments_start; arg_index != number_of_arguments; ++arg_index) {
      HInstruction* arg = invoke->InputAt(arg_index);
      DCHECK_EQ(arg->GetType(), DataType::Type::kReference);
      if (!arg->IsNullConstant()) {
        ReferenceTypeInfo arg_type_info = arg->GetReferenceTypeInfo();
        if (!arg_type_info.IsValid() ||
            !var_type->IsAssignableFrom(arg_type_info.GetTypeHandle().Get())) {
          return false;
        }
      }
    }
  }

  // Check the first coordinate.
  if (expected_coordinates_count != 0u) {
    ObjPtr<mirror::Class> coordinate0_type = var_handle->GetCoordinateType0();
    DCHECK(coordinate0_type != nullptr);
    ReferenceTypeInfo object_type_info = invoke->InputAt(1)->GetReferenceTypeInfo();
    if (!object_type_info.IsValid() ||
        !coordinate0_type->IsAssignableFrom(object_type_info.GetTypeHandle().Get())) {
      return false;
    }
  }

  // All required checks passed.
  return true;
}

void InstructionSimplifierVisitor::VisitInvoke(HInvoke* instruction) {
  switch (instruction->GetIntrinsic()) {
    case Intrinsics::kStringEquals:
      SimplifyStringEquals(instruction);
      break;
    case Intrinsics::kSystemArrayCopy:
      SimplifySystemArrayCopy(instruction);
      break;
    case Intrinsics::kFloatFloatToIntBits:
    case Intrinsics::kDoubleDoubleToLongBits:
      SimplifyFP2Int(instruction);
      break;
    case Intrinsics::kStringCharAt:
      // Instruction builder creates intermediate representation directly
      // but the inliner can sharpen CharSequence.charAt() to String.charAt().
      SimplifyStringCharAt(instruction);
      break;
    case Intrinsics::kStringLength:
      // Instruction builder creates intermediate representation directly
      // but the inliner can sharpen CharSequence.length() to String.length().
      SimplifyStringLength(instruction);
      break;
    case Intrinsics::kStringIndexOf:
    case Intrinsics::kStringIndexOfAfter:
      SimplifyStringIndexOf(instruction);
      break;
    case Intrinsics::kStringStringIndexOf:
    case Intrinsics::kStringStringIndexOfAfter:
      SimplifyNPEOnArgN(instruction, 1);  // 0th has own NullCheck
      break;
    case Intrinsics::kStringBufferAppend:
    case Intrinsics::kStringBuilderAppendObject:
    case Intrinsics::kStringBuilderAppendString:
    case Intrinsics::kStringBuilderAppendCharSequence:
    case Intrinsics::kStringBuilderAppendCharArray:
    case Intrinsics::kStringBuilderAppendBoolean:
    case Intrinsics::kStringBuilderAppendChar:
    case Intrinsics::kStringBuilderAppendInt:
    case Intrinsics::kStringBuilderAppendLong:
    case Intrinsics::kStringBuilderAppendFloat:
    case Intrinsics::kStringBuilderAppendDouble:
      SimplifyReturnThis(instruction);
      break;
    case Intrinsics::kStringBufferToString:
    case Intrinsics::kStringBuilderToString:
      SimplifyAllocationIntrinsic(instruction);
      break;
    case Intrinsics::kVarHandleCompareAndExchange:
    case Intrinsics::kVarHandleCompareAndExchangeAcquire:
    case Intrinsics::kVarHandleCompareAndExchangeRelease:
    case Intrinsics::kVarHandleCompareAndSet:
    case Intrinsics::kVarHandleGet:
    case Intrinsics::kVarHandleGetAcquire:
    case Intrinsics::kVarHandleGetAndAdd:
    case Intrinsics::kVarHandleGetAndAddAcquire:
    case Intrinsics::kVarHandleGetAndAddRelease:
    case Intrinsics::kVarHandleGetAndBitwiseAnd:
    case Intrinsics::kVarHandleGetAndBitwiseAndAcquire:
    case Intrinsics::kVarHandleGetAndBitwiseAndRelease:
    case Intrinsics::kVarHandleGetAndBitwiseOr:
    case Intrinsics::kVarHandleGetAndBitwiseOrAcquire:
    case Intrinsics::kVarHandleGetAndBitwiseOrRelease:
    case Intrinsics::kVarHandleGetAndBitwiseXor:
    case Intrinsics::kVarHandleGetAndBitwiseXorAcquire:
    case Intrinsics::kVarHandleGetAndBitwiseXorRelease:
    case Intrinsics::kVarHandleGetAndSet:
    case Intrinsics::kVarHandleGetAndSetAcquire:
    case Intrinsics::kVarHandleGetAndSetRelease:
    case Intrinsics::kVarHandleGetOpaque:
    case Intrinsics::kVarHandleGetVolatile:
    case Intrinsics::kVarHandleSet:
    case Intrinsics::kVarHandleSetOpaque:
    case Intrinsics::kVarHandleSetRelease:
    case Intrinsics::kVarHandleSetVolatile:
    case Intrinsics::kVarHandleWeakCompareAndSet:
    case Intrinsics::kVarHandleWeakCompareAndSetAcquire:
    case Intrinsics::kVarHandleWeakCompareAndSetPlain:
    case Intrinsics::kVarHandleWeakCompareAndSetRelease:
      SimplifyVarHandleIntrinsic(instruction);
      break;
    default:
      break;
  }
}

void InstructionSimplifierVisitor::VisitDeoptimize(HDeoptimize* deoptimize) {
  HInstruction* cond = deoptimize->InputAt(0);
  if (cond->IsConstant()) {
    if (cond->AsIntConstant()->IsFalse()) {
      // Never deopt: instruction can be removed.
      if (deoptimize->GuardsAnInput()) {
        deoptimize->ReplaceWith(deoptimize->GuardedInput());
      }
      deoptimize->GetBlock()->RemoveInstruction(deoptimize);
    } else {
      // Always deopt.
    }
  }
}

// Replace code looking like
//    OP y, x, const1
//    OP z, y, const2
// with
//    OP z, x, const3
// where OP is both an associative and a commutative operation.
bool InstructionSimplifierVisitor::TryHandleAssociativeAndCommutativeOperation(
    HBinaryOperation* instruction) {
  DCHECK(instruction->IsCommutative());

  if (!DataType::IsIntegralType(instruction->GetType())) {
    return false;
  }

  HInstruction* left = instruction->GetLeft();
  HInstruction* right = instruction->GetRight();
  // Variable names as described above.
  HConstant* const2;
  HBinaryOperation* y;

  if (instruction->GetKind() == left->GetKind() && right->IsConstant()) {
    const2 = right->AsConstant();
    y = left->AsBinaryOperation();
  } else if (left->IsConstant() && instruction->GetKind() == right->GetKind()) {
    const2 = left->AsConstant();
    y = right->AsBinaryOperation();
  } else {
    // The node does not match the pattern.
    return false;
  }

  // If `y` has more than one use, we do not perform the optimization
  // because it might increase code size (e.g. if the new constant is
  // no longer encodable as an immediate operand in the target ISA).
  if (!y->HasOnlyOneNonEnvironmentUse()) {
    return false;
  }

  // GetConstantRight() can return both left and right constants
  // for commutative operations.
  HConstant* const1 = y->GetConstantRight();
  if (const1 == nullptr) {
    return false;
  }

  instruction->ReplaceInput(const1, 0);
  instruction->ReplaceInput(const2, 1);
  HConstant* const3 = instruction->TryStaticEvaluation();
  DCHECK(const3 != nullptr);
  instruction->ReplaceInput(y->GetLeastConstantLeft(), 0);
  instruction->ReplaceInput(const3, 1);
  RecordSimplification();
  return true;
}

static HBinaryOperation* AsAddOrSub(HInstruction* binop) {
  return (binop->IsAdd() || binop->IsSub()) ? binop->AsBinaryOperation() : nullptr;
}

// Helper function that performs addition statically, considering the result type.
static int64_t ComputeAddition(DataType::Type type, int64_t x, int64_t y) {
  // Use the Compute() method for consistency with TryStaticEvaluation().
  if (type == DataType::Type::kInt32) {
    return HAdd::Compute<int32_t>(x, y);
  } else {
    DCHECK_EQ(type, DataType::Type::kInt64);
    return HAdd::Compute<int64_t>(x, y);
  }
}

// Helper function that handles the child classes of HConstant
// and returns an integer with the appropriate sign.
static int64_t GetValue(HConstant* constant, bool is_negated) {
  int64_t ret = Int64FromConstant(constant);
  return is_negated ? -ret : ret;
}

// Replace code looking like
//    OP1 y, x, const1
//    OP2 z, y, const2
// with
//    OP3 z, x, const3
// where OPx is either ADD or SUB, and at least one of OP{1,2} is SUB.
bool InstructionSimplifierVisitor::TrySubtractionChainSimplification(
    HBinaryOperation* instruction) {
  DCHECK(instruction->IsAdd() || instruction->IsSub()) << instruction->DebugName();

  DataType::Type type = instruction->GetType();
  if (!DataType::IsIntegralType(type)) {
    return false;
  }

  HInstruction* left = instruction->GetLeft();
  HInstruction* right = instruction->GetRight();
  // Variable names as described above.
  HConstant* const2 = right->IsConstant() ? right->AsConstant() : left->AsConstantOrNull();
  if (const2 == nullptr) {
    return false;
  }

  HBinaryOperation* y = (AsAddOrSub(left) != nullptr)
      ? left->AsBinaryOperation()
      : AsAddOrSub(right);
  // If y has more than one use, we do not perform the optimization because
  // it might increase code size (e.g. if the new constant is no longer
  // encodable as an immediate operand in the target ISA).
  if ((y == nullptr) || !y->HasOnlyOneNonEnvironmentUse()) {
    return false;
  }

  left = y->GetLeft();
  HConstant* const1 = left->IsConstant() ? left->AsConstant() : y->GetRight()->AsConstantOrNull();
  if (const1 == nullptr) {
    return false;
  }

  HInstruction* x = (const1 == left) ? y->GetRight() : left;
  // If both inputs are constants, let the constant folding pass deal with it.
  if (x->IsConstant()) {
    return false;
  }

  bool is_const2_negated = (const2 == right) && instruction->IsSub();
  int64_t const2_val = GetValue(const2, is_const2_negated);
  bool is_y_negated = (y == right) && instruction->IsSub();
  right = y->GetRight();
  bool is_const1_negated = is_y_negated ^ ((const1 == right) && y->IsSub());
  int64_t const1_val = GetValue(const1, is_const1_negated);
  bool is_x_negated = is_y_negated ^ ((x == right) && y->IsSub());
  int64_t const3_val = ComputeAddition(type, const1_val, const2_val);
  HBasicBlock* block = instruction->GetBlock();
  HConstant* const3 = block->GetGraph()->GetConstant(type, const3_val);
  ArenaAllocator* allocator = instruction->GetAllocator();
  HInstruction* z;

  if (is_x_negated) {
    z = new (allocator) HSub(type, const3, x, instruction->GetDexPc());
  } else {
    z = new (allocator) HAdd(type, x, const3, instruction->GetDexPc());
  }

  block->ReplaceAndRemoveInstructionWith(instruction, z);
  RecordSimplification();
  return true;
}

void InstructionSimplifierVisitor::VisitVecMul(HVecMul* instruction) {
  if (TryCombineVecMultiplyAccumulate(instruction)) {
    RecordSimplification();
  }
}

}  // namespace art
