/*
 * 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 "bounds_check_elimination.h"

#include <limits>

#include "base/scoped_arena_allocator.h"
#include "base/scoped_arena_containers.h"
#include "induction_var_range.h"
#include "nodes.h"
#include "side_effects_analysis.h"

namespace art HIDDEN {

class MonotonicValueRange;

/**
 * A value bound is represented as a pair of value and constant,
 * e.g. array.length - 1.
 */
class ValueBound : public ValueObject {
 public:
  ValueBound(HInstruction* instruction, int32_t constant) {
    if (instruction != nullptr && instruction->IsIntConstant()) {
      // Normalize ValueBound with constant instruction.
      int32_t instr_const = instruction->AsIntConstant()->GetValue();
      if (!WouldAddOverflowOrUnderflow(instr_const, constant)) {
        instruction_ = nullptr;
        constant_ = instr_const + constant;
        return;
      }
    }
    instruction_ = instruction;
    constant_ = constant;
  }

  // Return whether (left + right) overflows or underflows.
  static bool WouldAddOverflowOrUnderflow(int32_t left, int32_t right) {
    if (right == 0) {
      return false;
    }
    if ((right > 0) && (left <= (std::numeric_limits<int32_t>::max() - right))) {
      // No overflow.
      return false;
    }
    if ((right < 0) && (left >= (std::numeric_limits<int32_t>::min() - right))) {
      // No underflow.
      return false;
    }
    return true;
  }

  // Return true if instruction can be expressed as "left_instruction + right_constant".
  static bool IsAddOrSubAConstant(HInstruction* instruction,
                                  /* out */ HInstruction** left_instruction,
                                  /* out */ int32_t* right_constant) {
    HInstruction* left_so_far = nullptr;
    int32_t right_so_far = 0;
    while (instruction->IsAdd() || instruction->IsSub()) {
      HBinaryOperation* bin_op = instruction->AsBinaryOperation();
      HInstruction* left = bin_op->GetLeft();
      HInstruction* right = bin_op->GetRight();
      if (right->IsIntConstant()) {
        int32_t v = right->AsIntConstant()->GetValue();
        int32_t c = instruction->IsAdd() ? v : -v;
        if (!WouldAddOverflowOrUnderflow(right_so_far, c)) {
          instruction = left;
          left_so_far = left;
          right_so_far += c;
          continue;
        }
      }
      break;
    }
    // Return result: either false and "null+0" or true and "instr+constant".
    *left_instruction = left_so_far;
    *right_constant = right_so_far;
    return left_so_far != nullptr;
  }

  // Expresses any instruction as a value bound.
  static ValueBound AsValueBound(HInstruction* instruction) {
    if (instruction->IsIntConstant()) {
      return ValueBound(nullptr, instruction->AsIntConstant()->GetValue());
    }
    HInstruction *left;
    int32_t right;
    if (IsAddOrSubAConstant(instruction, &left, &right)) {
      return ValueBound(left, right);
    }
    return ValueBound(instruction, 0);
  }

  // Try to detect useful value bound format from an instruction, e.g.
  // a constant or array length related value.
  static ValueBound DetectValueBoundFromValue(HInstruction* instruction, /* out */ bool* found) {
    DCHECK(instruction != nullptr);
    if (instruction->IsIntConstant()) {
      *found = true;
      return ValueBound(nullptr, instruction->AsIntConstant()->GetValue());
    }

    if (instruction->IsArrayLength()) {
      *found = true;
      return ValueBound(instruction, 0);
    }
    // Try to detect (array.length + c) format.
    HInstruction *left;
    int32_t right;
    if (IsAddOrSubAConstant(instruction, &left, &right)) {
      if (left->IsArrayLength()) {
        *found = true;
        return ValueBound(left, right);
      }
    }

    // No useful bound detected.
    *found = false;
    return ValueBound::Max();
  }

  HInstruction* GetInstruction() const { return instruction_; }
  int32_t GetConstant() const { return constant_; }

  bool IsRelatedToArrayLength() const {
    // Some bounds are created with HNewArray* as the instruction instead
    // of HArrayLength*. They are treated the same.
    return (instruction_ != nullptr) &&
           (instruction_->IsArrayLength() || instruction_->IsNewArray());
  }

  bool IsConstant() const {
    return instruction_ == nullptr;
  }

  static ValueBound Min() { return ValueBound(nullptr, std::numeric_limits<int32_t>::min()); }
  static ValueBound Max() { return ValueBound(nullptr, std::numeric_limits<int32_t>::max()); }

  bool Equals(ValueBound bound) const {
    return instruction_ == bound.instruction_ && constant_ == bound.constant_;
  }

  static bool Equal(HInstruction* instruction1, HInstruction* instruction2) {
    if (instruction1 == instruction2) {
      return true;
    }
    if (instruction1 == nullptr || instruction2 == nullptr) {
      return false;
    }
    instruction1 = HuntForDeclaration(instruction1);
    instruction2 = HuntForDeclaration(instruction2);
    return instruction1 == instruction2;
  }

  // Returns if it's certain this->bound >= `bound`.
  bool GreaterThanOrEqualTo(ValueBound bound) const {
    if (Equal(instruction_, bound.instruction_)) {
      return constant_ >= bound.constant_;
    }
    // Not comparable. Just return false.
    return false;
  }

  // Returns if it's certain this->bound <= `bound`.
  bool LessThanOrEqualTo(ValueBound bound) const {
    if (Equal(instruction_, bound.instruction_)) {
      return constant_ <= bound.constant_;
    }
    // Not comparable. Just return false.
    return false;
  }

  // Returns if it's certain this->bound > `bound`.
  bool GreaterThan(ValueBound bound) const {
    if (Equal(instruction_, bound.instruction_)) {
      return constant_ > bound.constant_;
    }
    // Not comparable. Just return false.
    return false;
  }

  // Returns if it's certain this->bound < `bound`.
  bool LessThan(ValueBound bound) const {
    if (Equal(instruction_, bound.instruction_)) {
      return constant_ < bound.constant_;
    }
    // Not comparable. Just return false.
    return false;
  }

  // Try to narrow lower bound. Returns the greatest of the two if possible.
  // Pick one if they are not comparable.
  static ValueBound NarrowLowerBound(ValueBound bound1, ValueBound bound2) {
    if (bound1.GreaterThanOrEqualTo(bound2)) {
      return bound1;
    }
    if (bound2.GreaterThanOrEqualTo(bound1)) {
      return bound2;
    }

    // Not comparable. Just pick one. We may lose some info, but that's ok.
    // Favor constant as lower bound.
    return bound1.IsConstant() ? bound1 : bound2;
  }

  // Try to narrow upper bound. Returns the lowest of the two if possible.
  // Pick one if they are not comparable.
  static ValueBound NarrowUpperBound(ValueBound bound1, ValueBound bound2) {
    if (bound1.LessThanOrEqualTo(bound2)) {
      return bound1;
    }
    if (bound2.LessThanOrEqualTo(bound1)) {
      return bound2;
    }

    // Not comparable. Just pick one. We may lose some info, but that's ok.
    // Favor array length as upper bound.
    return bound1.IsRelatedToArrayLength() ? bound1 : bound2;
  }

  // Add a constant to a ValueBound.
  // `overflow` or `underflow` will return whether the resulting bound may
  // overflow or underflow an int.
  ValueBound Add(int32_t c, /* out */ bool* overflow, /* out */ bool* underflow) const {
    *overflow = *underflow = false;
    if (c == 0) {
      return *this;
    }

    int32_t new_constant;
    if (c > 0) {
      if (constant_ > (std::numeric_limits<int32_t>::max() - c)) {
        *overflow = true;
        return Max();
      }

      new_constant = constant_ + c;
      // (array.length + non-positive-constant) won't overflow an int.
      if (IsConstant() || (IsRelatedToArrayLength() && new_constant <= 0)) {
        return ValueBound(instruction_, new_constant);
      }
      // Be conservative.
      *overflow = true;
      return Max();
    } else {
      if (constant_ < (std::numeric_limits<int32_t>::min() - c)) {
        *underflow = true;
        return Min();
      }

      new_constant = constant_ + c;
      // Regardless of the value new_constant, (array.length+new_constant) will
      // never underflow since array.length is no less than 0.
      if (IsConstant() || IsRelatedToArrayLength()) {
        return ValueBound(instruction_, new_constant);
      }
      // Be conservative.
      *underflow = true;
      return Min();
    }
  }

 private:
  HInstruction* instruction_;
  int32_t constant_;
};

/**
 * Represent a range of lower bound and upper bound, both being inclusive.
 * Currently a ValueRange may be generated as a result of the following:
 * comparisons related to array bounds, array bounds check, add/sub on top
 * of an existing value range, NewArray or a loop phi corresponding to an
 * incrementing/decrementing array index (MonotonicValueRange).
 */
class ValueRange : public ArenaObject<kArenaAllocBoundsCheckElimination> {
 public:
  ValueRange(ScopedArenaAllocator* allocator, ValueBound lower, ValueBound upper)
      : allocator_(allocator), lower_(lower), upper_(upper) {}

  virtual ~ValueRange() {}

  virtual MonotonicValueRange* AsMonotonicValueRange() { return nullptr; }
  bool IsMonotonicValueRange() {
    return AsMonotonicValueRange() != nullptr;
  }

  ScopedArenaAllocator* GetAllocator() const { return allocator_; }
  ValueBound GetLower() const { return lower_; }
  ValueBound GetUpper() const { return upper_; }

  bool IsConstantValueRange() const { return lower_.IsConstant() && upper_.IsConstant(); }

  // If it's certain that this value range fits in other_range.
  virtual bool FitsIn(ValueRange* other_range) const {
    if (other_range == nullptr) {
      return true;
    }
    DCHECK(!other_range->IsMonotonicValueRange());
    return lower_.GreaterThanOrEqualTo(other_range->lower_) &&
           upper_.LessThanOrEqualTo(other_range->upper_);
  }

  // Returns the intersection of this and range.
  // If it's not possible to do intersection because some
  // bounds are not comparable, it's ok to pick either bound.
  virtual ValueRange* Narrow(ValueRange* range) {
    if (range == nullptr) {
      return this;
    }

    if (range->IsMonotonicValueRange()) {
      return this;
    }

    return new (allocator_) ValueRange(
        allocator_,
        ValueBound::NarrowLowerBound(lower_, range->lower_),
        ValueBound::NarrowUpperBound(upper_, range->upper_));
  }

  // Shift a range by a constant.
  ValueRange* Add(int32_t constant) const {
    bool overflow, underflow;
    ValueBound lower = lower_.Add(constant, &overflow, &underflow);
    if (underflow) {
      // Lower bound underflow will wrap around to positive values
      // and invalidate the upper bound.
      return nullptr;
    }
    ValueBound upper = upper_.Add(constant, &overflow, &underflow);
    if (overflow) {
      // Upper bound overflow will wrap around to negative values
      // and invalidate the lower bound.
      return nullptr;
    }
    return new (allocator_) ValueRange(allocator_, lower, upper);
  }

 private:
  ScopedArenaAllocator* const allocator_;
  const ValueBound lower_;  // inclusive
  const ValueBound upper_;  // inclusive

  DISALLOW_COPY_AND_ASSIGN(ValueRange);
};

/**
 * A monotonically incrementing/decrementing value range, e.g.
 * the variable i in "for (int i=0; i<array.length; i++)".
 * Special care needs to be taken to account for overflow/underflow
 * of such value ranges.
 */
class MonotonicValueRange : public ValueRange {
 public:
  MonotonicValueRange(ScopedArenaAllocator* allocator,
                      HPhi* induction_variable,
                      HInstruction* initial,
                      int32_t increment,
                      ValueBound bound)
      // To be conservative, give it full range [Min(), Max()] in case it's
      // used as a regular value range, due to possible overflow/underflow.
      : ValueRange(allocator, ValueBound::Min(), ValueBound::Max()),
        induction_variable_(induction_variable),
        initial_(initial),
        increment_(increment),
        bound_(bound) {}

  virtual ~MonotonicValueRange() {}

  int32_t GetIncrement() const { return increment_; }
  ValueBound GetBound() const { return bound_; }
  HBasicBlock* GetLoopHeader() const {
    DCHECK(induction_variable_->GetBlock()->IsLoopHeader());
    return induction_variable_->GetBlock();
  }

  MonotonicValueRange* AsMonotonicValueRange() override { return this; }

  // If it's certain that this value range fits in other_range.
  bool FitsIn(ValueRange* other_range) const override {
    if (other_range == nullptr) {
      return true;
    }
    DCHECK(!other_range->IsMonotonicValueRange());
    return false;
  }

  // Try to narrow this MonotonicValueRange given another range.
  // Ideally it will return a normal ValueRange. But due to
  // possible overflow/underflow, that may not be possible.
  ValueRange* Narrow(ValueRange* range) override {
    if (range == nullptr) {
      return this;
    }
    DCHECK(!range->IsMonotonicValueRange());

    if (increment_ > 0) {
      // Monotonically increasing.
      ValueBound lower = ValueBound::NarrowLowerBound(bound_, range->GetLower());
      if (!lower.IsConstant() || lower.GetConstant() == std::numeric_limits<int32_t>::min()) {
        // Lower bound isn't useful. Leave it to deoptimization.
        return this;
      }

      // We currently conservatively assume max array length is Max().
      // If we can make assumptions about the max array length, e.g. due to the max heap size,
      // divided by the element size (such as 4 bytes for each integer array), we can
      // lower this number and rule out some possible overflows.
      int32_t max_array_len = std::numeric_limits<int32_t>::max();

      // max possible integer value of range's upper value.
      int32_t upper = std::numeric_limits<int32_t>::max();
      // Try to lower upper.
      ValueBound upper_bound = range->GetUpper();
      if (upper_bound.IsConstant()) {
        upper = upper_bound.GetConstant();
      } else if (upper_bound.IsRelatedToArrayLength() && upper_bound.GetConstant() <= 0) {
        // Normal case. e.g. <= array.length - 1.
        upper = max_array_len + upper_bound.GetConstant();
      }

      // If we can prove for the last number in sequence of initial_,
      // initial_ + increment_, initial_ + 2 x increment_, ...
      // that's <= upper, (last_num_in_sequence + increment_) doesn't trigger overflow,
      // then this MonoticValueRange is narrowed to a normal value range.

      // Be conservative first, assume last number in the sequence hits upper.
      int32_t last_num_in_sequence = upper;
      if (initial_->IsIntConstant()) {
        int32_t initial_constant = initial_->AsIntConstant()->GetValue();
        if (upper <= initial_constant) {
          last_num_in_sequence = upper;
        } else {
          // Cast to int64_t for the substraction part to avoid int32_t overflow.
          last_num_in_sequence = initial_constant +
              ((int64_t)upper - (int64_t)initial_constant) / increment_ * increment_;
        }
      }
      if (last_num_in_sequence <= (std::numeric_limits<int32_t>::max() - increment_)) {
        // No overflow. The sequence will be stopped by the upper bound test as expected.
        return new (GetAllocator()) ValueRange(GetAllocator(), lower, range->GetUpper());
      }

      // There might be overflow. Give up narrowing.
      return this;
    } else {
      DCHECK_NE(increment_, 0);
      // Monotonically decreasing.
      ValueBound upper = ValueBound::NarrowUpperBound(bound_, range->GetUpper());
      if ((!upper.IsConstant() || upper.GetConstant() == std::numeric_limits<int32_t>::max()) &&
          !upper.IsRelatedToArrayLength()) {
        // Upper bound isn't useful. Leave it to deoptimization.
        return this;
      }

      // Need to take care of underflow. Try to prove underflow won't happen
      // for common cases.
      if (range->GetLower().IsConstant()) {
        int32_t constant = range->GetLower().GetConstant();
        if (constant >= (std::numeric_limits<int32_t>::min() - increment_)) {
          return new (GetAllocator()) ValueRange(GetAllocator(), range->GetLower(), upper);
        }
      }

      // For non-constant lower bound, just assume might be underflow. Give up narrowing.
      return this;
    }
  }

 private:
  HPhi* const induction_variable_;  // Induction variable for this monotonic value range.
  HInstruction* const initial_;     // Initial value.
  const int32_t increment_;         // Increment for each loop iteration.
  const ValueBound bound_;          // Additional value bound info for initial_.

  DISALLOW_COPY_AND_ASSIGN(MonotonicValueRange);
};

class BCEVisitor final : public HGraphVisitor {
 public:
  // The least number of bounds checks that should be eliminated by triggering
  // the deoptimization technique.
  static constexpr size_t kThresholdForAddingDeoptimize = 2;

  // Very large lengths are considered an anomaly. This is a threshold beyond which we don't
  // bother to apply the deoptimization technique since it's likely, or sometimes certain,
  // an AIOOBE will be thrown.
  static constexpr uint32_t kMaxLengthForAddingDeoptimize =
      std::numeric_limits<int32_t>::max() - 1024 * 1024;

  // Added blocks for loop body entry test.
  bool IsAddedBlock(HBasicBlock* block) const {
    return block->GetBlockId() >= initial_block_size_;
  }

  BCEVisitor(HGraph* graph,
             const SideEffectsAnalysis& side_effects,
             HInductionVarAnalysis* induction_analysis)
      : HGraphVisitor(graph),
        allocator_(graph->GetArenaStack()),
        maps_(graph->GetBlocks().size(),
              ScopedArenaSafeMap<int, ValueRange*>(
                  std::less<int>(),
                  allocator_.Adapter(kArenaAllocBoundsCheckElimination)),
              allocator_.Adapter(kArenaAllocBoundsCheckElimination)),
        first_index_bounds_check_map_(std::less<int>(),
                                      allocator_.Adapter(kArenaAllocBoundsCheckElimination)),
        early_exit_loop_(std::less<uint32_t>(),
                         allocator_.Adapter(kArenaAllocBoundsCheckElimination)),
        taken_test_loop_(std::less<uint32_t>(),
                         allocator_.Adapter(kArenaAllocBoundsCheckElimination)),
        finite_loop_(allocator_.Adapter(kArenaAllocBoundsCheckElimination)),
        has_dom_based_dynamic_bce_(false),
        initial_block_size_(graph->GetBlocks().size()),
        side_effects_(side_effects),
        induction_range_(induction_analysis),
        next_(nullptr) {}

  void VisitBasicBlock(HBasicBlock* block) override {
    DCHECK(!IsAddedBlock(block));
    first_index_bounds_check_map_.clear();
    // Visit phis and instructions using a safe iterator. The iteration protects
    // against deleting the current instruction during iteration. However, it
    // must advance next_ if that instruction is deleted during iteration.
    for (HInstruction* instruction = block->GetFirstPhi(); instruction != nullptr;) {
      DCHECK(instruction->IsInBlock());
      next_ = instruction->GetNext();
      instruction->Accept(this);
      instruction = next_;
    }
    for (HInstruction* instruction = block->GetFirstInstruction(); instruction != nullptr;) {
      DCHECK(instruction->IsInBlock());
      next_ = instruction->GetNext();
      instruction->Accept(this);
      instruction = next_;
    }
    // We should never deoptimize from an osr method, otherwise we might wrongly optimize
    // code dominated by the deoptimization.
    if (!GetGraph()->IsCompilingOsr()) {
      AddComparesWithDeoptimization(block);
    }
  }

  void Finish() {
    // Preserve SSA structure which may have been broken by adding one or more
    // new taken-test structures (see TransformLoopForDeoptimizationIfNeeded()).
    InsertPhiNodes();

    // Clear the loop data structures.
    early_exit_loop_.clear();
    taken_test_loop_.clear();
    finite_loop_.clear();

    // We may have eliminated all bounds checks so we should update the flag.
    // TODO(solanes): Do this without a linear pass of the graph?
    GetGraph()->SetHasBoundsChecks(false);
    for (HBasicBlock* block : GetGraph()->GetReversePostOrder()) {
      for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
        HInstruction* instruction = it.Current();
        if (instruction->IsBoundsCheck()) {
          GetGraph()->SetHasBoundsChecks(true);
          return;
        }
      }
    }
  }

 private:
  // Return the map of proven value ranges at the beginning of a basic block.
  ScopedArenaSafeMap<int, ValueRange*>* GetValueRangeMap(HBasicBlock* basic_block) {
    if (IsAddedBlock(basic_block)) {
      // Added blocks don't keep value ranges.
      return nullptr;
    }
    return &maps_[basic_block->GetBlockId()];
  }

  // Traverse up the dominator tree to look for value range info.
  ValueRange* LookupValueRange(HInstruction* instruction, HBasicBlock* basic_block) {
    while (basic_block != nullptr) {
      ScopedArenaSafeMap<int, ValueRange*>* map = GetValueRangeMap(basic_block);
      if (map != nullptr) {
        if (map->find(instruction->GetId()) != map->end()) {
          return map->Get(instruction->GetId());
        }
      } else {
        DCHECK(IsAddedBlock(basic_block));
      }
      basic_block = basic_block->GetDominator();
    }
    // Didn't find any.
    return nullptr;
  }

  // Helper method to assign a new range to an instruction in given basic block.
  void AssignRange(HBasicBlock* basic_block, HInstruction* instruction, ValueRange* range) {
    DCHECK_IMPLIES(range->IsMonotonicValueRange(), instruction->IsLoopHeaderPhi());
    GetValueRangeMap(basic_block)->Overwrite(instruction->GetId(), range);
  }

  // Narrow the value range of `instruction` at the end of `basic_block` with `range`,
  // and push the narrowed value range to `successor`.
  void ApplyRangeFromComparison(HInstruction* instruction, HBasicBlock* basic_block,
                                HBasicBlock* successor, ValueRange* range) {
    ValueRange* existing_range = LookupValueRange(instruction, basic_block);
    if (existing_range == nullptr) {
      if (range != nullptr) {
        AssignRange(successor, instruction, range);
      }
      return;
    }
    if (existing_range->IsMonotonicValueRange()) {
      DCHECK(instruction->IsLoopHeaderPhi());
      // Make sure the comparison is in the loop header so each increment is
      // checked with a comparison.
      if (instruction->GetBlock() != basic_block) {
        return;
      }
    }
    AssignRange(successor, instruction, existing_range->Narrow(range));
  }

  // Special case that we may simultaneously narrow two MonotonicValueRange's to
  // regular value ranges.
  void HandleIfBetweenTwoMonotonicValueRanges(HIf* instruction,
                                              HInstruction* left,
                                              HInstruction* right,
                                              IfCondition cond,
                                              MonotonicValueRange* left_range,
                                              MonotonicValueRange* right_range) {
    DCHECK(left->IsLoopHeaderPhi());
    DCHECK(right->IsLoopHeaderPhi());
    if (instruction->GetBlock() != left->GetBlock()) {
      // Comparison needs to be in loop header to make sure it's done after each
      // increment/decrement.
      return;
    }

    // Handle common cases which also don't have overflow/underflow concerns.
    if (left_range->GetIncrement() == 1 &&
        left_range->GetBound().IsConstant() &&
        right_range->GetIncrement() == -1 &&
        right_range->GetBound().IsRelatedToArrayLength() &&
        right_range->GetBound().GetConstant() < 0) {
      HBasicBlock* successor = nullptr;
      int32_t left_compensation = 0;
      int32_t right_compensation = 0;
      if (cond == kCondLT) {
        left_compensation = -1;
        right_compensation = 1;
        successor = instruction->IfTrueSuccessor();
      } else if (cond == kCondLE) {
        successor = instruction->IfTrueSuccessor();
      } else if (cond == kCondGT) {
        successor = instruction->IfFalseSuccessor();
      } else if (cond == kCondGE) {
        left_compensation = -1;
        right_compensation = 1;
        successor = instruction->IfFalseSuccessor();
      } else {
        // We don't handle '=='/'!=' test in case left and right can cross and
        // miss each other.
        return;
      }

      if (successor != nullptr) {
        bool overflow;
        bool underflow;
        ValueRange* new_left_range = new (&allocator_) ValueRange(
            &allocator_,
            left_range->GetBound(),
            right_range->GetBound().Add(left_compensation, &overflow, &underflow));
        if (!overflow && !underflow) {
          ApplyRangeFromComparison(left, instruction->GetBlock(), successor,
                                   new_left_range);
        }

        ValueRange* new_right_range = new (&allocator_) ValueRange(
            &allocator_,
            left_range->GetBound().Add(right_compensation, &overflow, &underflow),
            right_range->GetBound());
        if (!overflow && !underflow) {
          ApplyRangeFromComparison(right, instruction->GetBlock(), successor,
                                   new_right_range);
        }
      }
    }
  }

  // Handle "if (left cmp_cond right)".
  void HandleIf(HIf* instruction, HInstruction* left, HInstruction* right, IfCondition cond) {
    HBasicBlock* block = instruction->GetBlock();

    HBasicBlock* true_successor = instruction->IfTrueSuccessor();
    // There should be no critical edge at this point.
    DCHECK_EQ(true_successor->GetPredecessors().size(), 1u);

    HBasicBlock* false_successor = instruction->IfFalseSuccessor();
    // There should be no critical edge at this point.
    DCHECK_EQ(false_successor->GetPredecessors().size(), 1u);

    ValueRange* left_range = LookupValueRange(left, block);
    MonotonicValueRange* left_monotonic_range = nullptr;
    if (left_range != nullptr) {
      left_monotonic_range = left_range->AsMonotonicValueRange();
      if (left_monotonic_range != nullptr) {
        HBasicBlock* loop_head = left_monotonic_range->GetLoopHeader();
        if (instruction->GetBlock() != loop_head) {
          // For monotonic value range, don't handle `instruction`
          // if it's not defined in the loop header.
          return;
        }
      }
    }

    bool found;
    ValueBound bound = ValueBound::DetectValueBoundFromValue(right, &found);
    // Each comparison can establish a lower bound and an upper bound
    // for the left hand side.
    ValueBound lower = bound;
    ValueBound upper = bound;
    if (!found) {
      // No constant or array.length+c format bound found.
      // For i<j, we can still use j's upper bound as i's upper bound. Same for lower.
      ValueRange* right_range = LookupValueRange(right, block);
      if (right_range != nullptr) {
        if (right_range->IsMonotonicValueRange()) {
          if (left_range != nullptr && left_range->IsMonotonicValueRange()) {
            HandleIfBetweenTwoMonotonicValueRanges(instruction, left, right, cond,
                                                   left_range->AsMonotonicValueRange(),
                                                   right_range->AsMonotonicValueRange());
            return;
          }
        }
        lower = right_range->GetLower();
        upper = right_range->GetUpper();
      } else {
        lower = ValueBound::Min();
        upper = ValueBound::Max();
      }
    }

    bool overflow, underflow;
    if (cond == kCondLT || cond == kCondLE) {
      if (!upper.Equals(ValueBound::Max())) {
        int32_t compensation = (cond == kCondLT) ? -1 : 0;  // upper bound is inclusive
        ValueBound new_upper = upper.Add(compensation, &overflow, &underflow);
        if (overflow || underflow) {
          return;
        }
        ValueRange* new_range = new (&allocator_) ValueRange(
            &allocator_, ValueBound::Min(), new_upper);
        ApplyRangeFromComparison(left, block, true_successor, new_range);
      }

      // array.length as a lower bound isn't considered useful.
      if (!lower.Equals(ValueBound::Min()) && !lower.IsRelatedToArrayLength()) {
        int32_t compensation = (cond == kCondLE) ? 1 : 0;  // lower bound is inclusive
        ValueBound new_lower = lower.Add(compensation, &overflow, &underflow);
        if (overflow || underflow) {
          return;
        }
        ValueRange* new_range = new (&allocator_) ValueRange(
            &allocator_, new_lower, ValueBound::Max());
        ApplyRangeFromComparison(left, block, false_successor, new_range);
      }
    } else if (cond == kCondGT || cond == kCondGE) {
      // array.length as a lower bound isn't considered useful.
      if (!lower.Equals(ValueBound::Min()) && !lower.IsRelatedToArrayLength()) {
        int32_t compensation = (cond == kCondGT) ? 1 : 0;  // lower bound is inclusive
        ValueBound new_lower = lower.Add(compensation, &overflow, &underflow);
        if (overflow || underflow) {
          return;
        }
        ValueRange* new_range = new (&allocator_) ValueRange(
            &allocator_, new_lower, ValueBound::Max());
        ApplyRangeFromComparison(left, block, true_successor, new_range);
      }

      if (!upper.Equals(ValueBound::Max())) {
        int32_t compensation = (cond == kCondGE) ? -1 : 0;  // upper bound is inclusive
        ValueBound new_upper = upper.Add(compensation, &overflow, &underflow);
        if (overflow || underflow) {
          return;
        }
        ValueRange* new_range = new (&allocator_) ValueRange(
            &allocator_, ValueBound::Min(), new_upper);
        ApplyRangeFromComparison(left, block, false_successor, new_range);
      }
    } else if (cond == kCondNE || cond == kCondEQ) {
      if (left->IsArrayLength()) {
        if (lower.IsConstant() && upper.IsConstant()) {
          // Special case:
          //   length == [c,d] yields [c, d] along true
          //   length != [c,d] yields [c, d] along false
          if (!lower.Equals(ValueBound::Min()) || !upper.Equals(ValueBound::Max())) {
            ValueRange* new_range = new (&allocator_) ValueRange(&allocator_, lower, upper);
            ApplyRangeFromComparison(
                left, block, cond == kCondEQ ? true_successor : false_successor, new_range);
          }
          // In addition:
          //   length == 0 yields [1, max] along false
          //   length != 0 yields [1, max] along true
          if (lower.GetConstant() == 0 && upper.GetConstant() == 0) {
            ValueRange* new_range = new (&allocator_) ValueRange(
                &allocator_, ValueBound(nullptr, 1), ValueBound::Max());
            ApplyRangeFromComparison(
                left, block, cond == kCondEQ ? false_successor : true_successor, new_range);
          }
        }
      } else if (lower.IsRelatedToArrayLength() && lower.Equals(upper)) {
        // Special aliasing case, with x not array length itself:
        //   x == [length,length] yields x == length along true
        //   x != [length,length] yields x == length along false
        ValueRange* new_range = new (&allocator_) ValueRange(&allocator_, lower, upper);
        ApplyRangeFromComparison(
            left, block, cond == kCondEQ ? true_successor : false_successor, new_range);
      }
    }
  }

  void VisitBoundsCheck(HBoundsCheck* bounds_check) override {
    HBasicBlock* block = bounds_check->GetBlock();
    HInstruction* index = bounds_check->InputAt(0);
    HInstruction* array_length = bounds_check->InputAt(1);
    DCHECK(array_length->IsIntConstant() ||
           array_length->IsArrayLength() ||
           array_length->IsPhi());
    bool try_dynamic_bce = true;
    // Analyze index range.
    if (!index->IsIntConstant()) {
      // Non-constant index.
      ValueBound lower = ValueBound(nullptr, 0);        // constant 0
      ValueBound upper = ValueBound(array_length, -1);  // array_length - 1
      ValueRange array_range(&allocator_, lower, upper);
      // Try index range obtained by dominator-based analysis.
      ValueRange* index_range = LookupValueRange(index, block);
      if (index_range != nullptr) {
        if (index_range->FitsIn(&array_range)) {
          ReplaceInstruction(bounds_check, index);
          return;
        } else if (index_range->IsConstantValueRange()) {
          // If the non-constant index turns out to have a constant range,
          // make one more attempt to get a constant in the array range.
          ValueRange* existing_range = LookupValueRange(array_length, block);
          if (existing_range != nullptr &&
              existing_range->IsConstantValueRange() &&
              existing_range->GetLower().GetConstant() > 0) {
            ValueBound constant_upper(nullptr, existing_range->GetLower().GetConstant() - 1);
            ValueRange constant_array_range(&allocator_, lower, constant_upper);
            if (index_range->FitsIn(&constant_array_range)) {
              ReplaceInstruction(bounds_check, index);
              return;
            }
          }
        }
      }
      // Try index range obtained by induction variable analysis.
      // Disables dynamic bce if OOB is certain.
      if (InductionRangeFitsIn(&array_range, bounds_check, &try_dynamic_bce)) {
        ReplaceInstruction(bounds_check, index);
        return;
      }
    } else {
      // Constant index.
      int32_t constant = index->AsIntConstant()->GetValue();
      if (constant < 0) {
        // Will always throw exception.
        return;
      } else if (array_length->IsIntConstant()) {
        if (constant < array_length->AsIntConstant()->GetValue()) {
          ReplaceInstruction(bounds_check, index);
        }
        return;
      }
      // Analyze array length range.
      DCHECK(array_length->IsArrayLength());
      ValueRange* existing_range = LookupValueRange(array_length, block);
      if (existing_range != nullptr) {
        ValueBound lower = existing_range->GetLower();
        DCHECK(lower.IsConstant());
        if (constant < lower.GetConstant()) {
          ReplaceInstruction(bounds_check, index);
          return;
        } else {
          // Existing range isn't strong enough to eliminate the bounds check.
          // Fall through to update the array_length range with info from this
          // bounds check.
        }
      }
      // Once we have an array access like 'array[5] = 1', we record array.length >= 6.
      // We currently don't do it for non-constant index since a valid array[i] can't prove
      // a valid array[i-1] yet due to the lower bound side.
      if (constant == std::numeric_limits<int32_t>::max()) {
        // Max() as an index will definitely throw AIOOBE.
        return;
      } else {
        ValueBound lower = ValueBound(nullptr, constant + 1);
        ValueBound upper = ValueBound::Max();
        ValueRange* range = new (&allocator_) ValueRange(&allocator_, lower, upper);
        AssignRange(block, array_length, range);
      }
    }

    // If static analysis fails, and OOB is not certain, try dynamic elimination.
    if (try_dynamic_bce) {
      // Try loop-based dynamic elimination.
      HLoopInformation* loop = bounds_check->GetBlock()->GetLoopInformation();
      bool needs_finite_test = false;
      bool needs_taken_test = false;
      if (DynamicBCESeemsProfitable(loop, bounds_check->GetBlock()) &&
          induction_range_.CanGenerateRange(
              bounds_check->GetBlock(), index, &needs_finite_test, &needs_taken_test) &&
          CanHandleInfiniteLoop(loop, index, needs_finite_test) &&
          // Do this test last, since it may generate code.
          CanHandleLength(loop, array_length, needs_taken_test)) {
        TransformLoopForDeoptimizationIfNeeded(loop, needs_taken_test);
        TransformLoopForDynamicBCE(loop, bounds_check);
        return;
      }
      // Otherwise, prepare dominator-based dynamic elimination.
      if (first_index_bounds_check_map_.find(array_length->GetId()) ==
          first_index_bounds_check_map_.end()) {
        // Remember the first bounds check against each array_length. That bounds check
        // instruction has an associated HEnvironment where we may add an HDeoptimize
        // to eliminate subsequent bounds checks against the same array_length.
        first_index_bounds_check_map_.Put(array_length->GetId(), bounds_check);
      }
    }
  }

  static bool HasSameInputAtBackEdges(HPhi* phi) {
    DCHECK(phi->IsLoopHeaderPhi());
    HConstInputsRef inputs = phi->GetInputs();
    // Start with input 1. Input 0 is from the incoming block.
    const HInstruction* input1 = inputs[1];
    DCHECK(phi->GetBlock()->GetLoopInformation()->IsBackEdge(
        *phi->GetBlock()->GetPredecessors()[1]));
    for (size_t i = 2; i < inputs.size(); ++i) {
      DCHECK(phi->GetBlock()->GetLoopInformation()->IsBackEdge(
          *phi->GetBlock()->GetPredecessors()[i]));
      if (input1 != inputs[i]) {
        return false;
      }
    }
    return true;
  }

  void VisitPhi(HPhi* phi) override {
    if (phi->IsLoopHeaderPhi()
        && (phi->GetType() == DataType::Type::kInt32)
        && HasSameInputAtBackEdges(phi)) {
      HInstruction* instruction = phi->InputAt(1);
      HInstruction *left;
      int32_t increment;
      if (ValueBound::IsAddOrSubAConstant(instruction, &left, &increment)) {
        if (left == phi) {
          HInstruction* initial_value = phi->InputAt(0);
          ValueRange* range = nullptr;
          if (increment == 0) {
            // Add constant 0. It's really a fixed value.
            range = new (&allocator_) ValueRange(
                &allocator_,
                ValueBound(initial_value, 0),
                ValueBound(initial_value, 0));
          } else {
            // Monotonically increasing/decreasing.
            bool found;
            ValueBound bound = ValueBound::DetectValueBoundFromValue(
                initial_value, &found);
            if (!found) {
              // No constant or array.length+c bound found.
              // For i=j, we can still use j's upper bound as i's upper bound.
              // Same for lower.
              ValueRange* initial_range = LookupValueRange(initial_value, phi->GetBlock());
              if (initial_range != nullptr) {
                bound = increment > 0 ? initial_range->GetLower() :
                                        initial_range->GetUpper();
              } else {
                bound = increment > 0 ? ValueBound::Min() : ValueBound::Max();
              }
            }
            range = new (&allocator_) MonotonicValueRange(
                &allocator_,
                phi,
                initial_value,
                increment,
                bound);
          }
          AssignRange(phi->GetBlock(), phi, range);
        }
      }
    }
  }

  void VisitIf(HIf* instruction) override {
    if (instruction->InputAt(0)->IsCondition()) {
      HCondition* cond = instruction->InputAt(0)->AsCondition();
      HandleIf(instruction, cond->GetLeft(), cond->GetRight(), cond->GetCondition());
    }
  }

  // Check whether HSub is a result of the HRem optimization of:
  //   q = Div(dividend, const_divisor)
  //   r = Rem(dividend, const_divisor)
  // into
  //   q = Div(dividend, const_divisor)
  //   t = Mul(q, const_divisor)
  //   r = Sub(dividend, t)
  // or for divisors 2^n + 1 into
  //   q  = Div(dividend, const_divisor)
  //   t1 = Shl(q, n)
  //   t2 = Add(q, t1)
  //   r  = Sub(dividend, t2)
  // or for divisors 2^n - 1 into
  //   q  = Div(dividend, const_divisor)
  //   t1 = Shl(q, n)
  //   t2 = Sub(t1, q)
  //   r  = Sub(dividend, t2)
  //
  // If it is the case, the value range for the instruction is
  // [1 - abs(const_divisor), abs(const_divisor) - 1] merged with
  // the range of the left input is assigned and true is returned. Otherwise,
  // no range is assigned and false is returned.
  bool TryToAssignRangeIfOptimizedRemWithConstantDivisor(HSub* instruction) {
    if (instruction->GetResultType() != DataType::Type::kInt32) {
      return false;
    }

    auto is_needed_shl = [](HShl* shl) {
      return shl != nullptr && shl->GetRight()->IsConstant() && shl->GetLeft()->IsDiv();
    };

    HDiv* div = nullptr;
    int64_t const_divisor = 0;
    if (HMul* mul = instruction->GetRight()->AsMulOrNull()) {
      if (!mul->GetLeft()->IsDiv() || !mul->GetRight()->IsConstant()) {
        return false;
      }
      div = mul->GetLeft()->AsDiv();
      const_divisor = Int64FromConstant(mul->GetRight()->AsConstant());
    } else if (HAdd* add = instruction->GetRight()->AsAddOrNull()) {
      HShl* shl = add->GetRight()->AsShlOrNull();
      if (!is_needed_shl(shl)) {
        return false;
      }

      div = shl->GetLeft()->AsDiv();
      if (add->GetLeft() != div) {
        return false;
      }

      int32_t n = shl->GetRight()->AsIntConstant()->GetValue();
      if (n == BitSizeOf<int32_t>() - 1) {
        // 2^n + 1 will be negative.
        return false;
      }
      const_divisor = (1LL << n) + 1;
    } else if (HSub* sub = instruction->GetRight()->AsSubOrNull()) {
      HShl* shl = sub->GetLeft()->AsShlOrNull();
      if (!is_needed_shl(shl)) {
        return false;
      }

      div = shl->GetLeft()->AsDiv();
      if (sub->GetRight() != div) {
        return false;
      }

      int32_t n = shl->GetRight()->AsIntConstant()->GetValue();
      const_divisor = (1LL << n) - 1;
    }

    if (div == nullptr || !IsInt64Value(div->GetRight(), const_divisor) ||
        div->GetLeft() != instruction->GetLeft()) {
      return false;
    }

    ValueRange* range = nullptr;
    if (const_divisor == DataType::MinValueOfIntegralType(DataType::Type::kInt32)) {
      range = new (&allocator_) ValueRange(&allocator_,
          ValueBound(nullptr, DataType::MinValueOfIntegralType(DataType::Type::kInt32) + 1),
          ValueBound(nullptr, DataType::MaxValueOfIntegralType(DataType::Type::kInt32)));
    } else {
      DCHECK_GT(const_divisor, DataType::MinValueOfIntegralType(DataType::Type::kInt32));
      DCHECK_LE(const_divisor, DataType::MaxValueOfIntegralType(DataType::Type::kInt32));
      int32_t abs_const_divisor = static_cast<int32_t>(std::abs(const_divisor));
      range = new (&allocator_) ValueRange(&allocator_,
                                           ValueBound(nullptr, 1 - abs_const_divisor),
                                           ValueBound(nullptr, abs_const_divisor - 1));
    }
    HBasicBlock* basic_block = instruction->GetBlock();
    if (ValueRange* left_range = LookupValueRange(instruction->GetLeft(), basic_block)) {
      range = range->Narrow(left_range);
    }
    AssignRange(basic_block, instruction, range);
    return true;
  }

  void VisitAdd(HAdd* add) override {
    HInstruction* right = add->GetRight();
    if (right->IsIntConstant()) {
      ValueRange* left_range = LookupValueRange(add->GetLeft(), add->GetBlock());
      if (left_range == nullptr) {
        return;
      }
      ValueRange* range = left_range->Add(right->AsIntConstant()->GetValue());
      if (range != nullptr) {
        AssignRange(add->GetBlock(), add, range);
      }
    }
  }

  void VisitSub(HSub* sub) override {
    if (TryToAssignRangeIfOptimizedRemWithConstantDivisor(sub)) {
      return;
    }

    HInstruction* left = sub->GetLeft();
    HInstruction* right = sub->GetRight();
    if (right->IsIntConstant()) {
      ValueRange* left_range = LookupValueRange(left, sub->GetBlock());
      if (left_range == nullptr) {
        return;
      }
      ValueRange* range = left_range->Add(-right->AsIntConstant()->GetValue());
      if (range != nullptr) {
        AssignRange(sub->GetBlock(), sub, range);
        return;
      }
    }

    // Here we are interested in the typical triangular case of nested loops,
    // such as the inner loop 'for (int j=0; j<array.length-i; j++)' where i
    // is the index for outer loop. In this case, we know j is bounded by array.length-1.

    // Try to handle (array.length - i) or (array.length + c - i) format.
    HInstruction* left_of_left;  // left input of left.
    int32_t right_const = 0;
    if (ValueBound::IsAddOrSubAConstant(left, &left_of_left, &right_const)) {
      left = left_of_left;
    }
    // The value of left input of the sub equals (left + right_const).

    if (left->IsArrayLength()) {
      HInstruction* array_length = left->AsArrayLength();
      ValueRange* right_range = LookupValueRange(right, sub->GetBlock());
      if (right_range != nullptr) {
        ValueBound lower = right_range->GetLower();
        ValueBound upper = right_range->GetUpper();
        if (lower.IsConstant() && upper.IsRelatedToArrayLength()) {
          HInstruction* upper_inst = upper.GetInstruction();
          // Make sure it's the same array.
          if (ValueBound::Equal(array_length, upper_inst)) {
            int32_t c0 = right_const;
            int32_t c1 = lower.GetConstant();
            int32_t c2 = upper.GetConstant();
            // (array.length + c0 - v) where v is in [c1, array.length + c2]
            // gets [c0 - c2, array.length + c0 - c1] as its value range.
            if (!ValueBound::WouldAddOverflowOrUnderflow(c0, -c2) &&
                !ValueBound::WouldAddOverflowOrUnderflow(c0, -c1)) {
              if ((c0 - c1) <= 0) {
                // array.length + (c0 - c1) won't overflow/underflow.
                ValueRange* range = new (&allocator_) ValueRange(
                    &allocator_,
                    ValueBound(nullptr, right_const - upper.GetConstant()),
                    ValueBound(array_length, right_const - lower.GetConstant()));
                AssignRange(sub->GetBlock(), sub, range);
              }
            }
          }
        }
      }
    }
  }

  void FindAndHandlePartialArrayLength(HBinaryOperation* instruction) {
    DCHECK(instruction->IsDiv() || instruction->IsShr() || instruction->IsUShr());
    HInstruction* right = instruction->GetRight();
    int32_t right_const;
    if (right->IsIntConstant()) {
      right_const = right->AsIntConstant()->GetValue();
      // Detect division by two or more.
      if ((instruction->IsDiv() && right_const <= 1) ||
          (instruction->IsShr() && right_const < 1) ||
          (instruction->IsUShr() && right_const < 1)) {
        return;
      }
    } else {
      return;
    }

    // Try to handle array.length/2 or (array.length-1)/2 format.
    HInstruction* left = instruction->GetLeft();
    HInstruction* left_of_left;  // left input of left.
    int32_t c = 0;
    if (ValueBound::IsAddOrSubAConstant(left, &left_of_left, &c)) {
      left = left_of_left;
    }
    // The value of left input of instruction equals (left + c).

    // (array_length + 1) or smaller divided by two or more
    // always generate a value in [Min(), array_length].
    // This is true even if array_length is Max().
    if (left->IsArrayLength() && c <= 1) {
      if (instruction->IsUShr() && c < 0) {
        // Make sure for unsigned shift, left side is not negative.
        // e.g. if array_length is 2, ((array_length - 3) >>> 2) is way bigger
        // than array_length.
        return;
      }
      ValueRange* range = new (&allocator_) ValueRange(
          &allocator_,
          ValueBound(nullptr, std::numeric_limits<int32_t>::min()),
          ValueBound(left, 0));
      AssignRange(instruction->GetBlock(), instruction, range);
    }
  }

  void VisitDiv(HDiv* div) override {
    FindAndHandlePartialArrayLength(div);
  }

  void VisitShr(HShr* shr) override {
    FindAndHandlePartialArrayLength(shr);
  }

  void VisitUShr(HUShr* ushr) override {
    FindAndHandlePartialArrayLength(ushr);
  }

  void VisitAnd(HAnd* instruction) override {
    if (instruction->GetRight()->IsIntConstant()) {
      int32_t constant = instruction->GetRight()->AsIntConstant()->GetValue();
      if (constant > 0) {
        // constant serves as a mask so any number masked with it
        // gets a [0, constant] value range.
        ValueRange* range = new (&allocator_) ValueRange(
            &allocator_,
            ValueBound(nullptr, 0),
            ValueBound(nullptr, constant));
        AssignRange(instruction->GetBlock(), instruction, range);
      }
    }
  }

  void VisitRem(HRem* instruction) override {
    HInstruction* left = instruction->GetLeft();
    HInstruction* right = instruction->GetRight();

    // Handle 'i % CONST' format expression in array index, e.g:
    //   array[i % 20];
    if (right->IsIntConstant()) {
      int32_t right_const = std::abs(right->AsIntConstant()->GetValue());
      if (right_const == 0) {
        return;
      }
      // The sign of divisor CONST doesn't affect the sign final value range.
      // For example:
      // if (i > 0) {
      //   array[i % 10];  // index value range [0, 9]
      //   array[i % -10]; // index value range [0, 9]
      // }
      ValueRange* right_range = new (&allocator_) ValueRange(
          &allocator_,
          ValueBound(nullptr, 1 - right_const),
          ValueBound(nullptr, right_const - 1));

      ValueRange* left_range = LookupValueRange(left, instruction->GetBlock());
      if (left_range != nullptr) {
        right_range = right_range->Narrow(left_range);
      }
      AssignRange(instruction->GetBlock(), instruction, right_range);
      return;
    }

    // Handle following pattern:
    // i0 NullCheck
    // i1 ArrayLength[i0]
    // i2 DivByZeroCheck [i1]  <-- right
    // i3 Rem [i5, i2]         <-- we are here.
    // i4 BoundsCheck [i3,i1]
    if (right->IsDivZeroCheck()) {
      // if array_length can pass div-by-zero check,
      // array_length must be > 0.
      right = right->AsDivZeroCheck()->InputAt(0);
    }

    // Handle 'i % array.length' format expression in array index, e.g:
    //   array[(i+7) % array.length];
    if (right->IsArrayLength()) {
      ValueBound lower = ValueBound::Min();  // ideally, lower should be '1-array_length'.
      ValueBound upper = ValueBound(right, -1);  // array_length - 1
      ValueRange* right_range = new (&allocator_) ValueRange(
          &allocator_,
          lower,
          upper);
      ValueRange* left_range = LookupValueRange(left, instruction->GetBlock());
      if (left_range != nullptr) {
        right_range = right_range->Narrow(left_range);
      }
      AssignRange(instruction->GetBlock(), instruction, right_range);
      return;
    }
  }

  void VisitNewArray(HNewArray* new_array) override {
    HInstruction* len = new_array->GetLength();
    if (!len->IsIntConstant()) {
      HInstruction *left;
      int32_t right_const;
      if (ValueBound::IsAddOrSubAConstant(len, &left, &right_const)) {
        // (left + right_const) is used as size to new the array.
        // We record "-right_const <= left <= new_array - right_const";
        ValueBound lower = ValueBound(nullptr, -right_const);
        // We use new_array for the bound instead of new_array.length,
        // which isn't available as an instruction yet. new_array will
        // be treated the same as new_array.length when it's used in a ValueBound.
        ValueBound upper = ValueBound(new_array, -right_const);
        ValueRange* range = new (&allocator_) ValueRange(&allocator_, lower, upper);
        ValueRange* existing_range = LookupValueRange(left, new_array->GetBlock());
        if (existing_range != nullptr) {
          range = existing_range->Narrow(range);
        }
        AssignRange(new_array->GetBlock(), left, range);
      }
    }
  }

  /**
    * After null/bounds checks are eliminated, some invariant array references
    * may be exposed underneath which can be hoisted out of the loop to the
    * preheader or, in combination with dynamic bce, the deoptimization block.
    *
    * for (int i = 0; i < n; i++) {
    *                                <-------+
    *   for (int j = 0; j < n; j++)          |
    *     a[i][j] = 0;               --a[i]--+
    * }
    *
    * Note: this optimization is no longer applied after dominator-based dynamic deoptimization
    * has occurred (see AddCompareWithDeoptimization()), since in those cases it would be
    * unsafe to hoist array references across their deoptimization instruction inside a loop.
    */
  void VisitArrayGet(HArrayGet* array_get) override {
    if (!has_dom_based_dynamic_bce_ && array_get->IsInLoop()) {
      HLoopInformation* loop = array_get->GetBlock()->GetLoopInformation();
      if (loop->IsDefinedOutOfTheLoop(array_get->InputAt(0)) &&
          loop->IsDefinedOutOfTheLoop(array_get->InputAt(1))) {
        SideEffects loop_effects = side_effects_.GetLoopEffects(loop->GetHeader());
        if (!array_get->GetSideEffects().MayDependOn(loop_effects)) {
          // We can hoist ArrayGet only if its execution is guaranteed on every iteration.
          // In other words only if array_get_bb dominates all back branches.
          if (loop->DominatesAllBackEdges(array_get->GetBlock())) {
            HoistToPreHeaderOrDeoptBlock(loop, array_get);
          }
        }
      }
    }
  }

  /** Performs dominator-based dynamic elimination on suitable set of bounds checks. */
  void AddCompareWithDeoptimization(HBasicBlock* block,
                                    HInstruction* array_length,
                                    HInstruction* base,
                                    int32_t min_c, int32_t max_c) {
    HBoundsCheck* bounds_check = first_index_bounds_check_map_.Get(array_length->GetId());
    // Construct deoptimization on single or double bounds on range [base-min_c,base+max_c],
    // for example either for a[0]..a[3] just 3 or for a[base-1]..a[base+3] both base-1
    // and base+3, since we made the assumption any in between value may occur too.
    // In code, using unsigned comparisons:
    // (1) constants only
    //       if (max_c >= a.length) deoptimize;
    // (2) general case
    //       if (base-min_c >  base+max_c) deoptimize;
    //       if (base+max_c >= a.length  ) deoptimize;
    static_assert(kMaxLengthForAddingDeoptimize < std::numeric_limits<int32_t>::max(),
                  "Incorrect max length may be subject to arithmetic wrap-around");
    HInstruction* upper = GetGraph()->GetIntConstant(max_c);
    if (base == nullptr) {
      DCHECK_GE(min_c, 0);
    } else {
      HInstruction* lower = new (GetGraph()->GetAllocator())
          HAdd(DataType::Type::kInt32, base, GetGraph()->GetIntConstant(min_c));
      upper = new (GetGraph()->GetAllocator()) HAdd(DataType::Type::kInt32, base, upper);
      block->InsertInstructionBefore(lower, bounds_check);
      block->InsertInstructionBefore(upper, bounds_check);
      InsertDeoptInBlock(bounds_check, new (GetGraph()->GetAllocator()) HAbove(lower, upper));
    }
    InsertDeoptInBlock(
        bounds_check, new (GetGraph()->GetAllocator()) HAboveOrEqual(upper, array_length));
    // Flag that this kind of deoptimization has occurred.
    has_dom_based_dynamic_bce_ = true;
  }

  /** Attempts dominator-based dynamic elimination on remaining candidates. */
  void AddComparesWithDeoptimization(HBasicBlock* block) {
    for (const auto& entry : first_index_bounds_check_map_) {
      HBoundsCheck* bounds_check = entry.second;
      HInstruction* index = bounds_check->InputAt(0);
      HInstruction* array_length = bounds_check->InputAt(1);
      if (!array_length->IsArrayLength()) {
        continue;  // disregard phis and constants
      }
      // Collect all bounds checks that are still there and that are related as "a[base + constant]"
      // for a base instruction (possibly absent) and various constants. Note that no attempt
      // is made to partition the set into matching subsets (viz. a[0], a[1] and a[base+1] and
      // a[base+2] are considered as one set).
      // TODO: would such a partitioning be worthwhile?
      ValueBound value = ValueBound::AsValueBound(index);
      HInstruction* base = value.GetInstruction();
      int32_t min_c = base == nullptr ? 0 : value.GetConstant();
      int32_t max_c = value.GetConstant();
      ScopedArenaVector<HBoundsCheck*> candidates(
          allocator_.Adapter(kArenaAllocBoundsCheckElimination));
      ScopedArenaVector<HBoundsCheck*> standby(
          allocator_.Adapter(kArenaAllocBoundsCheckElimination));
      for (const HUseListNode<HInstruction*>& use : array_length->GetUses()) {
        // Another bounds check in same or dominated block?
        HInstruction* user = use.GetUser();
        HBasicBlock* other_block = user->GetBlock();
        if (user->IsBoundsCheck() && block->Dominates(other_block)) {
          HBoundsCheck* other_bounds_check = user->AsBoundsCheck();
          HInstruction* other_index = other_bounds_check->InputAt(0);
          HInstruction* other_array_length = other_bounds_check->InputAt(1);
          ValueBound other_value = ValueBound::AsValueBound(other_index);
          if (array_length == other_array_length && base == other_value.GetInstruction()) {
            // Reject certain OOB if BoundsCheck(l, l) occurs on considered subset.
            if (array_length == other_index) {
              candidates.clear();
              standby.clear();
              break;
            }
            // Since a subsequent dominated block could be under a conditional, only accept
            // the other bounds check if it is in same block or both blocks dominate the exit.
            // TODO: we could improve this by testing proper post-dominance, or even if this
            //       constant is seen along *all* conditional paths that follow.
            HBasicBlock* exit = GetGraph()->GetExitBlock();
            if (block == user->GetBlock() ||
                (block->Dominates(exit) && other_block->Dominates(exit))) {
              int32_t other_c = other_value.GetConstant();
              min_c = std::min(min_c, other_c);
              max_c = std::max(max_c, other_c);
              candidates.push_back(other_bounds_check);
            } else {
              // Add this candidate later only if it falls into the range.
              standby.push_back(other_bounds_check);
            }
          }
        }
      }
      // Add standby candidates that fall in selected range.
      for (HBoundsCheck* other_bounds_check : standby) {
        HInstruction* other_index = other_bounds_check->InputAt(0);
        int32_t other_c = ValueBound::AsValueBound(other_index).GetConstant();
        if (min_c <= other_c && other_c <= max_c) {
          candidates.push_back(other_bounds_check);
        }
      }
      // Perform dominator-based deoptimization if it seems profitable, where we eliminate
      // bounds checks and replace these with deopt checks that guard against any possible
      // OOB. Note that we reject cases where the distance min_c:max_c range gets close to
      // the maximum possible array length, since those cases are likely to always deopt
      // (such situations do not necessarily go OOB, though, since the array could be really
      // large, or the programmer could rely on arithmetic wrap-around from max to min).
      size_t threshold = kThresholdForAddingDeoptimize + (base == nullptr ? 0 : 1);  // extra test?
      uint32_t distance = static_cast<uint32_t>(max_c) - static_cast<uint32_t>(min_c);
      if (candidates.size() >= threshold &&
          (base != nullptr || min_c >= 0) &&  // reject certain OOB
           distance <= kMaxLengthForAddingDeoptimize) {  // reject likely/certain deopt
        AddCompareWithDeoptimization(block, array_length, base, min_c, max_c);
        for (HBoundsCheck* other_bounds_check : candidates) {
          // Only replace if still in the graph. This avoids visiting the same
          // bounds check twice if it occurred multiple times in the use list.
          if (other_bounds_check->IsInBlock()) {
            ReplaceInstruction(other_bounds_check, other_bounds_check->InputAt(0));
          }
        }
      }
    }
  }

  /**
   * Returns true if static range analysis based on induction variables can determine the bounds
   * check on the given array range is always satisfied with the computed index range. The output
   * parameter try_dynamic_bce is set to false if OOB is certain.
   */
  bool InductionRangeFitsIn(ValueRange* array_range,
                            HBoundsCheck* context,
                            bool* try_dynamic_bce) {
    InductionVarRange::Value v1;
    InductionVarRange::Value v2;
    bool needs_finite_test = false;
    HInstruction* index = context->InputAt(0);
    HInstruction* hint = HuntForDeclaration(context->InputAt(1));
    if (induction_range_.GetInductionRange(
            context->GetBlock(), index, hint, &v1, &v2, &needs_finite_test)) {
      if (v1.is_known && (v1.a_constant == 0 || v1.a_constant == 1) &&
          v2.is_known && (v2.a_constant == 0 || v2.a_constant == 1)) {
        DCHECK(v1.a_constant == 1 || v1.instruction == nullptr);
        DCHECK(v2.a_constant == 1 || v2.instruction == nullptr);
        ValueRange index_range(&allocator_,
                               ValueBound(v1.instruction, v1.b_constant),
                               ValueBound(v2.instruction, v2.b_constant));
        // If analysis reveals a certain OOB, disable dynamic BCE. Otherwise,
        // use analysis for static bce only if loop is finite.
        if (index_range.GetLower().LessThan(array_range->GetLower()) ||
            index_range.GetUpper().GreaterThan(array_range->GetUpper())) {
          *try_dynamic_bce = false;
        } else if (!needs_finite_test && index_range.FitsIn(array_range)) {
          return true;
        }
      }
    }
    return false;
  }

  /**
   * Performs loop-based dynamic elimination on a bounds check. In order to minimize the
   * number of eventually generated tests, related bounds checks with tests that can be
   * combined with tests for the given bounds check are collected first.
   */
  void TransformLoopForDynamicBCE(HLoopInformation* loop, HBoundsCheck* bounds_check) {
    HInstruction* index = bounds_check->InputAt(0);
    HInstruction* array_length = bounds_check->InputAt(1);
    DCHECK(loop->IsDefinedOutOfTheLoop(array_length));  // pre-checked
    DCHECK(loop->DominatesAllBackEdges(bounds_check->GetBlock()));
    // Collect all bounds checks in the same loop that are related as "a[base + constant]"
    // for a base instruction (possibly absent) and various constants.
    ValueBound value = ValueBound::AsValueBound(index);
    HInstruction* base = value.GetInstruction();
    int32_t min_c = base == nullptr ? 0 : value.GetConstant();
    int32_t max_c = value.GetConstant();
    ScopedArenaVector<HBoundsCheck*> candidates(
        allocator_.Adapter(kArenaAllocBoundsCheckElimination));
    ScopedArenaVector<HBoundsCheck*> standby(
        allocator_.Adapter(kArenaAllocBoundsCheckElimination));
    for (const HUseListNode<HInstruction*>& use : array_length->GetUses()) {
      HInstruction* user = use.GetUser();
      if (user->IsBoundsCheck() && loop == user->GetBlock()->GetLoopInformation()) {
        HBoundsCheck* other_bounds_check = user->AsBoundsCheck();
        HInstruction* other_index = other_bounds_check->InputAt(0);
        HInstruction* other_array_length = other_bounds_check->InputAt(1);
        ValueBound other_value = ValueBound::AsValueBound(other_index);
        int32_t other_c = other_value.GetConstant();
        if (array_length == other_array_length && base == other_value.GetInstruction()) {
          // Ensure every candidate could be picked for code generation.
          bool b1 = false, b2 = false;
          if (!induction_range_.CanGenerateRange(
                  other_bounds_check->GetBlock(), other_index, &b1, &b2)) {
            continue;
          }
          // Does the current basic block dominate all back edges? If not,
          // add this candidate later only if it falls into the range.
          if (!loop->DominatesAllBackEdges(user->GetBlock())) {
            standby.push_back(other_bounds_check);
            continue;
          }
          min_c = std::min(min_c, other_c);
          max_c = std::max(max_c, other_c);
          candidates.push_back(other_bounds_check);
        }
      }
    }
    // Add standby candidates that fall in selected range.
    for (HBoundsCheck* other_bounds_check : standby) {
      HInstruction* other_index = other_bounds_check->InputAt(0);
      int32_t other_c = ValueBound::AsValueBound(other_index).GetConstant();
      if (min_c <= other_c && other_c <= max_c) {
        candidates.push_back(other_bounds_check);
      }
    }
    // Perform loop-based deoptimization if it seems profitable, where we eliminate bounds
    // checks and replace these with deopt checks that guard against any possible OOB.
    DCHECK_LT(0u, candidates.size());
    uint32_t distance = static_cast<uint32_t>(max_c) - static_cast<uint32_t>(min_c);
    if ((base != nullptr || min_c >= 0) &&  // reject certain OOB
        distance <= kMaxLengthForAddingDeoptimize) {  // reject likely/certain deopt
      HBasicBlock* block = GetPreHeader(loop, bounds_check);
      HInstruction* min_lower = nullptr;
      HInstruction* min_upper = nullptr;
      HInstruction* max_lower = nullptr;
      HInstruction* max_upper = nullptr;
      // Iterate over all bounds checks.
      for (HBoundsCheck* other_bounds_check : candidates) {
        // Only handle if still in the graph. This avoids visiting the same
        // bounds check twice if it occurred multiple times in the use list.
        if (other_bounds_check->IsInBlock()) {
          HInstruction* other_index = other_bounds_check->InputAt(0);
          int32_t other_c = ValueBound::AsValueBound(other_index).GetConstant();
          // Generate code for either the maximum or minimum. Range analysis already was queried
          // whether code generation on the original and, thus, related bounds check was possible.
          // It handles either loop invariants (lower is not set) or unit strides.
          if (other_c == max_c) {
            induction_range_.GenerateRange(other_bounds_check->GetBlock(),
                                           other_index,
                                           GetGraph(),
                                           block,
                                           &max_lower,
                                           &max_upper);
          } else if (other_c == min_c && base != nullptr) {
            induction_range_.GenerateRange(other_bounds_check->GetBlock(),
                                           other_index,
                                           GetGraph(),
                                           block,
                                           &min_lower,
                                           &min_upper);
          }
          ReplaceInstruction(other_bounds_check, other_index);
        }
      }
      // In code, using unsigned comparisons:
      // (1) constants only
      //       if (max_upper >= a.length ) deoptimize;
      // (2) two symbolic invariants
      //       if (min_upper >  max_upper) deoptimize;   unless min_c == max_c
      //       if (max_upper >= a.length ) deoptimize;
      // (3) general case, unit strides (where lower would exceed upper for arithmetic wrap-around)
      //       if (min_lower >  max_lower) deoptimize;   unless min_c == max_c
      //       if (max_lower >  max_upper) deoptimize;
      //       if (max_upper >= a.length ) deoptimize;
      if (base == nullptr) {
        // Constants only.
        DCHECK_GE(min_c, 0);
        DCHECK(min_lower == nullptr && min_upper == nullptr &&
               max_lower == nullptr && max_upper != nullptr);
      } else if (max_lower == nullptr) {
        // Two symbolic invariants.
        if (min_c != max_c) {
          DCHECK(min_lower == nullptr && min_upper != nullptr &&
                 max_lower == nullptr && max_upper != nullptr);
          InsertDeoptInLoop(
              loop, block, new (GetGraph()->GetAllocator()) HAbove(min_upper, max_upper));
        } else {
          DCHECK(min_lower == nullptr && min_upper == nullptr &&
                 max_lower == nullptr && max_upper != nullptr);
        }
      } else {
        // General case, unit strides.
        if (min_c != max_c) {
          DCHECK(min_lower != nullptr && min_upper != nullptr &&
                 max_lower != nullptr && max_upper != nullptr);
          InsertDeoptInLoop(
              loop, block, new (GetGraph()->GetAllocator()) HAbove(min_lower, max_lower));
        } else {
          DCHECK(min_lower == nullptr && min_upper == nullptr &&
                 max_lower != nullptr && max_upper != nullptr);
        }
        InsertDeoptInLoop(
            loop, block, new (GetGraph()->GetAllocator()) HAbove(max_lower, max_upper));
      }
      InsertDeoptInLoop(
          loop, block, new (GetGraph()->GetAllocator()) HAboveOrEqual(max_upper, array_length));
    } else {
      // TODO: if rejected, avoid doing this again for subsequent instructions in this set?
    }
  }

  /**
   * Returns true if heuristics indicate that dynamic bce may be profitable.
   */
  bool DynamicBCESeemsProfitable(HLoopInformation* loop, HBasicBlock* block) {
    if (loop != nullptr) {
      // The loop preheader of an irreducible loop does not dominate all the blocks in
      // the loop. We would need to find the common dominator of all blocks in the loop.
      if (loop->IsIrreducible()) {
        return false;
      }
      // We should never deoptimize from an osr method, otherwise we might wrongly optimize
      // code dominated by the deoptimization.
      if (GetGraph()->IsCompilingOsr()) {
        return false;
      }
      // A try boundary preheader is hard to handle.
      // TODO: remove this restriction.
      if (loop->GetPreHeader()->GetLastInstruction()->IsTryBoundary()) {
        return false;
      }
      // Does loop have early-exits? If so, the full range may not be covered by the loop
      // at runtime and testing the range may apply deoptimization unnecessarily.
      if (IsEarlyExitLoop(loop)) {
        return false;
      }
      // Does the current basic block dominate all back edges? If not,
      // don't apply dynamic bce to something that may not be executed.
      return loop->DominatesAllBackEdges(block);
    }
    return false;
  }

  /**
   * Returns true if the loop has early exits, which implies it may not cover
   * the full range computed by range analysis based on induction variables.
   */
  bool IsEarlyExitLoop(HLoopInformation* loop) {
    const uint32_t loop_id = loop->GetHeader()->GetBlockId();
    // If loop has been analyzed earlier for early-exit, don't repeat the analysis.
    auto it = early_exit_loop_.find(loop_id);
    if (it != early_exit_loop_.end()) {
      return it->second;
    }
    // First time early-exit analysis for this loop. Since analysis requires scanning
    // the full loop-body, results of the analysis is stored for subsequent queries.
    HBlocksInLoopReversePostOrderIterator it_loop(*loop);
    for (it_loop.Advance(); !it_loop.Done(); it_loop.Advance()) {
      for (HBasicBlock* successor : it_loop.Current()->GetSuccessors()) {
        if (!loop->Contains(*successor)) {
          early_exit_loop_.Put(loop_id, true);
          return true;
        }
      }
    }
    early_exit_loop_.Put(loop_id, false);
    return false;
  }

  /**
   * Returns true if the array length is already loop invariant, or can be made so
   * by handling the null check under the hood of the array length operation.
   */
  bool CanHandleLength(HLoopInformation* loop, HInstruction* length, bool needs_taken_test) {
    if (loop->IsDefinedOutOfTheLoop(length)) {
      return true;
    } else if (length->IsArrayLength() && length->GetBlock()->GetLoopInformation() == loop) {
      if (CanHandleNullCheck(loop, length->InputAt(0), needs_taken_test)) {
        HoistToPreHeaderOrDeoptBlock(loop, length);
        return true;
      }
    }
    return false;
  }

  /**
   * Returns true if the null check is already loop invariant, or can be made so
   * by generating a deoptimization test.
   */
  bool CanHandleNullCheck(HLoopInformation* loop, HInstruction* check, bool needs_taken_test) {
    if (loop->IsDefinedOutOfTheLoop(check)) {
      return true;
    } else if (check->IsNullCheck() && check->GetBlock()->GetLoopInformation() == loop) {
      HInstruction* array = check->InputAt(0);
      if (loop->IsDefinedOutOfTheLoop(array)) {
        // Generate: if (array == null) deoptimize;
        TransformLoopForDeoptimizationIfNeeded(loop, needs_taken_test);
        HBasicBlock* block = GetPreHeader(loop, check);
        HInstruction* cond =
            new (GetGraph()->GetAllocator()) HEqual(array, GetGraph()->GetNullConstant());
        InsertDeoptInLoop(loop, block, cond, /* is_null_check= */ true);
        ReplaceInstruction(check, array);
        return true;
      }
    }
    return false;
  }

  /**
   * Returns true if compiler can apply dynamic bce to loops that may be infinite
   * (e.g. for (int i = 0; i <= U; i++) with U = MAX_INT), which would invalidate
   * the range analysis evaluation code by "overshooting" the computed range.
   * Since deoptimization would be a bad choice, and there is no other version
   * of the loop to use, dynamic bce in such cases is only allowed if other tests
   * ensure the loop is finite.
   */
  bool CanHandleInfiniteLoop(HLoopInformation* loop, HInstruction* index, bool needs_infinite_test) {
    if (needs_infinite_test) {
      // If we already forced the loop to be finite, allow directly.
      const uint32_t loop_id = loop->GetHeader()->GetBlockId();
      if (finite_loop_.find(loop_id) != finite_loop_.end()) {
        return true;
      }
      // Otherwise, allow dynamic bce if the index (which is necessarily an induction at
      // this point) is the direct loop index (viz. a[i]), since then the runtime tests
      // ensure upper bound cannot cause an infinite loop.
      HInstruction* control = loop->GetHeader()->GetLastInstruction();
      if (control->IsIf()) {
        HInstruction* if_expr = control->AsIf()->InputAt(0);
        if (if_expr->IsCondition()) {
          HCondition* condition = if_expr->AsCondition();
          if (index == condition->InputAt(0) ||
              index == condition->InputAt(1)) {
            finite_loop_.insert(loop_id);
            return true;
          }
        }
      }
      return false;
    }
    return true;
  }

  /**
   * Returns appropriate preheader for the loop, depending on whether the
   * instruction appears in the loop header or proper loop-body.
   */
  HBasicBlock* GetPreHeader(HLoopInformation* loop, HInstruction* instruction) {
    // Use preheader unless there is an earlier generated deoptimization block since
    // hoisted expressions may depend on and/or used by the deoptimization tests.
    HBasicBlock* header = loop->GetHeader();
    const uint32_t loop_id = header->GetBlockId();
    auto it = taken_test_loop_.find(loop_id);
    if (it != taken_test_loop_.end()) {
      HBasicBlock* block = it->second;
      // If always taken, keep it that way by returning the original preheader,
      // which can be found by following the predecessor of the true-block twice.
      if (instruction->GetBlock() == header) {
        return block->GetSinglePredecessor()->GetSinglePredecessor();
      }
      return block;
    }
    return loop->GetPreHeader();
  }

  /** Inserts a deoptimization test in a loop preheader. */
  void InsertDeoptInLoop(HLoopInformation* loop,
                         HBasicBlock* block,
                         HInstruction* condition,
                         bool is_null_check = false) {
    HInstruction* suspend = loop->GetSuspendCheck();
    DCHECK(suspend != nullptr);
    block->InsertInstructionBefore(condition, block->GetLastInstruction());
    DeoptimizationKind kind =
        is_null_check ? DeoptimizationKind::kLoopNullBCE : DeoptimizationKind::kLoopBoundsBCE;
    HDeoptimize* deoptimize = new (GetGraph()->GetAllocator()) HDeoptimize(
        GetGraph()->GetAllocator(), condition, kind, suspend->GetDexPc());
    block->InsertInstructionBefore(deoptimize, block->GetLastInstruction());
    if (suspend->HasEnvironment()) {
      deoptimize->CopyEnvironmentFromWithLoopPhiAdjustment(
          suspend->GetEnvironment(), loop->GetHeader());
    }
  }

  /** Inserts a deoptimization test right before a bounds check. */
  void InsertDeoptInBlock(HBoundsCheck* bounds_check, HInstruction* condition) {
    HBasicBlock* block = bounds_check->GetBlock();
    block->InsertInstructionBefore(condition, bounds_check);
    HDeoptimize* deoptimize = new (GetGraph()->GetAllocator()) HDeoptimize(
        GetGraph()->GetAllocator(),
        condition,
        DeoptimizationKind::kBlockBCE,
        bounds_check->GetDexPc());
    block->InsertInstructionBefore(deoptimize, bounds_check);
    deoptimize->CopyEnvironmentFrom(bounds_check->GetEnvironment());
  }

  /** Hoists instruction out of the loop to preheader or deoptimization block. */
  void HoistToPreHeaderOrDeoptBlock(HLoopInformation* loop, HInstruction* instruction) {
    HBasicBlock* block = GetPreHeader(loop, instruction);
    DCHECK(!instruction->HasEnvironment());
    instruction->MoveBefore(block->GetLastInstruction());
  }

  /**
   * Adds a new taken-test structure to a loop if needed and not already done.
   * The taken-test protects range analysis evaluation code to avoid any
   * deoptimization caused by incorrect trip-count evaluation in non-taken loops.
   *
   *          old_preheader
   *               |
   *            if_block          <- taken-test protects deoptimization block
   *            /      \
   *     true_block  false_block  <- deoptimizations/invariants are placed in true_block
   *            \       /
   *          new_preheader       <- may require phi nodes to preserve SSA structure
   *                |
   *             header
   *
   * For example, this loop:
   *
   *   for (int i = lower; i < upper; i++) {
   *     array[i] = 0;
   *   }
   *
   * will be transformed to:
   *
   *   if (lower < upper) {
   *     if (array == null) deoptimize;
   *     array_length = array.length;
   *     if (lower > upper)         deoptimize;  // unsigned
   *     if (upper >= array_length) deoptimize;  // unsigned
   *   } else {
   *     array_length = 0;
   *   }
   *   for (int i = lower; i < upper; i++) {
   *     // Loop without null check and bounds check, and any array.length replaced with array_length.
   *     array[i] = 0;
   *   }
   */
  void TransformLoopForDeoptimizationIfNeeded(HLoopInformation* loop, bool needs_taken_test) {
    // Not needed (can use preheader) or already done (can reuse)?
    const uint32_t loop_id = loop->GetHeader()->GetBlockId();
    if (!needs_taken_test || taken_test_loop_.find(loop_id) != taken_test_loop_.end()) {
      return;
    }

    // Generate top test structure.
    HBasicBlock* header = loop->GetHeader();
    GetGraph()->TransformLoopHeaderForBCE(header);
    HBasicBlock* new_preheader = loop->GetPreHeader();
    HBasicBlock* if_block = new_preheader->GetDominator();
    HBasicBlock* true_block = if_block->GetSuccessors()[0];  // True successor.
    HBasicBlock* false_block = if_block->GetSuccessors()[1];  // False successor.

    // Goto instructions.
    true_block->AddInstruction(new (GetGraph()->GetAllocator()) HGoto());
    false_block->AddInstruction(new (GetGraph()->GetAllocator()) HGoto());
    new_preheader->AddInstruction(new (GetGraph()->GetAllocator()) HGoto());

    // Insert the taken-test to see if the loop body is entered. If the
    // loop isn't entered at all, it jumps around the deoptimization block.
    if_block->AddInstruction(new (GetGraph()->GetAllocator()) HGoto());  // placeholder
    HInstruction* condition = induction_range_.GenerateTakenTest(
        header->GetLastInstruction(), GetGraph(), if_block);
    DCHECK(condition != nullptr);
    if_block->RemoveInstruction(if_block->GetLastInstruction());
    if_block->AddInstruction(new (GetGraph()->GetAllocator()) HIf(condition));

    taken_test_loop_.Put(loop_id, true_block);
  }

  /**
   * Inserts phi nodes that preserve SSA structure in generated top test structures.
   * All uses of instructions in the deoptimization block that reach the loop need
   * a phi node in the new loop preheader to fix the dominance relation.
   *
   * Example:
   *           if_block
   *            /      \
   *         x_0 = ..  false_block
   *            \       /
   *           x_1 = phi(x_0, null)   <- synthetic phi
   *               |
   *          new_preheader
   */
  void InsertPhiNodes() {
    // Scan all new deoptimization blocks.
    for (const auto& entry : taken_test_loop_) {
      HBasicBlock* true_block = entry.second;
      HBasicBlock* new_preheader = true_block->GetSingleSuccessor();
      // Scan all instructions in a new deoptimization block.
      for (HInstructionIterator it(true_block->GetInstructions()); !it.Done(); it.Advance()) {
        HInstruction* instruction = it.Current();
        DataType::Type type = instruction->GetType();
        HPhi* phi = nullptr;
        // Scan all uses of an instruction and replace each later use with a phi node.
        const HUseList<HInstruction*>& uses = instruction->GetUses();
        for (auto it2 = uses.begin(), end2 = uses.end(); it2 != end2; /* ++it2 below */) {
          HInstruction* user = it2->GetUser();
          size_t index = it2->GetIndex();
          // Increment `it2` now because `*it2` may disappear thanks to user->ReplaceInput().
          ++it2;
          if (user->GetBlock() != true_block) {
            if (phi == nullptr) {
              phi = NewPhi(new_preheader, instruction, type);
            }
            user->ReplaceInput(phi, index);  // Removes the use node from the list.
            induction_range_.Replace(user, instruction, phi);  // update induction
          }
        }
        // Scan all environment uses of an instruction and replace each later use with a phi node.
        const HUseList<HEnvironment*>& env_uses = instruction->GetEnvUses();
        for (auto it2 = env_uses.begin(), end2 = env_uses.end(); it2 != end2; /* ++it2 below */) {
          HEnvironment* user = it2->GetUser();
          size_t index = it2->GetIndex();
          // Increment `it2` now because `*it2` may disappear thanks to user->RemoveAsUserOfInput().
          ++it2;
          if (user->GetHolder()->GetBlock() != true_block) {
            if (phi == nullptr) {
              phi = NewPhi(new_preheader, instruction, type);
            }
            user->RemoveAsUserOfInput(index);
            user->SetRawEnvAt(index, phi);
            phi->AddEnvUseAt(user, index);
          }
        }
      }
    }
  }

  /**
   * Construct a phi(instruction, 0) in the new preheader to fix the dominance relation.
   * These are synthetic phi nodes without a virtual register.
   */
  HPhi* NewPhi(HBasicBlock* new_preheader,
               HInstruction* instruction,
               DataType::Type type) {
    HGraph* graph = GetGraph();
    HInstruction* zero;
    switch (type) {
      case DataType::Type::kReference: zero = graph->GetNullConstant(); break;
      case DataType::Type::kFloat32: zero = graph->GetFloatConstant(0); break;
      case DataType::Type::kFloat64: zero = graph->GetDoubleConstant(0); break;
      default: zero = graph->GetConstant(type, 0); break;
    }
    HPhi* phi = new (graph->GetAllocator())
        HPhi(graph->GetAllocator(), kNoRegNumber, /*number_of_inputs*/ 2, HPhi::ToPhiType(type));
    phi->SetRawInputAt(0, instruction);
    phi->SetRawInputAt(1, zero);
    if (type == DataType::Type::kReference) {
      phi->SetReferenceTypeInfoIfValid(instruction->GetReferenceTypeInfo());
    }
    new_preheader->AddPhi(phi);
    return phi;
  }

  /** Helper method to replace an instruction with another instruction. */
  void ReplaceInstruction(HInstruction* instruction, HInstruction* replacement) {
    // Safe iteration.
    if (instruction == next_) {
      next_ = next_->GetNext();
    }
    // Replace and remove.
    instruction->ReplaceWith(replacement);
    instruction->GetBlock()->RemoveInstruction(instruction);
  }

  // Use local allocator for allocating memory.
  ScopedArenaAllocator allocator_;

  // A set of maps, one per basic block, from instruction to range.
  ScopedArenaVector<ScopedArenaSafeMap<int, ValueRange*>> maps_;

  // Map an HArrayLength instruction's id to the first HBoundsCheck instruction
  // in a block that checks an index against that HArrayLength.
  ScopedArenaSafeMap<int, HBoundsCheck*> first_index_bounds_check_map_;

  // Early-exit loop bookkeeping.
  ScopedArenaSafeMap<uint32_t, bool> early_exit_loop_;

  // Taken-test loop bookkeeping.
  ScopedArenaSafeMap<uint32_t, HBasicBlock*> taken_test_loop_;

  // Finite loop bookkeeping.
  ScopedArenaSet<uint32_t> finite_loop_;

  // Flag that denotes whether dominator-based dynamic elimination has occurred.
  bool has_dom_based_dynamic_bce_;

  // Initial number of blocks.
  uint32_t initial_block_size_;

  // Side effects.
  const SideEffectsAnalysis& side_effects_;

  // Range analysis based on induction variables.
  InductionVarRange induction_range_;

  // Safe iteration.
  HInstruction* next_;

  DISALLOW_COPY_AND_ASSIGN(BCEVisitor);
};

bool BoundsCheckElimination::Run() {
  if (!graph_->HasBoundsChecks()) {
    return false;
  }

  // Reverse post order guarantees a node's dominators are visited first.
  // We want to visit in the dominator-based order since if a value is known to
  // be bounded by a range at one instruction, it must be true that all uses of
  // that value dominated by that instruction fits in that range. Range of that
  // value can be narrowed further down in the dominator tree.
  BCEVisitor visitor(graph_, side_effects_, induction_analysis_);
  for (size_t i = 0, size = graph_->GetReversePostOrder().size(); i != size; ++i) {
    HBasicBlock* current = graph_->GetReversePostOrder()[i];
    if (visitor.IsAddedBlock(current)) {
      // Skip added blocks. Their effects are already taken care of.
      continue;
    }
    visitor.VisitBasicBlock(current);
    // Skip forward to the current block in case new basic blocks were inserted
    // (which always appear earlier in reverse post order) to avoid visiting the
    // same basic block twice.
    size_t new_size = graph_->GetReversePostOrder().size();
    DCHECK_GE(new_size, size);
    i += new_size - size;
    DCHECK_EQ(current, graph_->GetReversePostOrder()[i]);
    size = new_size;
  }

  // Perform cleanup.
  visitor.Finish();

  return true;
}

}  // namespace art
