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

#include "base/bit_vector-inl.h"
#include "compiler_ir.h"
#include "dataflow_iterator-inl.h"
#include "dex_flags.h"
#include "dex_file-inl.h"
#include "driver/dex_compilation_unit.h"
#include "mir_field_info.h"
#include "mir_graph.h"
#include "mir_method_info.h"

namespace art {

inline TypeInference::Type TypeInference::Type::ArrayType(uint32_t array_depth, Type nested_type) {
  DCHECK_NE(array_depth, 0u);
  return Type(kFlagNarrow | kFlagRef | kFlagLowWord | (array_depth << kBitArrayDepthStart) |
              ((nested_type.raw_bits_ & kMaskWideAndType) << kArrayTypeShift));
}

inline TypeInference::Type TypeInference::Type::ArrayTypeFromComponent(Type component_type) {
  if (component_type.ArrayDepth() == 0u) {
    return ArrayType(1u, component_type);
  }
  if (UNLIKELY(component_type.ArrayDepth() == kMaxArrayDepth)) {
    return component_type;
  }
  return Type(component_type.raw_bits_ + (1u << kBitArrayDepthStart));  // array_depth + 1u;
}

TypeInference::Type TypeInference::Type::ShortyType(char shorty) {
  switch (shorty) {
    case 'L':
      return Type(kFlagLowWord | kFlagNarrow | kFlagRef);
    case 'D':
      return Type(kFlagLowWord | kFlagWide | kFlagFp);
    case 'J':
      return Type(kFlagLowWord | kFlagWide | kFlagCore);
    case 'F':
      return Type(kFlagLowWord | kFlagNarrow | kFlagFp);
    default:
      DCHECK(shorty == 'I' || shorty == 'S' || shorty == 'C' || shorty == 'B' || shorty == 'Z');
      return Type(kFlagLowWord | kFlagNarrow | kFlagCore);
  }
}

TypeInference::Type TypeInference::Type::DexType(const DexFile* dex_file, uint32_t type_idx) {
  const char* desc = dex_file->GetTypeDescriptor(dex_file->GetTypeId(type_idx));
  if (UNLIKELY(desc[0] == 'V')) {
    return Unknown();
  } else if (UNLIKELY(desc[0] == '[')) {
    size_t array_depth = 0u;
    while (*desc == '[') {
      ++array_depth;
      ++desc;
    }
    if (UNLIKELY(array_depth > kMaxArrayDepth)) {
      LOG(WARNING) << "Array depth exceeds " << kMaxArrayDepth << ": " << array_depth
          << " in dex file " << dex_file->GetLocation() << " type index " << type_idx;
      array_depth = kMaxArrayDepth;
    }
    Type shorty_result = Type::ShortyType(desc[0]);
    return ArrayType(array_depth, shorty_result);
  } else {
    return ShortyType(desc[0]);
  }
}

bool TypeInference::Type::MergeArrayConflict(Type src_type) {
  DCHECK(Ref());
  DCHECK_NE(ArrayDepth(), src_type.ArrayDepth());
  DCHECK_GE(std::min(ArrayDepth(), src_type.ArrayDepth()), 1u);
  bool size_conflict =
      (ArrayDepth() == 1u && (raw_bits_ & kFlagArrayWide) != 0u) ||
      (src_type.ArrayDepth() == 1u && (src_type.raw_bits_ & kFlagArrayWide) != 0u);
  // Mark all three array type bits so that merging any other type bits will not change this type.
  return Copy(Type((raw_bits_ & kMaskNonArray) |
                   (1u << kBitArrayDepthStart) | kFlagArrayCore | kFlagArrayRef | kFlagArrayFp |
                   kFlagArrayNarrow | (size_conflict ? kFlagArrayWide : 0u)));
}

bool TypeInference::Type::MergeStrong(Type src_type) {
  bool changed = MergeNonArrayFlags(src_type);
  if (src_type.ArrayDepth() != 0u) {
    if (ArrayDepth() == 0u) {
      DCHECK_EQ(raw_bits_ & ~kMaskNonArray, 0u);
      DCHECK_NE(src_type.raw_bits_ & kFlagRef, 0u);
      raw_bits_ |= src_type.raw_bits_ & (~kMaskNonArray | kFlagRef);
      changed = true;
    } else if (ArrayDepth() == src_type.ArrayDepth()) {
      changed |= MergeBits(src_type, kMaskArrayWideAndType);
    } else if (src_type.ArrayDepth() == 1u &&
        (((src_type.raw_bits_ ^ UnknownArrayType().raw_bits_) & kMaskArrayWideAndType) == 0u ||
         ((src_type.raw_bits_ ^ ObjectArrayType().raw_bits_) & kMaskArrayWideAndType) == 0u)) {
      // Source type is [L or [? but current type is at least [[, preserve it.
    } else if (ArrayDepth() == 1u &&
        (((raw_bits_ ^ UnknownArrayType().raw_bits_) & kMaskArrayWideAndType) == 0u ||
         ((raw_bits_ ^ ObjectArrayType().raw_bits_) & kMaskArrayWideAndType) == 0u)) {
      // Overwrite [? or [L with the source array type which is at least [[.
      raw_bits_ = (raw_bits_ & kMaskNonArray) | (src_type.raw_bits_ & ~kMaskNonArray);
      changed = true;
    } else {
      // Mark the array value type with conflict - both ref and fp.
      changed |= MergeArrayConflict(src_type);
    }
  }
  return changed;
}

bool TypeInference::Type::MergeWeak(Type src_type) {
  bool changed = MergeNonArrayFlags(src_type);
  if (src_type.ArrayDepth() != 0u && src_type.NonNull()) {
    DCHECK_NE(src_type.ArrayDepth(), 0u);
    if (ArrayDepth() == 0u) {
      DCHECK_EQ(raw_bits_ & ~kMaskNonArray, 0u);
      // Preserve current type.
    } else if (ArrayDepth() == src_type.ArrayDepth()) {
      changed |= MergeBits(src_type, kMaskArrayWideAndType);
    } else if (src_type.ArrayDepth() == 1u &&
        (((src_type.raw_bits_ ^ UnknownArrayType().raw_bits_) & kMaskArrayWideAndType) == 0u ||
         ((src_type.raw_bits_ ^ ObjectArrayType().raw_bits_) & kMaskArrayWideAndType) == 0u)) {
      // Source type is [L or [? but current type is at least [[, preserve it.
    } else if (ArrayDepth() == 1u &&
        (((raw_bits_ ^ UnknownArrayType().raw_bits_) & kMaskArrayWideAndType) == 0u ||
         ((raw_bits_ ^ ObjectArrayType().raw_bits_) & kMaskArrayWideAndType) == 0u)) {
      // We have [? or [L. If it's [?, upgrade to [L as the source array type is at least [[.
      changed |= MergeBits(ObjectArrayType(), kMaskArrayWideAndType);
    } else {
      // Mark the array value type with conflict - both ref and fp.
      changed |= MergeArrayConflict(src_type);
    }
  }
  return changed;
}

TypeInference::CheckCastData::CheckCastData(MIRGraph* mir_graph, ScopedArenaAllocator* alloc)
    : mir_graph_(mir_graph),
      alloc_(alloc),
      num_blocks_(mir_graph->GetNumBlocks()),
      num_sregs_(mir_graph->GetNumSSARegs()),
      check_cast_map_(std::less<MIR*>(), alloc->Adapter()),
      split_sreg_data_(std::less<int32_t>(), alloc->Adapter()) {
}

void TypeInference::CheckCastData::AddCheckCast(MIR* check_cast, Type type) {
  DCHECK_EQ(check_cast->dalvikInsn.opcode, Instruction::CHECK_CAST);
  type.CheckPureRef();
  int32_t extra_s_reg = static_cast<int32_t>(num_sregs_);
  num_sregs_ += 1;
  check_cast_map_.Put(check_cast, CheckCastMapValue{extra_s_reg, type});  // NOLINT
  int32_t s_reg = check_cast->ssa_rep->uses[0];
  auto lb = split_sreg_data_.lower_bound(s_reg);
  if (lb == split_sreg_data_.end() || split_sreg_data_.key_comp()(s_reg, lb->first)) {
    SplitSRegData split_s_reg_data = {
        0,
        alloc_->AllocArray<int32_t>(num_blocks_, kArenaAllocMisc),
        alloc_->AllocArray<int32_t>(num_blocks_, kArenaAllocMisc),
        new (alloc_) ArenaBitVector(alloc_, num_blocks_, false)
    };
    std::fill_n(split_s_reg_data.starting_mod_s_reg, num_blocks_, INVALID_SREG);
    std::fill_n(split_s_reg_data.ending_mod_s_reg, num_blocks_, INVALID_SREG);
    split_s_reg_data.def_phi_blocks_->ClearAllBits();
    BasicBlock* def_bb = FindDefBlock(check_cast);
    split_s_reg_data.ending_mod_s_reg[def_bb->id] = s_reg;
    split_s_reg_data.def_phi_blocks_->SetBit(def_bb->id);
    lb = split_sreg_data_.PutBefore(lb, s_reg, split_s_reg_data);
  }
  lb->second.ending_mod_s_reg[check_cast->bb] = extra_s_reg;
  lb->second.def_phi_blocks_->SetBit(check_cast->bb);
}

void TypeInference::CheckCastData::AddPseudoPhis() {
  // Look for pseudo-phis where a split SSA reg merges with a differently typed version
  // and initialize all starting_mod_s_reg.
  DCHECK(!split_sreg_data_.empty());
  ArenaBitVector* phi_blocks = new (alloc_) ArenaBitVector(alloc_, num_blocks_, false);

  for (auto& entry : split_sreg_data_) {
    SplitSRegData& data = entry.second;

    // Find pseudo-phi nodes.
    phi_blocks->ClearAllBits();
    ArenaBitVector* input_blocks = data.def_phi_blocks_;
    do {
      for (uint32_t idx : input_blocks->Indexes()) {
        BasicBlock* def_bb = mir_graph_->GetBasicBlock(idx);
        if (def_bb->dom_frontier != nullptr) {
          phi_blocks->Union(def_bb->dom_frontier);
        }
      }
    } while (input_blocks->Union(phi_blocks));

    // Find live pseudo-phis. Make sure they're merging the same SSA reg.
    data.def_phi_blocks_->ClearAllBits();
    int32_t s_reg = entry.first;
    int v_reg = mir_graph_->SRegToVReg(s_reg);
    for (uint32_t phi_bb_id : phi_blocks->Indexes()) {
      BasicBlock* phi_bb = mir_graph_->GetBasicBlock(phi_bb_id);
      DCHECK(phi_bb != nullptr);
      DCHECK(phi_bb->data_flow_info != nullptr);
      DCHECK(phi_bb->data_flow_info->live_in_v != nullptr);
      if (IsSRegLiveAtStart(phi_bb, v_reg, s_reg)) {
        int32_t extra_s_reg = static_cast<int32_t>(num_sregs_);
        num_sregs_ += 1;
        data.starting_mod_s_reg[phi_bb_id] = extra_s_reg;
        data.def_phi_blocks_->SetBit(phi_bb_id);
      }
    }

    // SSA rename for s_reg.
    TopologicalSortIterator iter(mir_graph_);
    for (BasicBlock* bb = iter.Next(); bb != nullptr; bb = iter.Next()) {
      if (bb->data_flow_info == nullptr || bb->block_type == kEntryBlock) {
        continue;
      }
      BasicBlockId bb_id = bb->id;
      if (data.def_phi_blocks_->IsBitSet(bb_id)) {
        DCHECK_NE(data.starting_mod_s_reg[bb_id], INVALID_SREG);
      } else {
        DCHECK_EQ(data.starting_mod_s_reg[bb_id], INVALID_SREG);
        if (IsSRegLiveAtStart(bb, v_reg, s_reg)) {
          // The earliest predecessor must have been processed already.
          BasicBlock* pred_bb = FindTopologicallyEarliestPredecessor(bb);
          int32_t mod_s_reg = data.ending_mod_s_reg[pred_bb->id];
          data.starting_mod_s_reg[bb_id] = (mod_s_reg != INVALID_SREG) ? mod_s_reg : s_reg;
        } else if (data.ending_mod_s_reg[bb_id] != INVALID_SREG) {
          // Start the original defining block with s_reg.
          data.starting_mod_s_reg[bb_id] = s_reg;
        }
      }
      if (data.ending_mod_s_reg[bb_id] == INVALID_SREG) {
        // If the block doesn't define the modified SSA reg, it propagates the starting type.
        data.ending_mod_s_reg[bb_id] = data.starting_mod_s_reg[bb_id];
      }
    }
  }
}

void TypeInference::CheckCastData::InitializeCheckCastSRegs(Type* sregs) const {
  for (const auto& entry : check_cast_map_) {
    DCHECK_LT(static_cast<size_t>(entry.second.modified_s_reg), num_sregs_);
    sregs[entry.second.modified_s_reg] = entry.second.type.AsNonNull();
  }
}

void TypeInference::CheckCastData::MergeCheckCastConflicts(Type* sregs) const {
  for (const auto& entry : check_cast_map_) {
    DCHECK_LT(static_cast<size_t>(entry.second.modified_s_reg), num_sregs_);
    sregs[entry.first->ssa_rep->uses[0]].MergeNonArrayFlags(
        sregs[entry.second.modified_s_reg].AsNull());
  }
}

void TypeInference::CheckCastData::MarkPseudoPhiBlocks(uint64_t* bb_df_attrs) const {
  for (auto& entry : split_sreg_data_) {
    for (uint32_t bb_id : entry.second.def_phi_blocks_->Indexes()) {
      bb_df_attrs[bb_id] |= DF_NULL_TRANSFER_N;
    }
  }
}

void TypeInference::CheckCastData::Start(BasicBlock* bb) {
  for (auto& entry : split_sreg_data_) {
    entry.second.current_mod_s_reg = entry.second.starting_mod_s_reg[bb->id];
  }
}

bool TypeInference::CheckCastData::ProcessPseudoPhis(BasicBlock* bb, Type* sregs) {
  bool changed = false;
  for (auto& entry : split_sreg_data_) {
    DCHECK_EQ(entry.second.current_mod_s_reg, entry.second.starting_mod_s_reg[bb->id]);
    if (entry.second.def_phi_blocks_->IsBitSet(bb->id)) {
      int32_t* ending_mod_s_reg = entry.second.ending_mod_s_reg;
      Type merged_type = sregs[entry.second.current_mod_s_reg];
      for (BasicBlockId pred_id : bb->predecessors) {
        DCHECK_LT(static_cast<size_t>(ending_mod_s_reg[pred_id]), num_sregs_);
        merged_type.MergeWeak(sregs[ending_mod_s_reg[pred_id]]);
      }
      if (UNLIKELY(!merged_type.IsDefined())) {
        // This can happen during an initial merge of a loop head if the original def is
        // actually an untyped null. (All other definitions are typed using the check-cast.)
      } else if (merged_type.Wide()) {
        // Ignore the pseudo-phi, just remember that there's a size mismatch.
        sregs[entry.second.current_mod_s_reg].MarkSizeConflict();
      } else {
        DCHECK(merged_type.Narrow() && merged_type.LowWord() && !merged_type.HighWord());
        // Propagate both down (fully) and up (without the "non-null" flag).
        changed |= sregs[entry.second.current_mod_s_reg].Copy(merged_type);
        merged_type = merged_type.AsNull();
        for (BasicBlockId pred_id : bb->predecessors) {
          DCHECK_LT(static_cast<size_t>(ending_mod_s_reg[pred_id]), num_sregs_);
          sregs[ending_mod_s_reg[pred_id]].MergeStrong(merged_type);
        }
      }
    }
  }
  return changed;
}

void TypeInference::CheckCastData::ProcessCheckCast(MIR* mir) {
  auto mir_it = check_cast_map_.find(mir);
  DCHECK(mir_it != check_cast_map_.end());
  auto sreg_it = split_sreg_data_.find(mir->ssa_rep->uses[0]);
  DCHECK(sreg_it != split_sreg_data_.end());
  sreg_it->second.current_mod_s_reg = mir_it->second.modified_s_reg;
}

TypeInference::SplitSRegData* TypeInference::CheckCastData::GetSplitSRegData(int32_t s_reg) {
  auto it = split_sreg_data_.find(s_reg);
  return (it == split_sreg_data_.end()) ? nullptr : &it->second;
}

BasicBlock* TypeInference::CheckCastData::FindDefBlock(MIR* check_cast) {
  // Find the initial definition of the SSA reg used by the check-cast.
  DCHECK_EQ(check_cast->dalvikInsn.opcode, Instruction::CHECK_CAST);
  int32_t s_reg = check_cast->ssa_rep->uses[0];
  if (mir_graph_->IsInVReg(s_reg)) {
    return mir_graph_->GetEntryBlock();
  }
  int v_reg = mir_graph_->SRegToVReg(s_reg);
  BasicBlock* bb = mir_graph_->GetBasicBlock(check_cast->bb);
  DCHECK(bb != nullptr);
  while (true) {
    // Find the earliest predecessor in the topological sort order to ensure we don't
    // go in a loop.
    BasicBlock* pred_bb = FindTopologicallyEarliestPredecessor(bb);
    DCHECK(pred_bb != nullptr);
    DCHECK(pred_bb->data_flow_info != nullptr);
    DCHECK(pred_bb->data_flow_info->vreg_to_ssa_map_exit != nullptr);
    if (pred_bb->data_flow_info->vreg_to_ssa_map_exit[v_reg] != s_reg) {
      // The s_reg was not valid at the end of pred_bb, so it must have been defined in bb.
      return bb;
    }
    bb = pred_bb;
  }
}

BasicBlock* TypeInference::CheckCastData::FindTopologicallyEarliestPredecessor(BasicBlock* bb) {
  DCHECK(!bb->predecessors.empty());
  const auto& indexes = mir_graph_->GetTopologicalSortOrderIndexes();
  DCHECK_LT(bb->id, indexes.size());
  size_t best_idx = indexes[bb->id];
  BasicBlockId best_id = NullBasicBlockId;
  for (BasicBlockId pred_id : bb->predecessors) {
    DCHECK_LT(pred_id, indexes.size());
    if (best_idx > indexes[pred_id]) {
      best_idx = indexes[pred_id];
      best_id = pred_id;
    }
  }
  // There must be at least one predecessor earlier than the bb.
  DCHECK_LT(best_idx, indexes[bb->id]);
  return mir_graph_->GetBasicBlock(best_id);
}

bool TypeInference::CheckCastData::IsSRegLiveAtStart(BasicBlock* bb, int v_reg, int32_t s_reg) {
  DCHECK_EQ(v_reg, mir_graph_->SRegToVReg(s_reg));
  DCHECK(bb != nullptr);
  DCHECK(bb->data_flow_info != nullptr);
  DCHECK(bb->data_flow_info->live_in_v != nullptr);
  if (!bb->data_flow_info->live_in_v->IsBitSet(v_reg)) {
    return false;
  }
  for (BasicBlockId pred_id : bb->predecessors) {
    BasicBlock* pred_bb = mir_graph_->GetBasicBlock(pred_id);
    DCHECK(pred_bb != nullptr);
    DCHECK(pred_bb->data_flow_info != nullptr);
    DCHECK(pred_bb->data_flow_info->vreg_to_ssa_map_exit != nullptr);
    if (pred_bb->data_flow_info->vreg_to_ssa_map_exit[v_reg] != s_reg) {
      return false;
    }
  }
  return true;
}

TypeInference::TypeInference(MIRGraph* mir_graph, ScopedArenaAllocator* alloc)
    : mir_graph_(mir_graph),
      cu_(mir_graph->GetCurrentDexCompilationUnit()->GetCompilationUnit()),
      check_cast_data_(!mir_graph->HasCheckCast() ? nullptr :
          InitializeCheckCastData(mir_graph, alloc)),
      num_sregs_(
          check_cast_data_ != nullptr ? check_cast_data_->NumSRegs() : mir_graph->GetNumSSARegs()),
      ifields_(mir_graph->GetIFieldLoweringInfoCount() == 0u ? nullptr :
          PrepareIFieldTypes(cu_->dex_file, mir_graph, alloc)),
      sfields_(mir_graph->GetSFieldLoweringInfoCount() == 0u ? nullptr :
          PrepareSFieldTypes(cu_->dex_file, mir_graph, alloc)),
      signatures_(mir_graph->GetMethodLoweringInfoCount() == 0u ? nullptr :
          PrepareSignatures(cu_->dex_file, mir_graph, alloc)),
      current_method_signature_(
          Signature(cu_->dex_file, cu_->method_idx, (cu_->access_flags & kAccStatic) != 0, alloc)),
      sregs_(alloc->AllocArray<Type>(num_sregs_, kArenaAllocMisc)),
      bb_df_attrs_(alloc->AllocArray<uint64_t>(mir_graph->GetNumBlocks(), kArenaAllocDFInfo)) {
  InitializeSRegs();
}

bool TypeInference::Apply(BasicBlock* bb) {
  bool changed = false;
  uint64_t bb_df_attrs = bb_df_attrs_[bb->id];
  if (bb_df_attrs != 0u) {
    if (UNLIKELY(check_cast_data_ != nullptr)) {
      check_cast_data_->Start(bb);
      if (bb_df_attrs & DF_NULL_TRANSFER_N) {
        changed |= check_cast_data_->ProcessPseudoPhis(bb, sregs_);
      }
    }
    MIR* mir = bb->first_mir_insn;
    MIR* main_mirs_end = ((bb_df_attrs & DF_SAME_TYPE_AB) != 0u) ? bb->last_mir_insn : nullptr;
    for (; mir != main_mirs_end && static_cast<int>(mir->dalvikInsn.opcode) == kMirOpPhi;
        mir = mir->next) {
      // Special-case handling for Phi comes first because we have 2 Phis instead of a wide one.
      // At least one input must have been previously processed. Look for the first
      // occurrence of a high_word or low_word flag to determine the type.
      size_t num_uses = mir->ssa_rep->num_uses;
      const int32_t* uses = mir->ssa_rep->uses;
      const int32_t* defs = mir->ssa_rep->defs;
      DCHECK_EQ(bb->predecessors.size(), num_uses);
      Type merged_type = sregs_[defs[0]];
      for (size_t pred_idx = 0; pred_idx != num_uses; ++pred_idx) {
        int32_t input_mod_s_reg = PhiInputModifiedSReg(uses[pred_idx], bb, pred_idx);
        merged_type.MergeWeak(sregs_[input_mod_s_reg]);
      }
      if (UNLIKELY(!merged_type.IsDefined())) {
        // No change
      } else if (merged_type.HighWord()) {
        // Ignore the high word phi, just remember if there's a size mismatch.
        if (UNLIKELY(merged_type.LowWord())) {
          sregs_[defs[0]].MarkSizeConflict();
        }
      } else {
        // Propagate both down (fully) and up (without the "non-null" flag).
        changed |= sregs_[defs[0]].Copy(merged_type);
        merged_type = merged_type.AsNull();
        for (size_t pred_idx = 0; pred_idx != num_uses; ++pred_idx) {
          int32_t input_mod_s_reg = PhiInputModifiedSReg(uses[pred_idx], bb, pred_idx);
          changed |= UpdateSRegFromLowWordType(input_mod_s_reg, merged_type);
        }
      }
    }

    // Propagate types with MOVEs and AGETs, process CHECK_CASTs for modified SSA reg tracking.
    for (; mir != main_mirs_end; mir = mir->next) {
      uint64_t attrs = MIRGraph::GetDataFlowAttributes(mir);
      size_t num_uses = mir->ssa_rep->num_uses;
      const int32_t* uses = mir->ssa_rep->uses;
      const int32_t* defs = mir->ssa_rep->defs;

      // Special handling for moves. Propagate type both ways.
      if ((attrs & DF_IS_MOVE) != 0) {
        int32_t used_mod_s_reg = ModifiedSReg(uses[0]);
        int32_t defd_mod_s_reg = defs[0];

        // The "non-null" flag is propagated only downwards from actual definitions and it's
        // not initially marked for moves, so used sreg must be marked before defined sreg.
        // The only exception is an inlined move where we know the type from the original invoke.
        DCHECK(sregs_[used_mod_s_reg].NonNull() || !sregs_[defd_mod_s_reg].NonNull() ||
               (mir->optimization_flags & MIR_CALLEE) != 0);
        changed |= UpdateSRegFromLowWordType(used_mod_s_reg, sregs_[defd_mod_s_reg].AsNull());

        // The value is the same, so either both registers are null or no register is.
        // In any case we can safely propagate the array type down.
        changed |= UpdateSRegFromLowWordType(defd_mod_s_reg, sregs_[used_mod_s_reg]);
        if (UNLIKELY((attrs & DF_REF_A) == 0 && sregs_[used_mod_s_reg].Ref())) {
          // Mark type conflict: move instead of move-object.
          sregs_[used_mod_s_reg].MarkTypeConflict();
        }
        continue;
      }

      // Handle AGET/APUT.
      if ((attrs & DF_HAS_RANGE_CHKS) != 0) {
        int32_t base_mod_s_reg = ModifiedSReg(uses[num_uses - 2u]);
        int32_t mod_s_reg = (attrs & DF_DA) != 0 ? defs[0] : ModifiedSReg(uses[0]);
        DCHECK_NE(sregs_[base_mod_s_reg].ArrayDepth(), 0u);
        if (!sregs_[base_mod_s_reg].NonNull()) {
          // If the base is null, don't propagate anything. All that we could determine
          // has already been merged in the previous stage.
        } else {
          changed |= UpdateSRegFromLowWordType(mod_s_reg, sregs_[base_mod_s_reg].ComponentType());
          Type array_type = Type::ArrayTypeFromComponent(sregs_[mod_s_reg]);
          if ((attrs & DF_DA) != 0) {
            changed |= sregs_[base_mod_s_reg].MergeStrong(array_type);
          } else {
            changed |= sregs_[base_mod_s_reg].MergeWeak(array_type);
          }
        }
        if (UNLIKELY((attrs & DF_REF_A) == 0 && sregs_[mod_s_reg].Ref())) {
          // Mark type conflict: aget/aput instead of aget/aput-object.
          sregs_[mod_s_reg].MarkTypeConflict();
        }
        continue;
      }

      // Special-case handling for check-cast to advance modified SSA reg.
      if (UNLIKELY((attrs & DF_CHK_CAST) != 0)) {
        DCHECK(check_cast_data_ != nullptr);
        check_cast_data_->ProcessCheckCast(mir);
      }
    }

    // Propagate types for IF_cc if present.
    if (mir != nullptr) {
      DCHECK(mir == bb->last_mir_insn);
      DCHECK(mir->next == nullptr);
      DCHECK_NE(MIRGraph::GetDataFlowAttributes(mir) & DF_SAME_TYPE_AB, 0u);
      DCHECK_EQ(mir->ssa_rep->num_uses, 2u);
      const int32_t* uses = mir->ssa_rep->uses;
      int32_t mod_s_reg0 = ModifiedSReg(uses[0]);
      int32_t mod_s_reg1 = ModifiedSReg(uses[1]);
      changed |= sregs_[mod_s_reg0].MergeWeak(sregs_[mod_s_reg1].AsNull());
      changed |= sregs_[mod_s_reg1].MergeWeak(sregs_[mod_s_reg0].AsNull());
    }
  }
  return changed;
}

void TypeInference::Finish() {
  if (UNLIKELY(check_cast_data_ != nullptr)) {
    check_cast_data_->MergeCheckCastConflicts(sregs_);
  }

  size_t num_sregs = mir_graph_->GetNumSSARegs();  // Without the extra SSA regs.
  for (size_t s_reg = 0; s_reg != num_sregs; ++s_reg) {
    if (sregs_[s_reg].SizeConflict()) {
      /*
       * The dex bytecode definition does not explicitly outlaw the definition of the same
       * virtual register to be used in both a 32-bit and 64-bit pair context.  However, dx
       * does not generate this pattern (at least recently).  Further, in the next revision of
       * dex, we will forbid this.  To support the few cases in the wild, detect this pattern
       * and punt to the interpreter.
       */
      LOG(WARNING) << PrettyMethod(cu_->method_idx, *cu_->dex_file)
                   << " has size conflict block for sreg " << s_reg
                   << ", punting to interpreter.";
      mir_graph_->SetPuntToInterpreter(true);
      return;
    }
  }

  size_t conflict_s_reg = 0;
  bool type_conflict = false;
  for (size_t s_reg = 0; s_reg != num_sregs; ++s_reg) {
    Type type = sregs_[s_reg];
    RegLocation* loc = &mir_graph_->reg_location_[s_reg];
    loc->wide = type.Wide();
    loc->defined = type.IsDefined();
    loc->fp = type.Fp();
    loc->core = type.Core();
    loc->ref = type.Ref();
    loc->high_word = type.HighWord();
    if (UNLIKELY(type.TypeConflict())) {
      type_conflict = true;
      conflict_s_reg = s_reg;
    }
  }

  if (type_conflict) {
    /*
     * We don't normally expect to see a Dalvik register definition used both as a
     * floating point and core value, though technically it could happen with constants.
     * Until we have proper typing, detect this situation and disable register promotion
     * (which relies on the distinction between core a fp usages).
     */
    LOG(WARNING) << PrettyMethod(cu_->method_idx, *cu_->dex_file)
                 << " has type conflict block for sreg " << conflict_s_reg
                 << ", disabling register promotion.";
    cu_->disable_opt |= (1 << kPromoteRegs);
  }
}

TypeInference::Type TypeInference::FieldType(const DexFile* dex_file, uint32_t field_idx) {
  uint32_t type_idx = dex_file->GetFieldId(field_idx).type_idx_;
  Type result = Type::DexType(dex_file, type_idx);
  return result;
}

TypeInference::Type* TypeInference::PrepareIFieldTypes(const DexFile* dex_file,
                                                       MIRGraph* mir_graph,
                                                       ScopedArenaAllocator* alloc) {
  size_t count = mir_graph->GetIFieldLoweringInfoCount();
  Type* ifields = alloc->AllocArray<Type>(count, kArenaAllocDFInfo);
  for (uint32_t i = 0u; i != count; ++i) {
    // NOTE: Quickened field accesses have invalid FieldIndex() but they are always resolved.
    const MirFieldInfo& info = mir_graph->GetIFieldLoweringInfo(i);
    const DexFile* current_dex_file = info.IsResolved() ? info.DeclaringDexFile() : dex_file;
    uint32_t field_idx = info.IsResolved() ? info.DeclaringFieldIndex() : info.FieldIndex();
    ifields[i] = FieldType(current_dex_file, field_idx);
    DCHECK_EQ(info.MemAccessType() == kDexMemAccessWide, ifields[i].Wide());
    DCHECK_EQ(info.MemAccessType() == kDexMemAccessObject, ifields[i].Ref());
  }
  return ifields;
}

TypeInference::Type* TypeInference::PrepareSFieldTypes(const DexFile* dex_file,
                                                       MIRGraph* mir_graph,
                                                       ScopedArenaAllocator* alloc) {
  size_t count = mir_graph->GetSFieldLoweringInfoCount();
  Type* sfields = alloc->AllocArray<Type>(count, kArenaAllocDFInfo);
  for (uint32_t i = 0u; i != count; ++i) {
    // FieldIndex() is always valid for static fields (no quickened instructions).
    sfields[i] = FieldType(dex_file, mir_graph->GetSFieldLoweringInfo(i).FieldIndex());
  }
  return sfields;
}

TypeInference::MethodSignature TypeInference::Signature(const DexFile* dex_file,
                                                        uint32_t method_idx,
                                                        bool is_static,
                                                        ScopedArenaAllocator* alloc) {
  const DexFile::MethodId& method_id = dex_file->GetMethodId(method_idx);
  const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id);
  Type return_type = Type::DexType(dex_file, proto_id.return_type_idx_);
  const DexFile::TypeList* type_list = dex_file->GetProtoParameters(proto_id);
  size_t this_size = (is_static ? 0u : 1u);
  size_t param_size = ((type_list != nullptr) ? type_list->Size() : 0u);
  size_t size = this_size + param_size;
  Type* param_types = (size != 0u) ? alloc->AllocArray<Type>(size, kArenaAllocDFInfo) : nullptr;
  if (!is_static) {
    param_types[0] = Type::DexType(dex_file, method_id.class_idx_);
  }
  for (size_t i = 0; i != param_size; ++i)  {
    uint32_t type_idx = type_list->GetTypeItem(i).type_idx_;
    param_types[this_size + i] = Type::DexType(dex_file, type_idx);
  }
  return MethodSignature{ return_type, size, param_types };  // NOLINT
}

TypeInference::MethodSignature* TypeInference::PrepareSignatures(const DexFile* dex_file,
                                                                 MIRGraph* mir_graph,
                                                                 ScopedArenaAllocator* alloc) {
  size_t count = mir_graph->GetMethodLoweringInfoCount();
  MethodSignature* signatures = alloc->AllocArray<MethodSignature>(count, kArenaAllocDFInfo);
  for (uint32_t i = 0u; i != count; ++i) {
    // NOTE: Quickened invokes have invalid MethodIndex() but they are always resolved.
    const MirMethodInfo& info = mir_graph->GetMethodLoweringInfo(i);
    uint32_t method_idx = info.IsResolved() ? info.DeclaringMethodIndex() : info.MethodIndex();
    const DexFile* current_dex_file = info.IsResolved() ? info.DeclaringDexFile() : dex_file;
    signatures[i] = Signature(current_dex_file, method_idx, info.IsStatic(), alloc);
  }
  return signatures;
}

TypeInference::CheckCastData* TypeInference::InitializeCheckCastData(MIRGraph* mir_graph,
                                                                     ScopedArenaAllocator* alloc) {
  if (!mir_graph->HasCheckCast()) {
    return nullptr;
  }

  CheckCastData* data = nullptr;
  const DexFile* dex_file = nullptr;
  PreOrderDfsIterator iter(mir_graph);
  for (BasicBlock* bb = iter.Next(); bb != nullptr; bb = iter.Next()) {
    for (MIR* mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) {
      if (mir->dalvikInsn.opcode == Instruction::CHECK_CAST) {
        if (data == nullptr) {
          data = new (alloc) CheckCastData(mir_graph, alloc);
          dex_file = mir_graph->GetCurrentDexCompilationUnit()->GetCompilationUnit()->dex_file;
        }
        Type type = Type::DexType(dex_file, mir->dalvikInsn.vB);
        data->AddCheckCast(mir, type);
      }
    }
  }
  if (data != nullptr) {
    data->AddPseudoPhis();
  }
  return data;
}

void TypeInference::InitializeSRegs() {
  std::fill_n(sregs_, num_sregs_, Type::Unknown());

  /* Treat ArtMethod* as a normal reference */
  sregs_[mir_graph_->GetMethodSReg()] = Type::NonArrayRefType();

  // Initialize parameter SSA regs at method entry.
  int32_t entry_param_s_reg = mir_graph_->GetFirstInVR();
  for (size_t i = 0, size = current_method_signature_.num_params; i != size; ++i)  {
    Type param_type = current_method_signature_.param_types[i].AsNonNull();
    sregs_[entry_param_s_reg] = param_type;
    entry_param_s_reg += param_type.Wide() ? 2 : 1;
  }
  DCHECK_EQ(static_cast<uint32_t>(entry_param_s_reg),
            mir_graph_->GetFirstInVR() + mir_graph_->GetNumOfInVRs());

  // Initialize check-cast types.
  if (UNLIKELY(check_cast_data_ != nullptr)) {
    check_cast_data_->InitializeCheckCastSRegs(sregs_);
  }

  // Initialize well-known SSA register definition types. Merge inferred types
  // upwards where a single merge is enough (INVOKE arguments and return type,
  // RETURN type, IPUT/SPUT source type).
  // NOTE: Using topological sort order to make sure the definition comes before
  // any upward merging. This allows simple assignment of the defined types
  // instead of MergeStrong().
  TopologicalSortIterator iter(mir_graph_);
  for (BasicBlock* bb = iter.Next(); bb != nullptr; bb = iter.Next()) {
    uint64_t bb_df_attrs = 0u;
    if (UNLIKELY(check_cast_data_ != nullptr)) {
      check_cast_data_->Start(bb);
    }
    // Ignore pseudo-phis, we're not setting types for SSA regs that depend on them in this pass.
    for (MIR* mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) {
      uint64_t attrs = MIRGraph::GetDataFlowAttributes(mir);
      bb_df_attrs |= attrs;

      const uint32_t num_uses = mir->ssa_rep->num_uses;
      const int32_t* uses = mir->ssa_rep->uses;
      const int32_t* defs = mir->ssa_rep->defs;

      uint16_t opcode = mir->dalvikInsn.opcode;
      switch (opcode) {
        case Instruction::CONST_4:
        case Instruction::CONST_16:
        case Instruction::CONST:
        case Instruction::CONST_HIGH16:
        case Instruction::CONST_WIDE_16:
        case Instruction::CONST_WIDE_32:
        case Instruction::CONST_WIDE:
        case Instruction::CONST_WIDE_HIGH16:
        case Instruction::MOVE:
        case Instruction::MOVE_FROM16:
        case Instruction::MOVE_16:
        case Instruction::MOVE_WIDE:
        case Instruction::MOVE_WIDE_FROM16:
        case Instruction::MOVE_WIDE_16:
        case Instruction::MOVE_OBJECT:
        case Instruction::MOVE_OBJECT_FROM16:
        case Instruction::MOVE_OBJECT_16:
          if ((mir->optimization_flags & MIR_CALLEE) != 0) {
            // Inlined const/move keeps method_lowering_info for type inference.
            DCHECK_LT(mir->meta.method_lowering_info, mir_graph_->GetMethodLoweringInfoCount());
            Type return_type = signatures_[mir->meta.method_lowering_info].return_type;
            DCHECK(return_type.IsDefined());  // Method return type can't be void.
            sregs_[defs[0]] = return_type.AsNonNull();
            if (return_type.Wide()) {
              DCHECK_EQ(defs[0] + 1, defs[1]);
              sregs_[defs[1]] = return_type.ToHighWord();
            }
            break;
          }
          FALLTHROUGH_INTENDED;
        case kMirOpPhi:
          // These cannot be determined in this simple pass and will be processed later.
          break;

        case Instruction::MOVE_RESULT:
        case Instruction::MOVE_RESULT_WIDE:
        case Instruction::MOVE_RESULT_OBJECT:
          // Nothing to do, handled with invoke-* or filled-new-array/-range.
          break;
        case Instruction::MOVE_EXCEPTION:
          // NOTE: We can never catch an array.
          sregs_[defs[0]] = Type::NonArrayRefType().AsNonNull();
          break;
        case Instruction::CONST_STRING:
        case Instruction::CONST_STRING_JUMBO:
          sregs_[defs[0]] = Type::NonArrayRefType().AsNonNull();
          break;
        case Instruction::CONST_CLASS:
          sregs_[defs[0]] = Type::NonArrayRefType().AsNonNull();
          break;
        case Instruction::CHECK_CAST:
          DCHECK(check_cast_data_ != nullptr);
          check_cast_data_->ProcessCheckCast(mir);
          break;
        case Instruction::ARRAY_LENGTH:
          sregs_[ModifiedSReg(uses[0])].MergeStrong(Type::UnknownArrayType());
          break;
        case Instruction::NEW_INSTANCE:
          sregs_[defs[0]] = Type::DexType(cu_->dex_file, mir->dalvikInsn.vB).AsNonNull();
          DCHECK(sregs_[defs[0]].Ref());
          DCHECK_EQ(sregs_[defs[0]].ArrayDepth(), 0u);
          break;
        case Instruction::NEW_ARRAY:
          sregs_[defs[0]] = Type::DexType(cu_->dex_file, mir->dalvikInsn.vC).AsNonNull();
          DCHECK(sregs_[defs[0]].Ref());
          DCHECK_NE(sregs_[defs[0]].ArrayDepth(), 0u);
          break;
        case Instruction::FILLED_NEW_ARRAY:
        case Instruction::FILLED_NEW_ARRAY_RANGE: {
          Type array_type = Type::DexType(cu_->dex_file, mir->dalvikInsn.vB);
          array_type.CheckPureRef();  // Previously checked by the method verifier.
          DCHECK_NE(array_type.ArrayDepth(), 0u);
          Type component_type = array_type.ComponentType();
          DCHECK(!component_type.Wide());
          MIR* move_result_mir = mir_graph_->FindMoveResult(bb, mir);
          if (move_result_mir != nullptr) {
            DCHECK_EQ(move_result_mir->dalvikInsn.opcode, Instruction::MOVE_RESULT_OBJECT);
            sregs_[move_result_mir->ssa_rep->defs[0]] = array_type.AsNonNull();
          }
          DCHECK_EQ(num_uses, mir->dalvikInsn.vA);
          for (size_t next = 0u; next != num_uses; ++next) {
            int32_t input_mod_s_reg = ModifiedSReg(uses[next]);
            sregs_[input_mod_s_reg].MergeStrong(component_type);
          }
          break;
        }
        case Instruction::INVOKE_VIRTUAL:
        case Instruction::INVOKE_SUPER:
        case Instruction::INVOKE_DIRECT:
        case Instruction::INVOKE_STATIC:
        case Instruction::INVOKE_INTERFACE:
        case Instruction::INVOKE_VIRTUAL_RANGE:
        case Instruction::INVOKE_SUPER_RANGE:
        case Instruction::INVOKE_DIRECT_RANGE:
        case Instruction::INVOKE_STATIC_RANGE:
        case Instruction::INVOKE_INTERFACE_RANGE:
        case Instruction::INVOKE_VIRTUAL_QUICK:
        case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
          const MethodSignature* signature = &signatures_[mir->meta.method_lowering_info];
          MIR* move_result_mir = mir_graph_->FindMoveResult(bb, mir);
          if (move_result_mir != nullptr) {
            Type return_type = signature->return_type;
            sregs_[move_result_mir->ssa_rep->defs[0]] = return_type.AsNonNull();
            if (return_type.Wide()) {
              DCHECK_EQ(move_result_mir->ssa_rep->defs[0] + 1, move_result_mir->ssa_rep->defs[1]);
              sregs_[move_result_mir->ssa_rep->defs[1]] = return_type.ToHighWord();
            }
          }
          size_t next = 0u;
          for (size_t i = 0, size = signature->num_params; i != size; ++i)  {
            Type param_type = signature->param_types[i];
            int32_t param_s_reg = ModifiedSReg(uses[next]);
            DCHECK(!param_type.Wide() || uses[next] + 1 == uses[next + 1]);
            UpdateSRegFromLowWordType(param_s_reg, param_type);
            next += param_type.Wide() ? 2 : 1;
          }
          DCHECK_EQ(next, num_uses);
          DCHECK_EQ(next, mir->dalvikInsn.vA);
          break;
        }

        case Instruction::RETURN_WIDE:
          DCHECK(current_method_signature_.return_type.Wide());
          DCHECK_EQ(uses[0] + 1, uses[1]);
          DCHECK_EQ(ModifiedSReg(uses[0]), uses[0]);
          FALLTHROUGH_INTENDED;
        case Instruction::RETURN:
        case Instruction::RETURN_OBJECT: {
          int32_t mod_s_reg = ModifiedSReg(uses[0]);
          UpdateSRegFromLowWordType(mod_s_reg, current_method_signature_.return_type);
          break;
        }

        // NOTE: For AGET/APUT we set only the array type. The operand type is set
        // below based on the data flow attributes.
        case Instruction::AGET:
        case Instruction::APUT:
          sregs_[ModifiedSReg(uses[num_uses - 2u])].MergeStrong(Type::NarrowArrayType());
          break;
        case Instruction::AGET_WIDE:
        case Instruction::APUT_WIDE:
          sregs_[ModifiedSReg(uses[num_uses - 2u])].MergeStrong(Type::WideArrayType());
          break;
        case Instruction::AGET_OBJECT:
          sregs_[defs[0]] = sregs_[defs[0]].AsNonNull();
          FALLTHROUGH_INTENDED;
        case Instruction::APUT_OBJECT:
          sregs_[ModifiedSReg(uses[num_uses - 2u])].MergeStrong(Type::ObjectArrayType());
          break;
        case Instruction::AGET_BOOLEAN:
        case Instruction::APUT_BOOLEAN:
        case Instruction::AGET_BYTE:
        case Instruction::APUT_BYTE:
        case Instruction::AGET_CHAR:
        case Instruction::APUT_CHAR:
        case Instruction::AGET_SHORT:
        case Instruction::APUT_SHORT:
          sregs_[ModifiedSReg(uses[num_uses - 2u])].MergeStrong(Type::NarrowCoreArrayType());
          break;

        case Instruction::IGET_WIDE:
        case Instruction::IGET_WIDE_QUICK:
          DCHECK_EQ(defs[0] + 1, defs[1]);
          DCHECK_LT(mir->meta.ifield_lowering_info, mir_graph_->GetIFieldLoweringInfoCount());
          sregs_[defs[1]] = ifields_[mir->meta.ifield_lowering_info].ToHighWord();
          FALLTHROUGH_INTENDED;
        case Instruction::IGET:
        case Instruction::IGET_OBJECT:
        case Instruction::IGET_BOOLEAN:
        case Instruction::IGET_BYTE:
        case Instruction::IGET_CHAR:
        case Instruction::IGET_SHORT:
        case Instruction::IGET_QUICK:
        case Instruction::IGET_OBJECT_QUICK:
        case Instruction::IGET_BOOLEAN_QUICK:
        case Instruction::IGET_BYTE_QUICK:
        case Instruction::IGET_CHAR_QUICK:
        case Instruction::IGET_SHORT_QUICK:
          DCHECK_LT(mir->meta.ifield_lowering_info, mir_graph_->GetIFieldLoweringInfoCount());
          sregs_[defs[0]] = ifields_[mir->meta.ifield_lowering_info].AsNonNull();
          break;
        case Instruction::IPUT_WIDE:
        case Instruction::IPUT_WIDE_QUICK:
          DCHECK_EQ(uses[0] + 1, uses[1]);
          FALLTHROUGH_INTENDED;
        case Instruction::IPUT:
        case Instruction::IPUT_OBJECT:
        case Instruction::IPUT_BOOLEAN:
        case Instruction::IPUT_BYTE:
        case Instruction::IPUT_CHAR:
        case Instruction::IPUT_SHORT:
        case Instruction::IPUT_QUICK:
        case Instruction::IPUT_OBJECT_QUICK:
        case Instruction::IPUT_BOOLEAN_QUICK:
        case Instruction::IPUT_BYTE_QUICK:
        case Instruction::IPUT_CHAR_QUICK:
        case Instruction::IPUT_SHORT_QUICK:
          DCHECK_LT(mir->meta.ifield_lowering_info, mir_graph_->GetIFieldLoweringInfoCount());
          UpdateSRegFromLowWordType(ModifiedSReg(uses[0]),
                                    ifields_[mir->meta.ifield_lowering_info]);
          break;
        case Instruction::SGET_WIDE:
          DCHECK_EQ(defs[0] + 1, defs[1]);
          DCHECK_LT(mir->meta.sfield_lowering_info, mir_graph_->GetSFieldLoweringInfoCount());
          sregs_[defs[1]] = sfields_[mir->meta.sfield_lowering_info].ToHighWord();
          FALLTHROUGH_INTENDED;
        case Instruction::SGET:
        case Instruction::SGET_OBJECT:
        case Instruction::SGET_BOOLEAN:
        case Instruction::SGET_BYTE:
        case Instruction::SGET_CHAR:
        case Instruction::SGET_SHORT:
          DCHECK_LT(mir->meta.sfield_lowering_info, mir_graph_->GetSFieldLoweringInfoCount());
          sregs_[defs[0]] = sfields_[mir->meta.sfield_lowering_info].AsNonNull();
          break;
        case Instruction::SPUT_WIDE:
          DCHECK_EQ(uses[0] + 1, uses[1]);
          FALLTHROUGH_INTENDED;
        case Instruction::SPUT:
        case Instruction::SPUT_OBJECT:
        case Instruction::SPUT_BOOLEAN:
        case Instruction::SPUT_BYTE:
        case Instruction::SPUT_CHAR:
        case Instruction::SPUT_SHORT:
          DCHECK_LT(mir->meta.sfield_lowering_info, mir_graph_->GetSFieldLoweringInfoCount());
          UpdateSRegFromLowWordType(ModifiedSReg(uses[0]),
                                          sfields_[mir->meta.sfield_lowering_info]);
          break;

        default:
          // No invokes or reference definitions here.
          DCHECK_EQ(attrs & (DF_FORMAT_35C | DF_FORMAT_3RC), 0u);
          DCHECK_NE(attrs & (DF_DA | DF_REF_A), (DF_DA | DF_REF_A));
          break;
      }

      if ((attrs & DF_NULL_TRANSFER_N) != 0) {
        // Don't process Phis at this stage.
        continue;
      }

      // Handle defs
      if (attrs & DF_DA) {
        int32_t s_reg = defs[0];
        sregs_[s_reg].SetLowWord();
        if (attrs & DF_FP_A) {
          sregs_[s_reg].SetFp();
        }
        if (attrs & DF_CORE_A) {
          sregs_[s_reg].SetCore();
        }
        if (attrs & DF_REF_A) {
          sregs_[s_reg].SetRef();
        }
        if (attrs & DF_A_WIDE) {
          sregs_[s_reg].SetWide();
          DCHECK_EQ(s_reg + 1, ModifiedSReg(defs[1]));
          sregs_[s_reg + 1].MergeHighWord(sregs_[s_reg]);
        } else {
          sregs_[s_reg].SetNarrow();
        }
      }

      // Handles uses
      size_t next = 0;
  #define PROCESS(REG)                                                        \
      if (attrs & DF_U##REG) {                                                \
        int32_t mod_s_reg = ModifiedSReg(uses[next]);                         \
        sregs_[mod_s_reg].SetLowWord();                                       \
        if (attrs & DF_FP_##REG) {                                            \
          sregs_[mod_s_reg].SetFp();                                          \
        }                                                                     \
        if (attrs & DF_CORE_##REG) {                                          \
          sregs_[mod_s_reg].SetCore();                                        \
        }                                                                     \
        if (attrs & DF_REF_##REG) {                                           \
          sregs_[mod_s_reg].SetRef();                                         \
        }                                                                     \
        if (attrs & DF_##REG##_WIDE) {                                        \
          sregs_[mod_s_reg].SetWide();                                        \
          DCHECK_EQ(mod_s_reg + 1, ModifiedSReg(uses[next + 1]));             \
          sregs_[mod_s_reg + 1].SetWide();                                    \
          sregs_[mod_s_reg + 1].MergeHighWord(sregs_[mod_s_reg]);             \
          next += 2;                                                          \
        } else {                                                              \
          sregs_[mod_s_reg].SetNarrow();                                      \
          next++;                                                             \
        }                                                                     \
      }
      PROCESS(A)
      PROCESS(B)
      PROCESS(C)
  #undef PROCESS
      DCHECK(next == mir->ssa_rep->num_uses || (attrs & (DF_FORMAT_35C | DF_FORMAT_3RC)) != 0);
    }
    // Record relevant attributes.
    bb_df_attrs_[bb->id] = bb_df_attrs &
        (DF_NULL_TRANSFER_N | DF_CHK_CAST | DF_IS_MOVE | DF_HAS_RANGE_CHKS | DF_SAME_TYPE_AB);
  }

  if (UNLIKELY(check_cast_data_ != nullptr)) {
    check_cast_data_->MarkPseudoPhiBlocks(bb_df_attrs_);
  }
}

int32_t TypeInference::ModifiedSReg(int32_t s_reg) {
  if (UNLIKELY(check_cast_data_ != nullptr)) {
    SplitSRegData* split_data = check_cast_data_->GetSplitSRegData(s_reg);
    if (UNLIKELY(split_data != nullptr)) {
      DCHECK_NE(split_data->current_mod_s_reg, INVALID_SREG);
      return split_data->current_mod_s_reg;
    }
  }
  return s_reg;
}

int32_t TypeInference::PhiInputModifiedSReg(int32_t s_reg, BasicBlock* bb, size_t pred_idx) {
  DCHECK_LT(pred_idx, bb->predecessors.size());
  if (UNLIKELY(check_cast_data_ != nullptr)) {
    SplitSRegData* split_data = check_cast_data_->GetSplitSRegData(s_reg);
    if (UNLIKELY(split_data != nullptr)) {
      return split_data->ending_mod_s_reg[bb->predecessors[pred_idx]];
    }
  }
  return s_reg;
}

bool TypeInference::UpdateSRegFromLowWordType(int32_t mod_s_reg, Type low_word_type) {
  DCHECK(low_word_type.LowWord());
  bool changed = sregs_[mod_s_reg].MergeStrong(low_word_type);
  if (!sregs_[mod_s_reg].Narrow()) {  // Wide without conflict with narrow.
    DCHECK(!low_word_type.Narrow());
    DCHECK_LT(mod_s_reg, mir_graph_->GetNumSSARegs());  // Original SSA reg.
    changed |= sregs_[mod_s_reg + 1].MergeHighWord(sregs_[mod_s_reg]);
  }
  return changed;
}

}  // namespace art
