/*
 * Copyright (C) 2012 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 "local_value_numbering.h"

#include "base/bit_utils.h"
#include "global_value_numbering.h"
#include "mir_field_info.h"
#include "mir_graph.h"
#include "utils.h"

namespace art {

namespace {  // anonymous namespace

// Operations used for value map keys instead of actual opcode.
static constexpr uint16_t kInvokeMemoryVersionBumpOp = Instruction::INVOKE_VIRTUAL;
static constexpr uint16_t kUnresolvedSFieldOp = Instruction::SGET;
static constexpr uint16_t kResolvedSFieldOp = Instruction::SGET_WIDE;
static constexpr uint16_t kUnresolvedIFieldOp = Instruction::IGET;
static constexpr uint16_t kNonAliasingIFieldLocOp = Instruction::IGET_WIDE;
static constexpr uint16_t kNonAliasingIFieldInitialOp = Instruction::IGET_OBJECT;
static constexpr uint16_t kAliasingIFieldOp = Instruction::IGET_BOOLEAN;
static constexpr uint16_t kAliasingIFieldStartVersionOp = Instruction::IGET_BYTE;
static constexpr uint16_t kAliasingIFieldBumpVersionOp = Instruction::IGET_CHAR;
static constexpr uint16_t kNonAliasingArrayOp = Instruction::AGET;
static constexpr uint16_t kNonAliasingArrayStartVersionOp = Instruction::AGET_WIDE;
static constexpr uint16_t kNonAliasingArrayBumpVersionOp = Instruction::AGET_OBJECT;
static constexpr uint16_t kAliasingArrayOp = Instruction::AGET_BOOLEAN;
static constexpr uint16_t kAliasingArrayStartVersionOp = Instruction::AGET_BYTE;
static constexpr uint16_t kAliasingArrayBumpVersionOp = Instruction::AGET_CHAR;
static constexpr uint16_t kMergeBlockMemoryVersionBumpOp = Instruction::INVOKE_VIRTUAL_RANGE;
static constexpr uint16_t kMergeBlockAliasingIFieldVersionBumpOp = Instruction::IPUT;
static constexpr uint16_t kMergeBlockAliasingIFieldMergeLocationOp = Instruction::IPUT_WIDE;
static constexpr uint16_t kMergeBlockNonAliasingArrayVersionBumpOp = Instruction::APUT;
static constexpr uint16_t kMergeBlockNonAliasingArrayMergeLocationOp = Instruction::APUT_WIDE;
static constexpr uint16_t kMergeBlockAliasingArrayVersionBumpOp = Instruction::APUT_OBJECT;
static constexpr uint16_t kMergeBlockAliasingArrayMergeLocationOp = Instruction::APUT_BOOLEAN;
static constexpr uint16_t kMergeBlockNonAliasingIFieldVersionBumpOp = Instruction::APUT_BYTE;
static constexpr uint16_t kMergeBlockSFieldVersionBumpOp = Instruction::APUT_CHAR;

}  // anonymous namespace

class LocalValueNumbering::AliasingIFieldVersions {
 public:
  static uint16_t StartMemoryVersion(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
                                     uint16_t field_id) {
    uint16_t type = gvn->GetIFieldType(field_id);
    return gvn->LookupValue(kAliasingIFieldStartVersionOp, field_id,
                            lvn->global_memory_version_, lvn->unresolved_ifield_version_[type]);
  }

  static uint16_t BumpMemoryVersion(GlobalValueNumbering* gvn, uint16_t old_version,
                                    uint16_t store_ref_set_id, uint16_t stored_value) {
    return gvn->LookupValue(kAliasingIFieldBumpVersionOp, old_version,
                            store_ref_set_id, stored_value);
  }

  static uint16_t LookupGlobalValue(GlobalValueNumbering* gvn,
                                    uint16_t field_id, uint16_t base, uint16_t memory_version) {
    return gvn->LookupValue(kAliasingIFieldOp, field_id, base, memory_version);
  }

  static uint16_t LookupMergeValue(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
                                   uint16_t field_id, uint16_t base) {
    // If the base/field_id is non-aliasing in lvn, use the non-aliasing value.
    uint16_t type = gvn->GetIFieldType(field_id);
    if (lvn->IsNonAliasingIField(base, field_id, type)) {
      uint16_t loc = gvn->LookupValue(kNonAliasingIFieldLocOp, base, field_id, type);
      auto lb = lvn->non_aliasing_ifield_value_map_.find(loc);
      return (lb != lvn->non_aliasing_ifield_value_map_.end())
          ? lb->second
          : gvn->LookupValue(kNonAliasingIFieldInitialOp, loc, kNoValue, kNoValue);
    }
    return AliasingValuesMergeGet<AliasingIFieldVersions>(
        gvn, lvn, &lvn->aliasing_ifield_value_map_, field_id, base);
  }

  static bool HasNewBaseVersion(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
                                uint16_t field_id) {
    uint16_t type = gvn->GetIFieldType(field_id);
    return lvn->unresolved_ifield_version_[type] == lvn->merge_new_memory_version_ ||
        lvn->global_memory_version_ == lvn->merge_new_memory_version_;
  }

  static uint16_t LookupMergeBlockValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
                                        uint16_t field_id) {
    return gvn->LookupValue(kMergeBlockAliasingIFieldVersionBumpOp, field_id, kNoValue, lvn_id);
  }

  static uint16_t LookupMergeLocationValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
                                           uint16_t field_id, uint16_t base) {
    return gvn->LookupValue(kMergeBlockAliasingIFieldMergeLocationOp, field_id, base, lvn_id);
  }
};

class LocalValueNumbering::NonAliasingArrayVersions {
 public:
  static uint16_t StartMemoryVersion(GlobalValueNumbering* gvn,
                                     const LocalValueNumbering* lvn ATTRIBUTE_UNUSED,
                                     uint16_t array) {
    return gvn->LookupValue(kNonAliasingArrayStartVersionOp, array, kNoValue, kNoValue);
  }

  static uint16_t BumpMemoryVersion(GlobalValueNumbering* gvn, uint16_t old_version,
                                    uint16_t store_ref_set_id, uint16_t stored_value) {
    return gvn->LookupValue(kNonAliasingArrayBumpVersionOp, old_version,
                            store_ref_set_id, stored_value);
  }

  static uint16_t LookupGlobalValue(GlobalValueNumbering* gvn,
                                    uint16_t array, uint16_t index, uint16_t memory_version) {
    return gvn->LookupValue(kNonAliasingArrayOp, array, index, memory_version);
  }

  static uint16_t LookupMergeValue(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
                                   uint16_t array, uint16_t index) {
    return AliasingValuesMergeGet<NonAliasingArrayVersions>(
        gvn, lvn, &lvn->non_aliasing_array_value_map_, array, index);
  }

  static bool HasNewBaseVersion(GlobalValueNumbering* gvn ATTRIBUTE_UNUSED,
                                const LocalValueNumbering* lvn ATTRIBUTE_UNUSED,
                                uint16_t array ATTRIBUTE_UNUSED) {
    return false;  // Not affected by global_memory_version_.
  }

  static uint16_t LookupMergeBlockValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
                                        uint16_t array) {
    return gvn->LookupValue(kMergeBlockNonAliasingArrayVersionBumpOp, array, kNoValue, lvn_id);
  }

  static uint16_t LookupMergeLocationValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
                                           uint16_t array, uint16_t index) {
    return gvn->LookupValue(kMergeBlockNonAliasingArrayMergeLocationOp, array, index, lvn_id);
  }
};

class LocalValueNumbering::AliasingArrayVersions {
 public:
  static uint16_t StartMemoryVersion(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
                                     uint16_t type) {
    return gvn->LookupValue(kAliasingArrayStartVersionOp, type, lvn->global_memory_version_,
                            kNoValue);
  }

  static uint16_t BumpMemoryVersion(GlobalValueNumbering* gvn, uint16_t old_version,
                                    uint16_t store_ref_set_id, uint16_t stored_value) {
    return gvn->LookupValue(kAliasingArrayBumpVersionOp, old_version,
                            store_ref_set_id, stored_value);
  }

  static uint16_t LookupGlobalValue(GlobalValueNumbering* gvn,
                                    uint16_t type, uint16_t location, uint16_t memory_version) {
    return gvn->LookupValue(kAliasingArrayOp, type, location, memory_version);
  }

  static uint16_t LookupMergeValue(GlobalValueNumbering* gvn,
                                   const LocalValueNumbering* lvn,
                                   uint16_t type, uint16_t location) {
    // If the location is non-aliasing in lvn, use the non-aliasing value.
    uint16_t array = gvn->GetArrayLocationBase(location);
    if (lvn->IsNonAliasingArray(array, type)) {
      uint16_t index = gvn->GetArrayLocationIndex(location);
      return NonAliasingArrayVersions::LookupMergeValue(gvn, lvn, array, index);
    }
    return AliasingValuesMergeGet<AliasingArrayVersions>(
        gvn, lvn, &lvn->aliasing_array_value_map_, type, location);
  }

  static bool HasNewBaseVersion(GlobalValueNumbering* gvn ATTRIBUTE_UNUSED,
                                const LocalValueNumbering* lvn,
                                uint16_t type ATTRIBUTE_UNUSED) {
    return lvn->global_memory_version_ == lvn->merge_new_memory_version_;
  }

  static uint16_t LookupMergeBlockValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
                                        uint16_t type) {
    return gvn->LookupValue(kMergeBlockAliasingArrayVersionBumpOp, type, kNoValue, lvn_id);
  }

  static uint16_t LookupMergeLocationValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
                                           uint16_t type, uint16_t location) {
    return gvn->LookupValue(kMergeBlockAliasingArrayMergeLocationOp, type, location, lvn_id);
  }
};

template <typename Map>
LocalValueNumbering::AliasingValues* LocalValueNumbering::GetAliasingValues(
    Map* map, const typename Map::key_type& key) {
  auto lb = map->lower_bound(key);
  if (lb == map->end() || map->key_comp()(key, lb->first)) {
    lb = map->PutBefore(lb, key, AliasingValues(this));
  }
  return &lb->second;
}

template <typename Versions, typename KeyType>
void LocalValueNumbering::UpdateAliasingValuesLoadVersion(const KeyType& key,
                                                          AliasingValues* values) {
  if (values->last_load_memory_version == kNoValue) {
    // Get the start version that accounts for aliasing with unresolved fields of the same
    // type and make it unique for the field by including the field_id.
    uint16_t memory_version = values->memory_version_before_stores;
    if (memory_version == kNoValue) {
      memory_version = Versions::StartMemoryVersion(gvn_, this, key);
    }
    if (!values->store_loc_set.empty()) {
      uint16_t ref_set_id = gvn_->GetRefSetId(values->store_loc_set);
      memory_version = Versions::BumpMemoryVersion(gvn_, memory_version, ref_set_id,
                                                   values->last_stored_value);
    }
    values->last_load_memory_version = memory_version;
  }
}

template <typename Versions, typename Map>
uint16_t LocalValueNumbering::AliasingValuesMergeGet(GlobalValueNumbering* gvn,
                                                     const LocalValueNumbering* lvn,
                                                     Map* map, const typename Map::key_type& key,
                                                     uint16_t location) {
  // Retrieve the value name that we would get from
  //   const_cast<LocalValueNumbering*>(lvn)->HandleAliasingValueGet(map. key, location)
  // but don't modify the map.
  uint16_t value_name;
  auto it = map->find(key);
  if (it == map->end()) {
    uint16_t start_version = Versions::StartMemoryVersion(gvn, lvn, key);
    value_name = Versions::LookupGlobalValue(gvn, key, location, start_version);
  } else if (it->second.store_loc_set.count(location) != 0u) {
    value_name = it->second.last_stored_value;
  } else {
    auto load_it = it->second.load_value_map.find(location);
    if (load_it != it->second.load_value_map.end()) {
      value_name = load_it->second;
    } else {
      value_name = Versions::LookupGlobalValue(gvn, key, location, it->second.last_load_memory_version);
    }
  }
  return value_name;
}

template <typename Versions, typename Map>
uint16_t LocalValueNumbering::HandleAliasingValuesGet(Map* map, const typename Map::key_type& key,
                                                      uint16_t location) {
  // Retrieve the value name for IGET/SGET/AGET, update the map with new value if any.
  uint16_t res;
  AliasingValues* values = GetAliasingValues(map, key);
  if (values->store_loc_set.count(location) != 0u) {
    res = values->last_stored_value;
  } else {
    UpdateAliasingValuesLoadVersion<Versions>(key, values);
    auto lb = values->load_value_map.lower_bound(location);
    if (lb != values->load_value_map.end() && lb->first == location) {
      res = lb->second;
    } else {
      res = Versions::LookupGlobalValue(gvn_, key, location, values->last_load_memory_version);
      values->load_value_map.PutBefore(lb, location, res);
    }
  }
  return res;
}

template <typename Versions, typename Map>
bool LocalValueNumbering::HandleAliasingValuesPut(Map* map, const typename Map::key_type& key,
                                                  uint16_t location, uint16_t value) {
  AliasingValues* values = GetAliasingValues(map, key);
  auto load_values_it = values->load_value_map.find(location);
  if (load_values_it != values->load_value_map.end() && load_values_it->second == value) {
    // This insn can be eliminated, it stores the same value that's already in the field.
    return false;
  }
  if (value == values->last_stored_value) {
    auto store_loc_lb = values->store_loc_set.lower_bound(location);
    if (store_loc_lb != values->store_loc_set.end() && *store_loc_lb == location) {
      // This insn can be eliminated, it stores the same value that's already in the field.
      return false;
    }
    values->store_loc_set.emplace_hint(store_loc_lb, location);
  } else {
    UpdateAliasingValuesLoadVersion<Versions>(key, values);
    values->memory_version_before_stores = values->last_load_memory_version;
    values->last_stored_value = value;
    values->store_loc_set.clear();
    values->store_loc_set.insert(location);
  }
  // Clear the last load memory version and remove all potentially overwritten values.
  values->last_load_memory_version = kNoValue;
  auto it = values->load_value_map.begin(), end = values->load_value_map.end();
  while (it != end) {
    if (it->second == value) {
      ++it;
    } else {
      it = values->load_value_map.erase(it);
    }
  }
  return true;
}

template <typename K>
void LocalValueNumbering::CopyAliasingValuesMap(ScopedArenaSafeMap<K, AliasingValues>* dest,
                                                const ScopedArenaSafeMap<K, AliasingValues>& src) {
  // We need each new AliasingValues (or rather its map members) to be constructed
  // with our allocator, rather than the allocator of the source.
  for (const auto& entry : src) {
    auto it = dest->PutBefore(dest->end(), entry.first, AliasingValues(this));
    it->second = entry.second;  // Map assignments preserve current allocator.
  }
}

LocalValueNumbering::LocalValueNumbering(GlobalValueNumbering* gvn, uint16_t id,
                                         ScopedArenaAllocator* allocator)
    : gvn_(gvn),
      id_(id),
      sreg_value_map_(std::less<uint16_t>(), allocator->Adapter()),
      sreg_wide_value_map_(std::less<uint16_t>(), allocator->Adapter()),
      sfield_value_map_(std::less<uint16_t>(), allocator->Adapter()),
      non_aliasing_ifield_value_map_(std::less<uint16_t>(), allocator->Adapter()),
      aliasing_ifield_value_map_(std::less<uint16_t>(), allocator->Adapter()),
      non_aliasing_array_value_map_(std::less<uint16_t>(), allocator->Adapter()),
      aliasing_array_value_map_(std::less<uint16_t>(), allocator->Adapter()),
      global_memory_version_(0u),
      non_aliasing_refs_(std::less<uint16_t>(), allocator->Adapter()),
      escaped_refs_(std::less<uint16_t>(), allocator->Adapter()),
      escaped_ifield_clobber_set_(EscapedIFieldClobberKeyComparator(), allocator->Adapter()),
      escaped_array_clobber_set_(EscapedArrayClobberKeyComparator(), allocator->Adapter()),
      range_checked_(RangeCheckKeyComparator() , allocator->Adapter()),
      null_checked_(std::less<uint16_t>(), allocator->Adapter()),
      div_zero_checked_(std::less<uint16_t>(), allocator->Adapter()),
      merge_names_(allocator->Adapter()),
      merge_map_(std::less<ScopedArenaVector<BasicBlockId>>(), allocator->Adapter()),
      merge_new_memory_version_(kNoValue) {
  std::fill_n(unresolved_sfield_version_, arraysize(unresolved_sfield_version_), 0u);
  std::fill_n(unresolved_ifield_version_, arraysize(unresolved_ifield_version_), 0u);
}

bool LocalValueNumbering::Equals(const LocalValueNumbering& other) const {
  DCHECK(gvn_ == other.gvn_);
  // Compare the maps/sets and memory versions.
  return sreg_value_map_ == other.sreg_value_map_ &&
      sreg_wide_value_map_ == other.sreg_wide_value_map_ &&
      sfield_value_map_ == other.sfield_value_map_ &&
      non_aliasing_ifield_value_map_ == other.non_aliasing_ifield_value_map_ &&
      aliasing_ifield_value_map_ == other.aliasing_ifield_value_map_ &&
      non_aliasing_array_value_map_ == other.non_aliasing_array_value_map_ &&
      aliasing_array_value_map_ == other.aliasing_array_value_map_ &&
      SameMemoryVersion(other) &&
      non_aliasing_refs_ == other.non_aliasing_refs_ &&
      escaped_refs_ == other.escaped_refs_ &&
      escaped_ifield_clobber_set_ == other.escaped_ifield_clobber_set_ &&
      escaped_array_clobber_set_ == other.escaped_array_clobber_set_ &&
      range_checked_ == other.range_checked_ &&
      null_checked_ == other.null_checked_ &&
      div_zero_checked_ == other.div_zero_checked_;
}

void LocalValueNumbering::MergeOne(const LocalValueNumbering& other, MergeType merge_type) {
  CopyLiveSregValues(&sreg_value_map_, other.sreg_value_map_);
  CopyLiveSregValues(&sreg_wide_value_map_, other.sreg_wide_value_map_);

  if (merge_type == kReturnMerge) {
    // RETURN or PHI+RETURN. We need only sreg value maps.
    return;
  }

  non_aliasing_ifield_value_map_ = other.non_aliasing_ifield_value_map_;
  CopyAliasingValuesMap(&non_aliasing_array_value_map_, other.non_aliasing_array_value_map_);
  non_aliasing_refs_ = other.non_aliasing_refs_;
  range_checked_ = other.range_checked_;
  null_checked_ = other.null_checked_;
  div_zero_checked_ = other.div_zero_checked_;

  const BasicBlock* pred_bb = gvn_->GetBasicBlock(other.Id());
  if (GlobalValueNumbering::HasNullCheckLastInsn(pred_bb, Id())) {
    int s_reg = pred_bb->last_mir_insn->ssa_rep->uses[0];
    null_checked_.insert(other.GetOperandValue(s_reg));
  }

  if (merge_type == kCatchMerge) {
    // Memory is clobbered. Use new memory version and don't merge aliasing locations.
    global_memory_version_ = NewMemoryVersion(&merge_new_memory_version_);
    std::fill_n(unresolved_sfield_version_, arraysize(unresolved_sfield_version_),
                global_memory_version_);
    std::fill_n(unresolved_ifield_version_, arraysize(unresolved_ifield_version_),
                global_memory_version_);
    PruneNonAliasingRefsForCatch();
    return;
  }

  DCHECK(merge_type == kNormalMerge);
  global_memory_version_ = other.global_memory_version_;
  std::copy_n(other.unresolved_ifield_version_, arraysize(unresolved_sfield_version_),
              unresolved_ifield_version_);
  std::copy_n(other.unresolved_sfield_version_, arraysize(unresolved_ifield_version_),
              unresolved_sfield_version_);
  sfield_value_map_ = other.sfield_value_map_;
  CopyAliasingValuesMap(&aliasing_ifield_value_map_, other.aliasing_ifield_value_map_);
  CopyAliasingValuesMap(&aliasing_array_value_map_, other.aliasing_array_value_map_);
  escaped_refs_ = other.escaped_refs_;
  escaped_ifield_clobber_set_ = other.escaped_ifield_clobber_set_;
  escaped_array_clobber_set_ = other.escaped_array_clobber_set_;
}

bool LocalValueNumbering::SameMemoryVersion(const LocalValueNumbering& other) const {
  return
      global_memory_version_ == other.global_memory_version_ &&
      std::equal(unresolved_ifield_version_,
                 unresolved_ifield_version_ + arraysize(unresolved_ifield_version_),
                 other.unresolved_ifield_version_) &&
      std::equal(unresolved_sfield_version_,
                 unresolved_sfield_version_ + arraysize(unresolved_sfield_version_),
                 other.unresolved_sfield_version_);
}

uint16_t LocalValueNumbering::NewMemoryVersion(uint16_t* new_version) {
  if (*new_version == kNoValue) {
    *new_version = gvn_->LookupValue(kMergeBlockMemoryVersionBumpOp, 0u, 0u, id_);
  }
  return *new_version;
}

void LocalValueNumbering::MergeMemoryVersions(bool clobbered_catch) {
  DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
  const LocalValueNumbering* cmp = gvn_->merge_lvns_[0];
  // Check if the global version has changed.
  bool new_global_version = clobbered_catch;
  if (!new_global_version) {
    for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
      if (lvn->global_memory_version_ != cmp->global_memory_version_) {
        // Use a new version for everything.
        new_global_version = true;
        break;
      }
    }
  }
  if (new_global_version) {
    global_memory_version_ = NewMemoryVersion(&merge_new_memory_version_);
    std::fill_n(unresolved_sfield_version_, arraysize(unresolved_sfield_version_),
                merge_new_memory_version_);
    std::fill_n(unresolved_ifield_version_, arraysize(unresolved_ifield_version_),
                merge_new_memory_version_);
  } else {
    // Initialize with a copy of memory versions from the comparison LVN.
    global_memory_version_ = cmp->global_memory_version_;
    std::copy_n(cmp->unresolved_ifield_version_, arraysize(unresolved_sfield_version_),
                unresolved_ifield_version_);
    std::copy_n(cmp->unresolved_sfield_version_, arraysize(unresolved_ifield_version_),
                unresolved_sfield_version_);
    for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
      if (lvn == cmp) {
        continue;
      }
      for (size_t i = 0; i != kDexMemAccessTypeCount; ++i) {
        if (lvn->unresolved_ifield_version_[i] != cmp->unresolved_ifield_version_[i]) {
          unresolved_ifield_version_[i] = NewMemoryVersion(&merge_new_memory_version_);
        }
        if (lvn->unresolved_sfield_version_[i] != cmp->unresolved_sfield_version_[i]) {
          unresolved_sfield_version_[i] = NewMemoryVersion(&merge_new_memory_version_);
        }
      }
    }
  }
}

void LocalValueNumbering::PruneNonAliasingRefsForCatch() {
  for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
    const BasicBlock* bb = gvn_->GetBasicBlock(lvn->Id());
    if (UNLIKELY(bb->taken == id_) || UNLIKELY(bb->fall_through == id_)) {
      // Non-exceptional path to a catch handler means that the catch block was actually
      // empty and all exceptional paths lead to the shared path after that empty block.
      continue;
    }
    DCHECK_EQ(bb->taken, kNullBlock);
    DCHECK_NE(bb->fall_through, kNullBlock);
    const BasicBlock* fall_through_bb = gvn_->GetBasicBlock(bb->fall_through);
    const MIR* mir = fall_through_bb->first_mir_insn;
    DCHECK(mir != nullptr);
    // Only INVOKEs can leak and clobber non-aliasing references if they throw.
    if ((mir->dalvikInsn.FlagsOf() & Instruction::kInvoke) != 0) {
      HandleInvokeArgs(mir, lvn);
    }
  }
}


template <typename Set, Set LocalValueNumbering::* set_ptr>
void LocalValueNumbering::IntersectSets() {
  DCHECK_GE(gvn_->merge_lvns_.size(), 2u);

  // Find the LVN with the least entries in the set.
  const LocalValueNumbering* least_entries_lvn = gvn_->merge_lvns_[0];
  for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
    if ((lvn->*set_ptr).size() < (least_entries_lvn->*set_ptr).size()) {
      least_entries_lvn = lvn;
    }
  }

  // For each key check if it's in all the LVNs.
  for (const auto& key : least_entries_lvn->*set_ptr) {
    bool checked = true;
    for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
      if (lvn != least_entries_lvn && (lvn->*set_ptr).count(key) == 0u) {
        checked = false;
        break;
      }
    }
    if (checked) {
      (this->*set_ptr).emplace_hint((this->*set_ptr).end(), key);
    }
  }
}

void LocalValueNumbering::CopyLiveSregValues(SregValueMap* dest, const SregValueMap& src) {
  auto dest_end = dest->end();
  ArenaBitVector* live_in_v = gvn_->GetMirGraph()->GetBasicBlock(id_)->data_flow_info->live_in_v;
  DCHECK(live_in_v != nullptr);
  for (const auto& entry : src) {
    bool live = live_in_v->IsBitSet(gvn_->GetMirGraph()->SRegToVReg(entry.first));
    if (live) {
      dest->PutBefore(dest_end, entry.first, entry.second);
    }
  }
}

template <LocalValueNumbering::SregValueMap LocalValueNumbering::* map_ptr>
void LocalValueNumbering::IntersectSregValueMaps() {
  DCHECK_GE(gvn_->merge_lvns_.size(), 2u);

  // Find the LVN with the least entries in the set.
  const LocalValueNumbering* least_entries_lvn = gvn_->merge_lvns_[0];
  for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
    if ((lvn->*map_ptr).size() < (least_entries_lvn->*map_ptr).size()) {
      least_entries_lvn = lvn;
    }
  }

  // For each key check if it's in all the LVNs.
  ArenaBitVector* live_in_v = gvn_->GetMirGraph()->GetBasicBlock(id_)->data_flow_info->live_in_v;
  DCHECK(live_in_v != nullptr);
  for (const auto& entry : least_entries_lvn->*map_ptr) {
    bool live_and_same = live_in_v->IsBitSet(gvn_->GetMirGraph()->SRegToVReg(entry.first));
    if (live_and_same) {
      for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
        if (lvn != least_entries_lvn) {
          auto it = (lvn->*map_ptr).find(entry.first);
          if (it == (lvn->*map_ptr).end() || !(it->second == entry.second)) {
            live_and_same = false;
            break;
          }
        }
      }
    }
    if (live_and_same) {
      (this->*map_ptr).PutBefore((this->*map_ptr).end(), entry.first, entry.second);
    }
  }
}

// Intersect maps as sets. The value type must be equality-comparable.
template <typename Map>
void LocalValueNumbering::InPlaceIntersectMaps(Map* work_map, const Map& other_map) {
  auto work_it = work_map->begin(), work_end = work_map->end();
  auto cmp = work_map->value_comp();
  for (const auto& entry : other_map) {
    while (work_it != work_end &&
        (cmp(*work_it, entry) ||
         (!cmp(entry, *work_it) && !(work_it->second == entry.second)))) {
      work_it = work_map->erase(work_it);
    }
    if (work_it == work_end) {
      return;
    }
    ++work_it;
  }
}

template <typename Set, Set LocalValueNumbering::*set_ptr, void (LocalValueNumbering::*MergeFn)(
    const typename Set::value_type& entry, typename Set::iterator hint)>
void LocalValueNumbering::MergeSets() {
  auto cmp = (this->*set_ptr).value_comp();
  for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
    auto my_it = (this->*set_ptr).begin(), my_end = (this->*set_ptr).end();
    for (const auto& entry : lvn->*set_ptr) {
      while (my_it != my_end && cmp(*my_it, entry)) {
        ++my_it;
      }
      if (my_it != my_end && !cmp(entry, *my_it)) {
        // Already handled.
        ++my_it;
      } else {
        // Merge values for this field_id.
        (this->*MergeFn)(entry, my_it);  // my_it remains valid across inserts to std::set/SafeMap.
      }
    }
  }
}

void LocalValueNumbering::IntersectAliasingValueLocations(AliasingValues* work_values,
                                                          const AliasingValues* values) {
  auto cmp = work_values->load_value_map.key_comp();
  auto work_it = work_values->load_value_map.begin(), work_end = work_values->load_value_map.end();
  auto store_it = values->store_loc_set.begin(), store_end = values->store_loc_set.end();
  auto load_it = values->load_value_map.begin(), load_end = values->load_value_map.end();
  while (store_it != store_end || load_it != load_end) {
    uint16_t loc;
    if (store_it != store_end && (load_it == load_end || *store_it < load_it->first)) {
      loc = *store_it;
      ++store_it;
    } else {
      loc = load_it->first;
      ++load_it;
      DCHECK(store_it == store_end || cmp(loc, *store_it));
    }
    while (work_it != work_end && cmp(work_it->first, loc)) {
      work_it = work_values->load_value_map.erase(work_it);
    }
    if (work_it != work_end && !cmp(loc, work_it->first)) {
      // The location matches, keep it.
      ++work_it;
    }
  }
  while (work_it != work_end) {
    work_it = work_values->load_value_map.erase(work_it);
  }
}

void LocalValueNumbering::MergeEscapedRefs(const ValueNameSet::value_type& entry,
                                           ValueNameSet::iterator hint) {
  // See if the ref is either escaped or non-aliasing in each predecessor.
  bool is_escaped = true;
  for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
    if (lvn->non_aliasing_refs_.count(entry) == 0u &&
        lvn->escaped_refs_.count(entry) == 0u) {
      is_escaped = false;
      break;
    }
  }
  if (is_escaped) {
    escaped_refs_.emplace_hint(hint, entry);
  }
}

void LocalValueNumbering::MergeEscapedIFieldTypeClobberSets(
    const EscapedIFieldClobberSet::value_type& entry, EscapedIFieldClobberSet::iterator hint) {
  // Insert only type-clobber entries (field_id == kNoValue) of escaped refs.
  if (entry.field_id == kNoValue && escaped_refs_.count(entry.base) != 0u) {
    escaped_ifield_clobber_set_.emplace_hint(hint, entry);
  }
}

void LocalValueNumbering::MergeEscapedIFieldClobberSets(
    const EscapedIFieldClobberSet::value_type& entry, EscapedIFieldClobberSet::iterator hint) {
  // Insert only those entries of escaped refs that are not overridden by a type clobber.
  if (!(hint == escaped_ifield_clobber_set_.end() &&
        hint->base == entry.base && hint->type == entry.type) &&
      escaped_refs_.count(entry.base) != 0u) {
    escaped_ifield_clobber_set_.emplace_hint(hint, entry);
  }
}

void LocalValueNumbering::MergeEscapedArrayClobberSets(
    const EscapedArrayClobberSet::value_type& entry, EscapedArrayClobberSet::iterator hint) {
  if (escaped_refs_.count(entry.base) != 0u) {
    escaped_array_clobber_set_.emplace_hint(hint, entry);
  }
}

void LocalValueNumbering::MergeNullChecked() {
  DCHECK_GE(gvn_->merge_lvns_.size(), 2u);

  // Find the LVN with the least entries in the set.
  const LocalValueNumbering* least_entries_lvn = gvn_->merge_lvns_[0];
  for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
    if (lvn->null_checked_.size() < least_entries_lvn->null_checked_.size()) {
      least_entries_lvn = lvn;
    }
  }

  // For each null-checked value name check if it's null-checked in all the LVNs.
  for (const auto& value_name : least_entries_lvn->null_checked_) {
    // Merge null_checked_ for this ref.
    merge_names_.clear();
    merge_names_.resize(gvn_->merge_lvns_.size(), value_name);
    if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
      null_checked_.insert(null_checked_.end(), value_name);
    }
  }

  // Now check if the least_entries_lvn has a null-check as the last insn.
  const BasicBlock* least_entries_bb = gvn_->GetBasicBlock(least_entries_lvn->Id());
  if (gvn_->HasNullCheckLastInsn(least_entries_bb, id_)) {
    int s_reg = least_entries_bb->last_mir_insn->ssa_rep->uses[0];
    uint32_t value_name = least_entries_lvn->GetOperandValue(s_reg);
    merge_names_.clear();
    merge_names_.resize(gvn_->merge_lvns_.size(), value_name);
    if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
      null_checked_.insert(value_name);
    }
  }
}

void LocalValueNumbering::MergeDivZeroChecked() {
  DCHECK_GE(gvn_->merge_lvns_.size(), 2u);

  // Find the LVN with the least entries in the set.
  const LocalValueNumbering* least_entries_lvn = gvn_->merge_lvns_[0];
  for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
    if (lvn->div_zero_checked_.size() < least_entries_lvn->div_zero_checked_.size()) {
      least_entries_lvn = lvn;
    }
  }

  // For each div-zero value name check if it's div-zero checked in all the LVNs.
  for (const auto& value_name : least_entries_lvn->div_zero_checked_) {
    // Merge null_checked_ for this ref.
    merge_names_.clear();
    merge_names_.resize(gvn_->merge_lvns_.size(), value_name);
    if (gvn_->DivZeroCheckedInAllPredecessors(merge_names_)) {
      div_zero_checked_.insert(div_zero_checked_.end(), value_name);
    }
  }
}

void LocalValueNumbering::MergeSFieldValues(const SFieldToValueMap::value_type& entry,
                                            SFieldToValueMap::iterator hint) {
  uint16_t field_id = entry.first;
  merge_names_.clear();
  uint16_t value_name = kNoValue;
  bool same_values = true;
  for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
    // Get the value name as in HandleSGet() but don't modify *lvn.
    auto it = lvn->sfield_value_map_.find(field_id);
    if (it != lvn->sfield_value_map_.end()) {
      value_name = it->second;
    } else {
      uint16_t type = gvn_->GetSFieldType(field_id);
      value_name = gvn_->LookupValue(kResolvedSFieldOp, field_id,
                                     lvn->unresolved_sfield_version_[type],
                                     lvn->global_memory_version_);
    }

    same_values = same_values && (merge_names_.empty() || value_name == merge_names_.back());
    merge_names_.push_back(value_name);
  }
  if (same_values) {
    // value_name already contains the result.
  } else {
    auto lb = merge_map_.lower_bound(merge_names_);
    if (lb != merge_map_.end() && !merge_map_.key_comp()(merge_names_, lb->first)) {
      value_name = lb->second;
    } else {
      value_name = gvn_->LookupValue(kMergeBlockSFieldVersionBumpOp, field_id, id_, kNoValue);
      merge_map_.PutBefore(lb, merge_names_, value_name);
      if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
        null_checked_.insert(value_name);
      }
    }
  }
  sfield_value_map_.PutBefore(hint, field_id, value_name);
}

void LocalValueNumbering::MergeNonAliasingIFieldValues(const IFieldLocToValueMap::value_type& entry,
                                                       IFieldLocToValueMap::iterator hint) {
  uint16_t field_loc = entry.first;
  merge_names_.clear();
  uint16_t value_name = kNoValue;
  bool same_values = true;
  for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
    // Get the value name as in HandleIGet() but don't modify *lvn.
    auto it = lvn->non_aliasing_ifield_value_map_.find(field_loc);
    if (it != lvn->non_aliasing_ifield_value_map_.end()) {
      value_name = it->second;
    } else {
      value_name = gvn_->LookupValue(kNonAliasingIFieldInitialOp, field_loc, kNoValue, kNoValue);
    }

    same_values = same_values && (merge_names_.empty() || value_name == merge_names_.back());
    merge_names_.push_back(value_name);
  }
  if (same_values) {
    // value_name already contains the result.
  } else {
    auto lb = merge_map_.lower_bound(merge_names_);
    if (lb != merge_map_.end() && !merge_map_.key_comp()(merge_names_, lb->first)) {
      value_name = lb->second;
    } else {
      value_name = gvn_->LookupValue(kMergeBlockNonAliasingIFieldVersionBumpOp, field_loc,
                                     id_, kNoValue);
      merge_map_.PutBefore(lb, merge_names_, value_name);
      if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
        null_checked_.insert(value_name);
      }
    }
  }
  non_aliasing_ifield_value_map_.PutBefore(hint, field_loc, value_name);
}

template <typename Map, Map LocalValueNumbering::*map_ptr, typename Versions>
void LocalValueNumbering::MergeAliasingValues(const typename Map::value_type& entry,
                                              typename Map::iterator hint) {
  const typename Map::key_type& key = entry.first;

  auto it = (this->*map_ptr).PutBefore(hint, key, AliasingValues(this));
  AliasingValues* my_values = &it->second;

  const AliasingValues* cmp_values = nullptr;
  bool same_version = !Versions::HasNewBaseVersion(gvn_, this, key);
  uint16_t load_memory_version_for_same_version = kNoValue;
  if (same_version) {
    // Find the first non-null values.
    for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
      auto value = (lvn->*map_ptr).find(key);
      if (value != (lvn->*map_ptr).end()) {
        cmp_values = &value->second;
        break;
      }
    }
    DCHECK(cmp_values != nullptr);  // There must be at least one non-null values.

    // Check if we have identical memory versions, i.e. the global memory version, unresolved
    // field version and the values' memory_version_before_stores, last_stored_value
    // and store_loc_set are identical.
    for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
      auto value = (lvn->*map_ptr).find(key);
      if (value == (lvn->*map_ptr).end()) {
        if (cmp_values->memory_version_before_stores != kNoValue) {
          same_version = false;
          break;
        }
      } else if (cmp_values->last_stored_value != value->second.last_stored_value ||
          cmp_values->memory_version_before_stores != value->second.memory_version_before_stores ||
          cmp_values->store_loc_set != value->second.store_loc_set) {
        same_version = false;
        break;
      } else if (value->second.last_load_memory_version != kNoValue) {
        DCHECK(load_memory_version_for_same_version == kNoValue ||
               load_memory_version_for_same_version == value->second.last_load_memory_version);
        load_memory_version_for_same_version = value->second.last_load_memory_version;
      }
    }
  }

  if (same_version) {
    // Copy the identical values.
    my_values->memory_version_before_stores = cmp_values->memory_version_before_stores;
    my_values->last_stored_value = cmp_values->last_stored_value;
    my_values->store_loc_set = cmp_values->store_loc_set;
    my_values->last_load_memory_version = load_memory_version_for_same_version;
    // Merge load values seen in all incoming arcs (i.e. an intersection).
    if (!cmp_values->load_value_map.empty()) {
      my_values->load_value_map = cmp_values->load_value_map;
      for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
        auto value = (lvn->*map_ptr).find(key);
        if (value == (lvn->*map_ptr).end() || value->second.load_value_map.empty()) {
          my_values->load_value_map.clear();
          break;
        }
        InPlaceIntersectMaps(&my_values->load_value_map, value->second.load_value_map);
        if (my_values->load_value_map.empty()) {
          break;
        }
      }
    }
  } else {
    // Bump version number for the merge.
    my_values->memory_version_before_stores = my_values->last_load_memory_version =
        Versions::LookupMergeBlockValue(gvn_, id_, key);

    // Calculate the locations that have been either read from or written to in each incoming LVN.
    bool first_lvn = true;
    for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
      auto value = (lvn->*map_ptr).find(key);
      if (value == (lvn->*map_ptr).end()) {
        my_values->load_value_map.clear();
        break;
      }
      if (first_lvn) {
        first_lvn = false;
        // Copy the first LVN's locations. Values will be overwritten later.
        my_values->load_value_map = value->second.load_value_map;
        for (uint16_t location : value->second.store_loc_set) {
          my_values->load_value_map.Put(location, 0u);
        }
      } else {
        IntersectAliasingValueLocations(my_values, &value->second);
      }
    }
    // Calculate merged values for the intersection.
    for (auto& load_value_entry : my_values->load_value_map) {
      uint16_t location = load_value_entry.first;
      merge_names_.clear();
      uint16_t value_name = kNoValue;
      bool same_values = true;
      for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
        value_name = Versions::LookupMergeValue(gvn_, lvn, key, location);
        same_values = same_values && (merge_names_.empty() || value_name == merge_names_.back());
        merge_names_.push_back(value_name);
      }
      if (same_values) {
        // value_name already contains the result.
      } else {
        auto lb = merge_map_.lower_bound(merge_names_);
        if (lb != merge_map_.end() && !merge_map_.key_comp()(merge_names_, lb->first)) {
          value_name = lb->second;
        } else {
          // NOTE: In addition to the key and id_ which don't change on an LVN recalculation
          // during GVN, we also add location which can actually change on recalculation, so the
          // value_name below may change. This could lead to an infinite loop if the location
          // value name always changed when the refereced value name changes. However, given that
          // we assign unique value names for other merges, such as Phis, such a dependency is
          // not possible in a well-formed SSA graph.
          value_name = Versions::LookupMergeLocationValue(gvn_, id_, key, location);
          merge_map_.PutBefore(lb, merge_names_, value_name);
          if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
            null_checked_.insert(value_name);
          }
        }
      }
      load_value_entry.second = value_name;
    }
  }
}

void LocalValueNumbering::Merge(MergeType merge_type) {
  DCHECK_GE(gvn_->merge_lvns_.size(), 2u);

  // Always reserve space in merge_names_. Even if we don't use it in Merge() we may need it
  // in GetStartingVregValueNumberImpl() when the merge_names_'s allocator is not the top.
  merge_names_.reserve(gvn_->merge_lvns_.size());

  IntersectSregValueMaps<&LocalValueNumbering::sreg_value_map_>();
  IntersectSregValueMaps<&LocalValueNumbering::sreg_wide_value_map_>();
  if (merge_type == kReturnMerge) {
    // RETURN or PHI+RETURN. We need only sreg value maps.
    return;
  }

  MergeMemoryVersions(merge_type == kCatchMerge);

  // Merge non-aliasing maps/sets.
  IntersectSets<ValueNameSet, &LocalValueNumbering::non_aliasing_refs_>();
  if (!non_aliasing_refs_.empty() && merge_type == kCatchMerge) {
    PruneNonAliasingRefsForCatch();
  }
  if (!non_aliasing_refs_.empty()) {
    MergeSets<IFieldLocToValueMap, &LocalValueNumbering::non_aliasing_ifield_value_map_,
              &LocalValueNumbering::MergeNonAliasingIFieldValues>();
    MergeSets<NonAliasingArrayValuesMap, &LocalValueNumbering::non_aliasing_array_value_map_,
              &LocalValueNumbering::MergeAliasingValues<
                  NonAliasingArrayValuesMap, &LocalValueNumbering::non_aliasing_array_value_map_,
                  NonAliasingArrayVersions>>();
  }

  // We won't do anything complicated for range checks, just calculate the intersection.
  IntersectSets<RangeCheckSet, &LocalValueNumbering::range_checked_>();

  // Merge null_checked_. We may later insert more, such as merged object field values.
  MergeNullChecked();

  // Now merge the div_zero_checked_.
  MergeDivZeroChecked();

  if (merge_type == kCatchMerge) {
    // Memory is clobbered. New memory version already created, don't merge aliasing locations.
    return;
  }

  DCHECK(merge_type == kNormalMerge);

  // Merge escaped refs and clobber sets.
  MergeSets<ValueNameSet, &LocalValueNumbering::escaped_refs_,
            &LocalValueNumbering::MergeEscapedRefs>();
  if (!escaped_refs_.empty()) {
    MergeSets<EscapedIFieldClobberSet, &LocalValueNumbering::escaped_ifield_clobber_set_,
              &LocalValueNumbering::MergeEscapedIFieldTypeClobberSets>();
    MergeSets<EscapedIFieldClobberSet, &LocalValueNumbering::escaped_ifield_clobber_set_,
              &LocalValueNumbering::MergeEscapedIFieldClobberSets>();
    MergeSets<EscapedArrayClobberSet, &LocalValueNumbering::escaped_array_clobber_set_,
              &LocalValueNumbering::MergeEscapedArrayClobberSets>();
  }

  MergeSets<SFieldToValueMap, &LocalValueNumbering::sfield_value_map_,
            &LocalValueNumbering::MergeSFieldValues>();
  MergeSets<AliasingIFieldValuesMap, &LocalValueNumbering::aliasing_ifield_value_map_,
            &LocalValueNumbering::MergeAliasingValues<
                AliasingIFieldValuesMap, &LocalValueNumbering::aliasing_ifield_value_map_,
                AliasingIFieldVersions>>();
  MergeSets<AliasingArrayValuesMap, &LocalValueNumbering::aliasing_array_value_map_,
            &LocalValueNumbering::MergeAliasingValues<
                AliasingArrayValuesMap, &LocalValueNumbering::aliasing_array_value_map_,
                AliasingArrayVersions>>();
}

void LocalValueNumbering::PrepareEntryBlock() {
  uint32_t vreg = gvn_->GetMirGraph()->GetFirstInVR();
  CompilationUnit* cu = gvn_->GetCompilationUnit();
  const char* shorty = cu->shorty;
  ++shorty;  // Skip return value.
  if ((cu->access_flags & kAccStatic) == 0) {
    // If non-static method, mark "this" as non-null
    uint16_t value_name = GetOperandValue(vreg);
    ++vreg;
    null_checked_.insert(value_name);
  }
  for ( ; *shorty != 0; ++shorty, ++vreg) {
    if (*shorty == 'J' || *shorty == 'D') {
      uint16_t value_name = GetOperandValueWide(vreg);
      SetOperandValueWide(vreg, value_name);
      ++vreg;
    }
  }
}

uint16_t LocalValueNumbering::MarkNonAliasingNonNull(MIR* mir) {
  uint16_t res = GetOperandValue(mir->ssa_rep->defs[0]);
  DCHECK(null_checked_.find(res) == null_checked_.end());
  null_checked_.insert(res);
  non_aliasing_refs_.insert(res);
  return res;
}

bool LocalValueNumbering::IsNonAliasing(uint16_t reg) const {
  return non_aliasing_refs_.find(reg) != non_aliasing_refs_.end();
}

bool LocalValueNumbering::IsNonAliasingIField(uint16_t reg, uint16_t field_id,
                                              uint16_t type) const {
  if (IsNonAliasing(reg)) {
    return true;
  }
  if (escaped_refs_.find(reg) == escaped_refs_.end()) {
    return false;
  }
  // Check for IPUTs to unresolved fields.
  EscapedIFieldClobberKey key1 = { reg, type, kNoValue };
  if (escaped_ifield_clobber_set_.find(key1) != escaped_ifield_clobber_set_.end()) {
    return false;
  }
  // Check for aliased IPUTs to the same field.
  EscapedIFieldClobberKey key2 = { reg, type, field_id };
  return escaped_ifield_clobber_set_.find(key2) == escaped_ifield_clobber_set_.end();
}

bool LocalValueNumbering::IsNonAliasingArray(uint16_t reg, uint16_t type) const {
  if (IsNonAliasing(reg)) {
    return true;
  }
  if (escaped_refs_.count(reg) == 0u) {
    return false;
  }
  // Check for aliased APUTs.
  EscapedArrayClobberKey key = { reg, type };
  return escaped_array_clobber_set_.find(key) == escaped_array_clobber_set_.end();
}

void LocalValueNumbering::HandleNullCheck(MIR* mir, uint16_t reg) {
  auto lb = null_checked_.lower_bound(reg);
  if (lb != null_checked_.end() && *lb == reg) {
    if (LIKELY(gvn_->CanModify())) {
      if (gvn_->GetCompilationUnit()->verbose) {
        LOG(INFO) << "Removing null check for 0x" << std::hex << mir->offset;
      }
      mir->optimization_flags |= MIR_IGNORE_NULL_CHECK;
    }
  } else {
    null_checked_.insert(lb, reg);
  }
}

void LocalValueNumbering::HandleRangeCheck(MIR* mir, uint16_t array, uint16_t index) {
  RangeCheckKey key = { array, index };
  auto lb = range_checked_.lower_bound(key);
  if (lb != range_checked_.end() && !RangeCheckKeyComparator()(key, *lb)) {
    if (LIKELY(gvn_->CanModify())) {
      if (gvn_->GetCompilationUnit()->verbose) {
        LOG(INFO) << "Removing range check for 0x" << std::hex << mir->offset;
      }
      mir->optimization_flags |= MIR_IGNORE_RANGE_CHECK;
    }
  } else {
    // Mark range check completed.
    range_checked_.insert(lb, key);
  }
}

void LocalValueNumbering::HandleDivZeroCheck(MIR* mir, uint16_t reg) {
  auto lb = div_zero_checked_.lower_bound(reg);
  if (lb != div_zero_checked_.end() && *lb == reg) {
    if (LIKELY(gvn_->CanModify())) {
      if (gvn_->GetCompilationUnit()->verbose) {
        LOG(INFO) << "Removing div zero check for 0x" << std::hex << mir->offset;
      }
      mir->optimization_flags |= MIR_IGNORE_DIV_ZERO_CHECK;
    }
  } else {
    div_zero_checked_.insert(lb, reg);
  }
}

void LocalValueNumbering::HandlePutObject(MIR* mir) {
  // If we're storing a non-aliasing reference, stop tracking it as non-aliasing now.
  uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]);
  HandleEscapingRef(base);
  if (gvn_->CanModify() && null_checked_.count(base) != 0u) {
    if (gvn_->GetCompilationUnit()->verbose) {
      LOG(INFO) << "Removing GC card mark value null check for 0x" << std::hex << mir->offset;
    }
    mir->optimization_flags |= MIR_STORE_NON_NULL_VALUE;
  }
}

void LocalValueNumbering::HandleEscapingRef(uint16_t base) {
  auto it = non_aliasing_refs_.find(base);
  if (it != non_aliasing_refs_.end()) {
    non_aliasing_refs_.erase(it);
    escaped_refs_.insert(base);
  }
}

void LocalValueNumbering::HandleInvokeArgs(const MIR* mir, const LocalValueNumbering* mir_lvn) {
  const int32_t* uses = mir->ssa_rep->uses;
  const int32_t* uses_end = uses + mir->ssa_rep->num_uses;
  while (uses != uses_end) {
    uint16_t sreg = *uses;
    ++uses;
    // Avoid LookupValue() so that we don't store new values in the global value map.
    auto local_it = mir_lvn->sreg_value_map_.find(sreg);
    if (local_it != mir_lvn->sreg_value_map_.end()) {
      non_aliasing_refs_.erase(local_it->second);
    } else {
      uint16_t value_name = gvn_->FindValue(kNoValue, sreg, kNoValue, kNoValue);
      if (value_name != kNoValue) {
        non_aliasing_refs_.erase(value_name);
      }
    }
  }
}

uint16_t LocalValueNumbering::HandlePhi(MIR* mir) {
  if (gvn_->merge_lvns_.empty()) {
    // Running LVN without a full GVN?
    return kNoValue;
  }
  // Determine if this Phi is merging wide regs.
  RegLocation raw_dest = gvn_->GetMirGraph()->GetRawDest(mir);
  if (raw_dest.high_word) {
    // This is the high part of a wide reg. Ignore the Phi.
    return kNoValue;
  }
  bool wide = raw_dest.wide;
  // Iterate over *merge_lvns_ and skip incoming sregs for BBs without associated LVN.
  merge_names_.clear();
  uint16_t value_name = kNoValue;
  bool same_values = true;
  BasicBlockId* incoming = mir->meta.phi_incoming;
  int32_t* uses = mir->ssa_rep->uses;
  int16_t pos = 0;
  for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
    DCHECK_LT(pos, mir->ssa_rep->num_uses);
    while (incoming[pos] != lvn->Id()) {
      ++pos;
      DCHECK_LT(pos, mir->ssa_rep->num_uses);
    }
    int s_reg = uses[pos];
    ++pos;
    value_name = wide ? lvn->GetOperandValueWide(s_reg) : lvn->GetOperandValue(s_reg);

    same_values = same_values && (merge_names_.empty() || value_name == merge_names_.back());
    merge_names_.push_back(value_name);
  }
  if (same_values) {
    // value_name already contains the result.
  } else {
    auto lb = merge_map_.lower_bound(merge_names_);
    if (lb != merge_map_.end() && !merge_map_.key_comp()(merge_names_, lb->first)) {
      value_name = lb->second;
    } else {
      value_name = gvn_->LookupValue(kNoValue, mir->ssa_rep->defs[0], kNoValue, kNoValue);
      merge_map_.PutBefore(lb, merge_names_, value_name);
      if (!wide && gvn_->NullCheckedInAllPredecessors(merge_names_)) {
        null_checked_.insert(value_name);
      }
      if (gvn_->DivZeroCheckedInAllPredecessors(merge_names_)) {
        div_zero_checked_.insert(value_name);
      }
    }
  }
  if (wide) {
    SetOperandValueWide(mir->ssa_rep->defs[0], value_name);
  } else {
    SetOperandValue(mir->ssa_rep->defs[0], value_name);
  }
  return value_name;
}

uint16_t LocalValueNumbering::HandleConst(MIR* mir, uint32_t value) {
  RegLocation raw_dest = gvn_->GetMirGraph()->GetRawDest(mir);
  uint16_t res;
  if (value == 0u && raw_dest.ref) {
    res = GlobalValueNumbering::kNullValue;
  } else {
    Instruction::Code op = raw_dest.fp ? Instruction::CONST_HIGH16 : Instruction::CONST;
    res = gvn_->LookupValue(op, Low16Bits(value), High16Bits(value), 0);
  }
  SetOperandValue(mir->ssa_rep->defs[0], res);
  return res;
}

uint16_t LocalValueNumbering::HandleConstWide(MIR* mir, uint64_t value) {
  RegLocation raw_dest = gvn_->GetMirGraph()->GetRawDest(mir);
  Instruction::Code op = raw_dest.fp ? Instruction::CONST_HIGH16 : Instruction::CONST;
  uint32_t low_word = Low32Bits(value);
  uint32_t high_word = High32Bits(value);
  uint16_t low_res = gvn_->LookupValue(op, Low16Bits(low_word), High16Bits(low_word), 1);
  uint16_t high_res = gvn_->LookupValue(op, Low16Bits(high_word), High16Bits(high_word), 2);
  uint16_t res = gvn_->LookupValue(op, low_res, high_res, 3);
  SetOperandValueWide(mir->ssa_rep->defs[0], res);
  return res;
}

uint16_t LocalValueNumbering::HandleAGet(MIR* mir, uint16_t opcode) {
  uint16_t array = GetOperandValue(mir->ssa_rep->uses[0]);
  HandleNullCheck(mir, array);
  uint16_t index = GetOperandValue(mir->ssa_rep->uses[1]);
  HandleRangeCheck(mir, array, index);
  uint16_t type = AGetMemAccessType(static_cast<Instruction::Code>(opcode));
  // Establish value number for loaded register.
  uint16_t res;
  if (IsNonAliasingArray(array, type)) {
    res = HandleAliasingValuesGet<NonAliasingArrayVersions>(&non_aliasing_array_value_map_,
                                                            array, index);
  } else {
    uint16_t location = gvn_->GetArrayLocation(array, index);
    res = HandleAliasingValuesGet<AliasingArrayVersions>(&aliasing_array_value_map_,
                                                         type, location);
  }
  if (opcode == Instruction::AGET_WIDE) {
    SetOperandValueWide(mir->ssa_rep->defs[0], res);
  } else {
    SetOperandValue(mir->ssa_rep->defs[0], res);
  }
  return res;
}

void LocalValueNumbering::HandleAPut(MIR* mir, uint16_t opcode) {
  int array_idx = (opcode == Instruction::APUT_WIDE) ? 2 : 1;
  int index_idx = array_idx + 1;
  uint16_t array = GetOperandValue(mir->ssa_rep->uses[array_idx]);
  HandleNullCheck(mir, array);
  uint16_t index = GetOperandValue(mir->ssa_rep->uses[index_idx]);
  HandleRangeCheck(mir, array, index);

  uint16_t type = APutMemAccessType(static_cast<Instruction::Code>(opcode));
  uint16_t value = (opcode == Instruction::APUT_WIDE)
                   ? GetOperandValueWide(mir->ssa_rep->uses[0])
                   : GetOperandValue(mir->ssa_rep->uses[0]);
  if (IsNonAliasing(array)) {
    bool put_is_live = HandleAliasingValuesPut<NonAliasingArrayVersions>(
        &non_aliasing_array_value_map_, array, index, value);
    if (!put_is_live) {
      // This APUT can be eliminated, it stores the same value that's already in the field.
      // TODO: Eliminate the APUT.
      return;
    }
  } else {
    uint16_t location = gvn_->GetArrayLocation(array, index);
    bool put_is_live = HandleAliasingValuesPut<AliasingArrayVersions>(
        &aliasing_array_value_map_, type, location, value);
    if (!put_is_live) {
      // This APUT can be eliminated, it stores the same value that's already in the field.
      // TODO: Eliminate the APUT.
      return;
    }

    // Clobber all escaped array refs for this type.
    for (uint16_t escaped_array : escaped_refs_) {
      EscapedArrayClobberKey clobber_key = { escaped_array, type };
      escaped_array_clobber_set_.insert(clobber_key);
    }
  }
}

uint16_t LocalValueNumbering::HandleIGet(MIR* mir, uint16_t opcode) {
  uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]);
  HandleNullCheck(mir, base);
  const MirFieldInfo& field_info = gvn_->GetMirGraph()->GetIFieldLoweringInfo(mir);
  uint16_t res;
  if (!field_info.IsResolved() || field_info.IsVolatile()) {
    // Unresolved fields may be volatile, so handle them as such to be safe.
    HandleInvokeOrClInitOrAcquireOp(mir);  // Volatile GETs have acquire semantics.
    // Volatile fields always get a new memory version; field id is irrelevant.
    // Use result s_reg - will be unique.
    res = gvn_->LookupValue(kNoValue, mir->ssa_rep->defs[0], kNoValue, kNoValue);
  } else {
    uint16_t type = IGetMemAccessType(static_cast<Instruction::Code>(opcode));
    uint16_t field_id = gvn_->GetIFieldId(mir);
    if (IsNonAliasingIField(base, field_id, type)) {
      uint16_t loc = gvn_->LookupValue(kNonAliasingIFieldLocOp, base, field_id, type);
      auto lb = non_aliasing_ifield_value_map_.lower_bound(loc);
      if (lb != non_aliasing_ifield_value_map_.end() && lb->first == loc) {
        res = lb->second;
      } else {
        res = gvn_->LookupValue(kNonAliasingIFieldInitialOp, loc, kNoValue, kNoValue);
        non_aliasing_ifield_value_map_.PutBefore(lb, loc, res);
      }
    } else {
      res = HandleAliasingValuesGet<AliasingIFieldVersions>(&aliasing_ifield_value_map_,
                                                            field_id, base);
    }
  }
  if (opcode == Instruction::IGET_WIDE) {
    SetOperandValueWide(mir->ssa_rep->defs[0], res);
  } else {
    SetOperandValue(mir->ssa_rep->defs[0], res);
  }
  return res;
}

void LocalValueNumbering::HandleIPut(MIR* mir, uint16_t opcode) {
  int base_reg = (opcode == Instruction::IPUT_WIDE) ? 2 : 1;
  uint16_t base = GetOperandValue(mir->ssa_rep->uses[base_reg]);
  HandleNullCheck(mir, base);
  uint16_t type = IPutMemAccessType(static_cast<Instruction::Code>(opcode));
  const MirFieldInfo& field_info = gvn_->GetMirGraph()->GetIFieldLoweringInfo(mir);
  if (!field_info.IsResolved()) {
    // Unresolved fields always alias with everything of the same type.
    // Use mir->offset as modifier; without elaborate inlining, it will be unique.
    unresolved_ifield_version_[type] =
        gvn_->LookupValue(kUnresolvedIFieldOp, kNoValue, kNoValue, mir->offset);

    // For simplicity, treat base as escaped now.
    HandleEscapingRef(base);

    // Clobber all fields of escaped references of the same type.
    for (uint16_t escaped_ref : escaped_refs_) {
      EscapedIFieldClobberKey clobber_key = { escaped_ref, type, kNoValue };
      escaped_ifield_clobber_set_.insert(clobber_key);
    }

    // Aliasing fields of the same type may have been overwritten.
    auto it = aliasing_ifield_value_map_.begin(), end = aliasing_ifield_value_map_.end();
    while (it != end) {
      if (gvn_->GetIFieldType(it->first) != type) {
        ++it;
      } else {
        it = aliasing_ifield_value_map_.erase(it);
      }
    }
  } else if (field_info.IsVolatile()) {
    // Nothing to do, resolved volatile fields always get a new memory version anyway and
    // can't alias with resolved non-volatile fields.
  } else {
    uint16_t field_id = gvn_->GetIFieldId(mir);
    uint16_t value = (opcode == Instruction::IPUT_WIDE)
                     ? GetOperandValueWide(mir->ssa_rep->uses[0])
                     : GetOperandValue(mir->ssa_rep->uses[0]);
    if (IsNonAliasing(base)) {
      uint16_t loc = gvn_->LookupValue(kNonAliasingIFieldLocOp, base, field_id, type);
      auto lb = non_aliasing_ifield_value_map_.lower_bound(loc);
      if (lb != non_aliasing_ifield_value_map_.end() && lb->first == loc) {
        if (lb->second == value) {
          // This IPUT can be eliminated, it stores the same value that's already in the field.
          // TODO: Eliminate the IPUT.
          return;
        }
        lb->second = value;  // Overwrite.
      } else {
        non_aliasing_ifield_value_map_.PutBefore(lb, loc, value);
      }
    } else {
      bool put_is_live = HandleAliasingValuesPut<AliasingIFieldVersions>(
          &aliasing_ifield_value_map_, field_id, base, value);
      if (!put_is_live) {
        // This IPUT can be eliminated, it stores the same value that's already in the field.
        // TODO: Eliminate the IPUT.
        return;
      }

      // Clobber all fields of escaped references for this field.
      for (uint16_t escaped_ref : escaped_refs_) {
        EscapedIFieldClobberKey clobber_key = { escaped_ref, type, field_id };
        escaped_ifield_clobber_set_.insert(clobber_key);
      }
    }
  }
}

uint16_t LocalValueNumbering::HandleSGet(MIR* mir, uint16_t opcode) {
  const MirSFieldLoweringInfo& field_info = gvn_->GetMirGraph()->GetSFieldLoweringInfo(mir);
  if (!field_info.IsResolved() || field_info.IsVolatile() ||
      (!field_info.IsClassInitialized() &&
       (mir->optimization_flags & MIR_CLASS_IS_INITIALIZED) == 0)) {
    // Volatile SGETs (and unresolved fields are potentially volatile) have acquire semantics
    // and class initialization can call arbitrary functions, we need to wipe aliasing values.
    HandleInvokeOrClInitOrAcquireOp(mir);
  }
  uint16_t res;
  if (!field_info.IsResolved() || field_info.IsVolatile()) {
    // Unresolved fields may be volatile, so handle them as such to be safe.
    // Volatile fields always get a new memory version; field id is irrelevant.
    // Use result s_reg - will be unique.
    res = gvn_->LookupValue(kNoValue, mir->ssa_rep->defs[0], kNoValue, kNoValue);
  } else {
    uint16_t type = SGetMemAccessType(static_cast<Instruction::Code>(opcode));
    uint16_t field_id = gvn_->GetSFieldId(mir);
    auto lb = sfield_value_map_.lower_bound(field_id);
    if (lb != sfield_value_map_.end() && lb->first == field_id) {
      res = lb->second;
    } else {
      // Resolved non-volatile static fields can alias with non-resolved fields of the same type,
      // so we need to use unresolved_sfield_version_[type] in addition to global_memory_version_
      // to determine the version of the field.
      res = gvn_->LookupValue(kResolvedSFieldOp, field_id,
                              unresolved_sfield_version_[type], global_memory_version_);
      sfield_value_map_.PutBefore(lb, field_id, res);
    }
  }
  if (opcode == Instruction::SGET_WIDE) {
    SetOperandValueWide(mir->ssa_rep->defs[0], res);
  } else {
    SetOperandValue(mir->ssa_rep->defs[0], res);
  }
  return res;
}

void LocalValueNumbering::HandleSPut(MIR* mir, uint16_t opcode) {
  const MirSFieldLoweringInfo& field_info = gvn_->GetMirGraph()->GetSFieldLoweringInfo(mir);
  if (!field_info.IsClassInitialized() &&
      (mir->optimization_flags & MIR_CLASS_IS_INITIALIZED) == 0) {
    // Class initialization can call arbitrary functions, we need to wipe aliasing values.
    HandleInvokeOrClInitOrAcquireOp(mir);
  }
  uint16_t type = SPutMemAccessType(static_cast<Instruction::Code>(opcode));
  if (!field_info.IsResolved()) {
    // Unresolved fields always alias with everything of the same type.
    // Use mir->offset as modifier; without elaborate inlining, it will be unique.
    unresolved_sfield_version_[type] =
        gvn_->LookupValue(kUnresolvedSFieldOp, kNoValue, kNoValue, mir->offset);
    RemoveSFieldsForType(type);
  } else if (field_info.IsVolatile()) {
    // Nothing to do, resolved volatile fields always get a new memory version anyway and
    // can't alias with resolved non-volatile fields.
  } else {
    uint16_t field_id = gvn_->GetSFieldId(mir);
    uint16_t value = (opcode == Instruction::SPUT_WIDE)
                     ? GetOperandValueWide(mir->ssa_rep->uses[0])
                     : GetOperandValue(mir->ssa_rep->uses[0]);
    // Resolved non-volatile static fields can alias with non-resolved fields of the same type,
    // so we need to use unresolved_sfield_version_[type] in addition to global_memory_version_
    // to determine the version of the field.
    auto lb = sfield_value_map_.lower_bound(field_id);
    if (lb != sfield_value_map_.end() && lb->first == field_id) {
      if (lb->second == value) {
        // This SPUT can be eliminated, it stores the same value that's already in the field.
        // TODO: Eliminate the SPUT.
        return;
      }
      lb->second = value;  // Overwrite.
    } else {
      sfield_value_map_.PutBefore(lb, field_id, value);
    }
  }
}

void LocalValueNumbering::RemoveSFieldsForType(uint16_t type) {
  // Erase all static fields of this type from the sfield_value_map_.
  for (auto it = sfield_value_map_.begin(), end = sfield_value_map_.end(); it != end; ) {
    if (gvn_->GetSFieldType(it->first) == type) {
      it = sfield_value_map_.erase(it);
    } else {
      ++it;
    }
  }
}

void LocalValueNumbering::HandleInvokeOrClInitOrAcquireOp(MIR* mir) {
  // Use mir->offset as modifier; without elaborate inlining, it will be unique.
  global_memory_version_ =
      gvn_->LookupValue(kInvokeMemoryVersionBumpOp, 0u, 0u, mir->offset);
  // All static fields and instance fields and array elements of aliasing references,
  // including escaped references, may have been modified.
  sfield_value_map_.clear();
  aliasing_ifield_value_map_.clear();
  aliasing_array_value_map_.clear();
  escaped_refs_.clear();
  escaped_ifield_clobber_set_.clear();
  escaped_array_clobber_set_.clear();
}

uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) {
  uint16_t res = kNoValue;
  uint16_t opcode = mir->dalvikInsn.opcode;
  switch (opcode) {
    case Instruction::NOP:
    case Instruction::RETURN_VOID:
    case Instruction::RETURN:
    case Instruction::RETURN_OBJECT:
    case Instruction::RETURN_WIDE:
    case Instruction::GOTO:
    case Instruction::GOTO_16:
    case Instruction::GOTO_32:
    case Instruction::THROW:
    case Instruction::FILL_ARRAY_DATA:
    case Instruction::PACKED_SWITCH:
    case Instruction::SPARSE_SWITCH:
    case Instruction::IF_EQ:
    case Instruction::IF_NE:
    case Instruction::IF_LT:
    case Instruction::IF_GE:
    case Instruction::IF_GT:
    case Instruction::IF_LE:
    case Instruction::IF_EQZ:
    case Instruction::IF_NEZ:
    case Instruction::IF_LTZ:
    case Instruction::IF_GEZ:
    case Instruction::IF_GTZ:
    case Instruction::IF_LEZ:
    case kMirOpFusedCmplFloat:
    case kMirOpFusedCmpgFloat:
    case kMirOpFusedCmplDouble:
    case kMirOpFusedCmpgDouble:
    case kMirOpFusedCmpLong:
      // Nothing defined - take no action.
      break;

    case Instruction::MONITOR_ENTER:
      HandleNullCheck(mir, GetOperandValue(mir->ssa_rep->uses[0]));
      HandleInvokeOrClInitOrAcquireOp(mir);  // Acquire operation.
      break;

    case Instruction::MONITOR_EXIT:
      HandleNullCheck(mir, GetOperandValue(mir->ssa_rep->uses[0]));
      // If we're running GVN and CanModify(), uneliminated null check indicates bytecode error.
      if ((mir->optimization_flags & MIR_IGNORE_NULL_CHECK) == 0 &&
          gvn_->work_lvn_ != nullptr && gvn_->CanModify()) {
        LOG(WARNING) << "Bytecode error: MONITOR_EXIT is still null checked at 0x" << std::hex
            << mir->offset << " in " << PrettyMethod(gvn_->cu_->method_idx, *gvn_->cu_->dex_file);
      }
      break;

    case Instruction::FILLED_NEW_ARRAY:
    case Instruction::FILLED_NEW_ARRAY_RANGE:
      // Nothing defined but the result will be unique and non-null.
      if (mir->next != nullptr && mir->next->dalvikInsn.opcode == Instruction::MOVE_RESULT_OBJECT) {
        uint16_t array = MarkNonAliasingNonNull(mir->next);
        // Do not SetOperandValue(), we'll do that when we process the MOVE_RESULT_OBJECT.
        if (kLocalValueNumberingEnableFilledNewArrayTracking && mir->ssa_rep->num_uses != 0u) {
          AliasingValues* values = GetAliasingValues(&non_aliasing_array_value_map_, array);
          // Clear the value if we got a merged version in a loop.
          *values = AliasingValues(this);
          for (size_t i = 0u, count = mir->ssa_rep->num_uses; i != count; ++i) {
            DCHECK_EQ(High16Bits(i), 0u);
            uint16_t index = gvn_->LookupValue(Instruction::CONST, i, 0u, 0);
            uint16_t value = GetOperandValue(mir->ssa_rep->uses[i]);
            values->load_value_map.Put(index, value);
            RangeCheckKey key = { array, index };
            range_checked_.insert(key);
          }
        }
        // The MOVE_RESULT_OBJECT will be processed next and we'll return the value name then.
      }
      // All args escaped (if references).
      for (size_t i = 0u, count = mir->ssa_rep->num_uses; i != count; ++i) {
        uint16_t reg = GetOperandValue(mir->ssa_rep->uses[i]);
        HandleEscapingRef(reg);
      }
      break;

    case kMirOpNullCheck:
      HandleNullCheck(mir, GetOperandValue(mir->ssa_rep->uses[0]));
      break;

    case Instruction::INVOKE_DIRECT:
    case Instruction::INVOKE_DIRECT_RANGE:
    case Instruction::INVOKE_VIRTUAL:
    case Instruction::INVOKE_VIRTUAL_RANGE:
    case Instruction::INVOKE_SUPER:
    case Instruction::INVOKE_SUPER_RANGE:
    case Instruction::INVOKE_INTERFACE:
    case Instruction::INVOKE_INTERFACE_RANGE: {
        // Nothing defined but handle the null check.
        uint16_t reg = GetOperandValue(mir->ssa_rep->uses[0]);
        HandleNullCheck(mir, reg);
      }
      FALLTHROUGH_INTENDED;
    case Instruction::INVOKE_STATIC:
    case Instruction::INVOKE_STATIC_RANGE:
      // Make ref args aliasing.
      HandleInvokeArgs(mir, this);
      HandleInvokeOrClInitOrAcquireOp(mir);
      break;

    case Instruction::INSTANCE_OF: {
        uint16_t operand = GetOperandValue(mir->ssa_rep->uses[0]);
        uint16_t type = mir->dalvikInsn.vC;
        res = gvn_->LookupValue(Instruction::INSTANCE_OF, operand, type, kNoValue);
        SetOperandValue(mir->ssa_rep->defs[0], res);
      }
      break;
    case Instruction::CHECK_CAST:
      if (gvn_->CanModify()) {
        // Check if there was an instance-of operation on the same value and if we are
        // in a block where its result is true. If so, we can eliminate the check-cast.
        uint16_t operand = GetOperandValue(mir->ssa_rep->uses[0]);
        uint16_t type = mir->dalvikInsn.vB;
        uint16_t cond = gvn_->FindValue(Instruction::INSTANCE_OF, operand, type, kNoValue);
        if (cond != kNoValue && gvn_->IsTrueInBlock(cond, Id())) {
          if (gvn_->GetCompilationUnit()->verbose) {
            LOG(INFO) << "Removing check-cast at 0x" << std::hex << mir->offset;
          }
          // Don't use kMirOpNop. Keep the check-cast as it defines the type of the register.
          mir->optimization_flags |= MIR_IGNORE_CHECK_CAST;
        }
      }
      break;

    case Instruction::MOVE_RESULT:
    case Instruction::MOVE_RESULT_OBJECT:
      // 1 result, treat as unique each time, use result s_reg - will be unique.
      res = GetOperandValue(mir->ssa_rep->defs[0]);
      SetOperandValue(mir->ssa_rep->defs[0], res);
      break;
    case Instruction::MOVE_EXCEPTION:
    case Instruction::NEW_INSTANCE:
    case Instruction::NEW_ARRAY:
      // 1 result, treat as unique each time, use result s_reg - will be unique.
      res = MarkNonAliasingNonNull(mir);
      SetOperandValue(mir->ssa_rep->defs[0], res);
      break;
    case Instruction::CONST_CLASS:
      DCHECK_EQ(Low16Bits(mir->dalvikInsn.vB), mir->dalvikInsn.vB);
      res = gvn_->LookupValue(Instruction::CONST_CLASS, mir->dalvikInsn.vB, 0, 0);
      SetOperandValue(mir->ssa_rep->defs[0], res);
      null_checked_.insert(res);
      non_aliasing_refs_.insert(res);
      break;
    case Instruction::CONST_STRING:
    case Instruction::CONST_STRING_JUMBO:
      // These strings are internalized, so assign value based on the string pool index.
      res = gvn_->LookupValue(Instruction::CONST_STRING, Low16Bits(mir->dalvikInsn.vB),
                              High16Bits(mir->dalvikInsn.vB), 0);
      SetOperandValue(mir->ssa_rep->defs[0], res);
      null_checked_.insert(res);  // May already be there.
      // NOTE: Hacking the contents of an internalized string via reflection is possible
      // but the behavior is undefined. Therefore, we consider the string constant and
      // the reference non-aliasing.
      // TUNING: We could keep this property even if the reference "escapes".
      non_aliasing_refs_.insert(res);  // May already be there.
      break;
    case Instruction::MOVE_RESULT_WIDE:
      // 1 wide result, treat as unique each time, use result s_reg - will be unique.
      res = GetOperandValueWide(mir->ssa_rep->defs[0]);
      SetOperandValueWide(mir->ssa_rep->defs[0], res);
      break;

    case kMirOpPhi:
      res = HandlePhi(mir);
      break;

    case Instruction::MOVE:
    case Instruction::MOVE_OBJECT:
    case Instruction::MOVE_16:
    case Instruction::MOVE_OBJECT_16:
    case Instruction::MOVE_FROM16:
    case Instruction::MOVE_OBJECT_FROM16:
    case kMirOpCopy:
      // Just copy value number of source to value number of result.
      res = GetOperandValue(mir->ssa_rep->uses[0]);
      SetOperandValue(mir->ssa_rep->defs[0], res);
      break;

    case Instruction::MOVE_WIDE:
    case Instruction::MOVE_WIDE_16:
    case Instruction::MOVE_WIDE_FROM16:
      // Just copy value number of source to value number of result.
      res = GetOperandValueWide(mir->ssa_rep->uses[0]);
      SetOperandValueWide(mir->ssa_rep->defs[0], res);
      break;

    case Instruction::CONST_HIGH16:
      res = HandleConst(mir, mir->dalvikInsn.vB << 16);
      break;
    case Instruction::CONST:
    case Instruction::CONST_4:
    case Instruction::CONST_16:
      res = HandleConst(mir, mir->dalvikInsn.vB);
      break;

    case Instruction::CONST_WIDE_16:
    case Instruction::CONST_WIDE_32:
      res = HandleConstWide(
          mir,
          mir->dalvikInsn.vB +
              ((mir->dalvikInsn.vB & 0x80000000) != 0 ? UINT64_C(0xffffffff00000000) : 0u));
      break;

    case Instruction::CONST_WIDE:
      res = HandleConstWide(mir, mir->dalvikInsn.vB_wide);
      break;

    case Instruction::CONST_WIDE_HIGH16:
      res = HandleConstWide(mir, static_cast<uint64_t>(mir->dalvikInsn.vB) << 48);
      break;

    case Instruction::ARRAY_LENGTH: {
        // Handle the null check.
        uint16_t reg = GetOperandValue(mir->ssa_rep->uses[0]);
        HandleNullCheck(mir, reg);
      }
      FALLTHROUGH_INTENDED;
    case Instruction::NEG_INT:
    case Instruction::NOT_INT:
    case Instruction::NEG_FLOAT:
    case Instruction::INT_TO_BYTE:
    case Instruction::INT_TO_SHORT:
    case Instruction::INT_TO_CHAR:
    case Instruction::INT_TO_FLOAT:
    case Instruction::FLOAT_TO_INT: {
        // res = op + 1 operand
        uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
        res = gvn_->LookupValue(opcode, operand1, kNoValue, kNoValue);
        SetOperandValue(mir->ssa_rep->defs[0], res);
      }
      break;

    case Instruction::LONG_TO_FLOAT:
    case Instruction::LONG_TO_INT:
    case Instruction::DOUBLE_TO_FLOAT:
    case Instruction::DOUBLE_TO_INT: {
        // res = op + 1 wide operand
        uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
        res = gvn_->LookupValue(opcode, operand1, kNoValue, kNoValue);
        SetOperandValue(mir->ssa_rep->defs[0], res);
      }
      break;

    case Instruction::DOUBLE_TO_LONG:
    case Instruction::LONG_TO_DOUBLE:
    case Instruction::NEG_LONG:
    case Instruction::NOT_LONG:
    case Instruction::NEG_DOUBLE: {
        // wide res = op + 1 wide operand
        uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
        res = gvn_->LookupValue(opcode, operand1, kNoValue, kNoValue);
        SetOperandValueWide(mir->ssa_rep->defs[0], res);
      }
      break;

    case Instruction::FLOAT_TO_DOUBLE:
    case Instruction::FLOAT_TO_LONG:
    case Instruction::INT_TO_DOUBLE:
    case Instruction::INT_TO_LONG: {
        // wide res = op + 1 operand
        uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
        res = gvn_->LookupValue(opcode, operand1, kNoValue, kNoValue);
        SetOperandValueWide(mir->ssa_rep->defs[0], res);
      }
      break;

    case Instruction::CMPL_DOUBLE:
    case Instruction::CMPG_DOUBLE:
    case Instruction::CMP_LONG: {
        // res = op + 2 wide operands
        uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
        uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]);
        res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
        SetOperandValue(mir->ssa_rep->defs[0], res);
      }
      break;

    case Instruction::DIV_INT:
    case Instruction::DIV_INT_2ADDR:
    case Instruction::REM_INT:
    case Instruction::REM_INT_2ADDR:
      HandleDivZeroCheck(mir, GetOperandValue(mir->ssa_rep->uses[1]));
      FALLTHROUGH_INTENDED;

    case Instruction::CMPG_FLOAT:
    case Instruction::CMPL_FLOAT:
    case Instruction::ADD_INT:
    case Instruction::ADD_INT_2ADDR:
    case Instruction::MUL_INT:
    case Instruction::MUL_INT_2ADDR:
    case Instruction::AND_INT:
    case Instruction::AND_INT_2ADDR:
    case Instruction::OR_INT:
    case Instruction::OR_INT_2ADDR:
    case Instruction::XOR_INT:
    case Instruction::XOR_INT_2ADDR:
    case Instruction::SUB_INT:
    case Instruction::SUB_INT_2ADDR:
    case Instruction::SHL_INT:
    case Instruction::SHL_INT_2ADDR:
    case Instruction::SHR_INT:
    case Instruction::SHR_INT_2ADDR:
    case Instruction::USHR_INT:
    case Instruction::USHR_INT_2ADDR: {
        // res = op + 2 operands
        uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
        uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[1]);
        res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
        SetOperandValue(mir->ssa_rep->defs[0], res);
      }
      break;

    case Instruction::DIV_LONG:
    case Instruction::REM_LONG:
    case Instruction::DIV_LONG_2ADDR:
    case Instruction::REM_LONG_2ADDR:
      HandleDivZeroCheck(mir, GetOperandValueWide(mir->ssa_rep->uses[2]));
      FALLTHROUGH_INTENDED;

    case Instruction::ADD_LONG:
    case Instruction::SUB_LONG:
    case Instruction::MUL_LONG:
    case Instruction::AND_LONG:
    case Instruction::OR_LONG:
    case Instruction::XOR_LONG:
    case Instruction::ADD_LONG_2ADDR:
    case Instruction::SUB_LONG_2ADDR:
    case Instruction::MUL_LONG_2ADDR:
    case Instruction::AND_LONG_2ADDR:
    case Instruction::OR_LONG_2ADDR:
    case Instruction::XOR_LONG_2ADDR:
    case Instruction::ADD_DOUBLE:
    case Instruction::SUB_DOUBLE:
    case Instruction::MUL_DOUBLE:
    case Instruction::DIV_DOUBLE:
    case Instruction::REM_DOUBLE:
    case Instruction::ADD_DOUBLE_2ADDR:
    case Instruction::SUB_DOUBLE_2ADDR:
    case Instruction::MUL_DOUBLE_2ADDR:
    case Instruction::DIV_DOUBLE_2ADDR:
    case Instruction::REM_DOUBLE_2ADDR: {
        // wide res = op + 2 wide operands
        uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
        uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]);
        res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
        SetOperandValueWide(mir->ssa_rep->defs[0], res);
      }
      break;

    case Instruction::SHL_LONG:
    case Instruction::SHR_LONG:
    case Instruction::USHR_LONG:
    case Instruction::SHL_LONG_2ADDR:
    case Instruction::SHR_LONG_2ADDR:
    case Instruction::USHR_LONG_2ADDR: {
        // wide res = op + 1 wide operand + 1 operand
        uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
        uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[2]);
        res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
        SetOperandValueWide(mir->ssa_rep->defs[0], res);
      }
      break;

    case Instruction::ADD_FLOAT:
    case Instruction::SUB_FLOAT:
    case Instruction::MUL_FLOAT:
    case Instruction::DIV_FLOAT:
    case Instruction::REM_FLOAT:
    case Instruction::ADD_FLOAT_2ADDR:
    case Instruction::SUB_FLOAT_2ADDR:
    case Instruction::MUL_FLOAT_2ADDR:
    case Instruction::DIV_FLOAT_2ADDR:
    case Instruction::REM_FLOAT_2ADDR: {
        // res = op + 2 operands
        uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
        uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[1]);
        res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
        SetOperandValue(mir->ssa_rep->defs[0], res);
      }
      break;

    case Instruction::RSUB_INT:
    case Instruction::ADD_INT_LIT16:
    case Instruction::MUL_INT_LIT16:
    case Instruction::DIV_INT_LIT16:
    case Instruction::REM_INT_LIT16:
    case Instruction::AND_INT_LIT16:
    case Instruction::OR_INT_LIT16:
    case Instruction::XOR_INT_LIT16:
    case Instruction::ADD_INT_LIT8:
    case Instruction::RSUB_INT_LIT8:
    case Instruction::MUL_INT_LIT8:
    case Instruction::DIV_INT_LIT8:
    case Instruction::REM_INT_LIT8:
    case Instruction::AND_INT_LIT8:
    case Instruction::OR_INT_LIT8:
    case Instruction::XOR_INT_LIT8:
    case Instruction::SHL_INT_LIT8:
    case Instruction::SHR_INT_LIT8:
    case Instruction::USHR_INT_LIT8: {
        // Same as res = op + 2 operands, except use vC as operand 2
        uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
        uint16_t operand2 = gvn_->LookupValue(Instruction::CONST, mir->dalvikInsn.vC, 0, 0);
        res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
        SetOperandValue(mir->ssa_rep->defs[0], res);
      }
      break;

    case Instruction::AGET_OBJECT:
    case Instruction::AGET:
    case Instruction::AGET_WIDE:
    case Instruction::AGET_BOOLEAN:
    case Instruction::AGET_BYTE:
    case Instruction::AGET_CHAR:
    case Instruction::AGET_SHORT:
      res = HandleAGet(mir, opcode);
      break;

    case Instruction::APUT_OBJECT:
      HandlePutObject(mir);
      FALLTHROUGH_INTENDED;
    case Instruction::APUT:
    case Instruction::APUT_WIDE:
    case Instruction::APUT_BYTE:
    case Instruction::APUT_BOOLEAN:
    case Instruction::APUT_SHORT:
    case Instruction::APUT_CHAR:
      HandleAPut(mir, opcode);
      break;

    case Instruction::IGET_OBJECT:
    case Instruction::IGET:
    case Instruction::IGET_WIDE:
    case Instruction::IGET_BOOLEAN:
    case Instruction::IGET_BYTE:
    case Instruction::IGET_CHAR:
    case Instruction::IGET_SHORT:
      res = HandleIGet(mir, opcode);
      break;

    case Instruction::IPUT_OBJECT:
      HandlePutObject(mir);
      FALLTHROUGH_INTENDED;
    case Instruction::IPUT:
    case Instruction::IPUT_WIDE:
    case Instruction::IPUT_BOOLEAN:
    case Instruction::IPUT_BYTE:
    case Instruction::IPUT_CHAR:
    case Instruction::IPUT_SHORT:
      HandleIPut(mir, opcode);
      break;

    case Instruction::SGET_OBJECT:
    case Instruction::SGET:
    case Instruction::SGET_WIDE:
    case Instruction::SGET_BOOLEAN:
    case Instruction::SGET_BYTE:
    case Instruction::SGET_CHAR:
    case Instruction::SGET_SHORT:
      res = HandleSGet(mir, opcode);
      break;

    case Instruction::SPUT_OBJECT:
      HandlePutObject(mir);
      FALLTHROUGH_INTENDED;
    case Instruction::SPUT:
    case Instruction::SPUT_WIDE:
    case Instruction::SPUT_BOOLEAN:
    case Instruction::SPUT_BYTE:
    case Instruction::SPUT_CHAR:
    case Instruction::SPUT_SHORT:
      HandleSPut(mir, opcode);
      break;
  }
  return res;
}

uint16_t LocalValueNumbering::GetEndingVregValueNumberImpl(int v_reg, bool wide) const {
  const BasicBlock* bb = gvn_->GetBasicBlock(Id());
  DCHECK(bb != nullptr);
  int s_reg = bb->data_flow_info->vreg_to_ssa_map_exit[v_reg];
  if (s_reg == INVALID_SREG) {
    return kNoValue;
  }
  if (gvn_->GetMirGraph()->GetRegLocation(s_reg).wide != wide) {
    return kNoValue;
  }
  if (wide) {
    int high_s_reg = bb->data_flow_info->vreg_to_ssa_map_exit[v_reg + 1];
    if (high_s_reg != s_reg + 1) {
      return kNoValue;  // High word has been overwritten.
    }
    return GetSregValueWide(s_reg);
  } else {
    return GetSregValue(s_reg);
  }
}

uint16_t LocalValueNumbering::GetStartingVregValueNumberImpl(int v_reg, bool wide) const {
  DCHECK_EQ(gvn_->mode_, GlobalValueNumbering::kModeGvnPostProcessing);
  DCHECK(gvn_->CanModify());
  const BasicBlock* bb = gvn_->GetBasicBlock(Id());
  DCHECK(bb != nullptr);
  DCHECK_NE(bb->predecessors.size(), 0u);
  if (bb->predecessors.size() == 1u) {
    return gvn_->GetLvn(bb->predecessors[0])->GetEndingVregValueNumberImpl(v_reg, wide);
  }
  merge_names_.clear();
  uint16_t value_name = kNoValue;
  bool same_values = true;
  for (BasicBlockId pred_id : bb->predecessors) {
    value_name = gvn_->GetLvn(pred_id)->GetEndingVregValueNumberImpl(v_reg, wide);
    if (value_name == kNoValue) {
      return kNoValue;
    }
    same_values = same_values && (merge_names_.empty() || value_name == merge_names_.back());
    merge_names_.push_back(value_name);
  }
  if (same_values) {
    // value_name already contains the result.
  } else {
    auto lb = merge_map_.lower_bound(merge_names_);
    if (lb != merge_map_.end() && !merge_map_.key_comp()(merge_names_, lb->first)) {
      value_name = lb->second;
    } else {
      value_name = kNoValue;  // We never assigned a value name to this set of merged names.
    }
  }
  return value_name;
}

}    // namespace art
