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

#include <inttypes.h>
#include <queue>
#include <unistd.h>

#include "base/bit_vector-inl.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/stringprintf.h"
#include "base/scoped_arena_containers.h"
#include "compiler_ir.h"
#include "dex_file-inl.h"
#include "dex_flags.h"
#include "dex_instruction-inl.h"
#include "driver/compiler_driver.h"
#include "driver/dex_compilation_unit.h"
#include "dex/quick/quick_compiler.h"
#include "leb128.h"
#include "pass_driver_me_post_opt.h"
#include "stack.h"
#include "utils.h"

namespace art {

#define MAX_PATTERN_LEN 5

const char* MIRGraph::extended_mir_op_names_[kMirOpLast - kMirOpFirst] = {
  "Phi",
  "Copy",
  "FusedCmplFloat",
  "FusedCmpgFloat",
  "FusedCmplDouble",
  "FusedCmpgDouble",
  "FusedCmpLong",
  "Nop",
  "OpNullCheck",
  "OpRangeCheck",
  "OpDivZeroCheck",
  "Check",
  "Select",
  "ConstVector",
  "MoveVector",
  "PackedMultiply",
  "PackedAddition",
  "PackedSubtract",
  "PackedShiftLeft",
  "PackedSignedShiftRight",
  "PackedUnsignedShiftRight",
  "PackedAnd",
  "PackedOr",
  "PackedXor",
  "PackedAddReduce",
  "PackedReduce",
  "PackedSet",
  "ReserveVectorRegisters",
  "ReturnVectorRegisters",
  "MemBarrier",
  "PackedArrayGet",
  "PackedArrayPut",
  "MaddInt",
  "MsubInt",
  "MaddLong",
  "MsubLong",
};

MIRGraph::MIRGraph(CompilationUnit* cu, ArenaAllocator* arena)
    : reg_location_(nullptr),
      block_id_map_(std::less<unsigned int>(), arena->Adapter()),
      cu_(cu),
      ssa_base_vregs_(arena->Adapter(kArenaAllocSSAToDalvikMap)),
      ssa_subscripts_(arena->Adapter(kArenaAllocSSAToDalvikMap)),
      vreg_to_ssa_map_(nullptr),
      ssa_last_defs_(nullptr),
      is_constant_v_(nullptr),
      constant_values_(nullptr),
      use_counts_(arena->Adapter()),
      raw_use_counts_(arena->Adapter()),
      num_reachable_blocks_(0),
      max_num_reachable_blocks_(0),
      dfs_orders_up_to_date_(false),
      domination_up_to_date_(false),
      mir_ssa_rep_up_to_date_(false),
      topological_order_up_to_date_(false),
      dfs_order_(arena->Adapter(kArenaAllocDfsPreOrder)),
      dfs_post_order_(arena->Adapter(kArenaAllocDfsPostOrder)),
      dom_post_order_traversal_(arena->Adapter(kArenaAllocDomPostOrder)),
      topological_order_(arena->Adapter(kArenaAllocTopologicalSortOrder)),
      topological_order_loop_ends_(arena->Adapter(kArenaAllocTopologicalSortOrder)),
      topological_order_indexes_(arena->Adapter(kArenaAllocTopologicalSortOrder)),
      topological_order_loop_head_stack_(arena->Adapter(kArenaAllocTopologicalSortOrder)),
      max_nested_loops_(0u),
      i_dom_list_(nullptr),
      temp_scoped_alloc_(),
      block_list_(arena->Adapter(kArenaAllocBBList)),
      try_block_addr_(nullptr),
      entry_block_(nullptr),
      exit_block_(nullptr),
      current_code_item_(nullptr),
      m_units_(arena->Adapter()),
      method_stack_(arena->Adapter()),
      current_method_(kInvalidEntry),
      current_offset_(kInvalidEntry),
      def_count_(0),
      opcode_count_(nullptr),
      num_ssa_regs_(0),
      extended_basic_blocks_(arena->Adapter()),
      method_sreg_(0),
      attributes_(METHOD_IS_LEAF),  // Start with leaf assumption, change on encountering invoke.
      checkstats_(nullptr),
      arena_(arena),
      backward_branches_(0),
      forward_branches_(0),
      num_non_special_compiler_temps_(0),
      max_available_special_compiler_temps_(1),  // We only need the method ptr as a special temp for now.
      requested_backend_temp_(false),
      compiler_temps_committed_(false),
      punt_to_interpreter_(false),
      merged_df_flags_(0u),
      ifield_lowering_infos_(arena->Adapter(kArenaAllocLoweringInfo)),
      sfield_lowering_infos_(arena->Adapter(kArenaAllocLoweringInfo)),
      method_lowering_infos_(arena->Adapter(kArenaAllocLoweringInfo)),
      suspend_checks_in_loops_(nullptr) {
  memset(&temp_, 0, sizeof(temp_));
  use_counts_.reserve(256);
  raw_use_counts_.reserve(256);
  block_list_.reserve(100);
  try_block_addr_ = new (arena_) ArenaBitVector(arena_, 0, true /* expandable */);


  if (cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) {
    // X86 requires a temp to keep track of the method address.
    // TODO For x86_64, addressing can be done with RIP. When that is implemented,
    // this needs to be updated to reserve 0 temps for BE.
    max_available_non_special_compiler_temps_ = cu_->target64 ? 2 : 1;
    reserved_temps_for_backend_ = max_available_non_special_compiler_temps_;
  } else {
    // Other architectures do not have a known lower bound for non-special temps.
    // We allow the update of the max to happen at BE initialization stage and simply set 0 for now.
    max_available_non_special_compiler_temps_ = 0;
    reserved_temps_for_backend_ = 0;
  }
}

MIRGraph::~MIRGraph() {
  STLDeleteElements(&block_list_);
  STLDeleteElements(&m_units_);
}

/*
 * Parse an instruction, return the length of the instruction
 */
int MIRGraph::ParseInsn(const uint16_t* code_ptr, MIR::DecodedInstruction* decoded_instruction) {
  const Instruction* inst = Instruction::At(code_ptr);
  decoded_instruction->opcode = inst->Opcode();
  decoded_instruction->vA = inst->HasVRegA() ? inst->VRegA() : 0;
  decoded_instruction->vB = inst->HasVRegB() ? inst->VRegB() : 0;
  decoded_instruction->vB_wide = inst->HasWideVRegB() ? inst->WideVRegB() : 0;
  decoded_instruction->vC = inst->HasVRegC() ?  inst->VRegC() : 0;
  if (inst->HasVarArgs35c()) {
    inst->GetVarArgs(decoded_instruction->arg);
  }
  return inst->SizeInCodeUnits();
}


/* Split an existing block from the specified code offset into two */
BasicBlock* MIRGraph::SplitBlock(DexOffset code_offset,
                                 BasicBlock* orig_block, BasicBlock** immed_pred_block_p) {
  DCHECK_GT(code_offset, orig_block->start_offset);
  MIR* insn = orig_block->first_mir_insn;
  MIR* prev = nullptr;  // Will be set to instruction before split.
  while (insn) {
    if (insn->offset == code_offset) break;
    prev = insn;
    insn = insn->next;
  }
  if (insn == nullptr) {
    LOG(FATAL) << "Break split failed";
  }
  // Now insn is at the instruction where we want to split, namely
  // insn will be the first instruction of the "bottom" block.
  // Similarly, prev will be the last instruction of the "top" block

  BasicBlock* bottom_block = CreateNewBB(kDalvikByteCode);

  bottom_block->start_offset = code_offset;
  bottom_block->first_mir_insn = insn;
  bottom_block->last_mir_insn = orig_block->last_mir_insn;

  /* If this block was terminated by a return, conditional branch or throw,
   * the flag needs to go with the bottom block
   */
  bottom_block->terminated_by_return = orig_block->terminated_by_return;
  orig_block->terminated_by_return = false;

  bottom_block->conditional_branch = orig_block->conditional_branch;
  orig_block->conditional_branch = false;

  bottom_block->explicit_throw = orig_block->explicit_throw;
  orig_block->explicit_throw = false;

  /* Handle the taken path */
  bottom_block->taken = orig_block->taken;
  if (bottom_block->taken != NullBasicBlockId) {
    orig_block->taken = NullBasicBlockId;
    BasicBlock* bb_taken = GetBasicBlock(bottom_block->taken);
    bb_taken->ErasePredecessor(orig_block->id);
    bb_taken->predecessors.push_back(bottom_block->id);
  }

  /* Handle the fallthrough path */
  bottom_block->fall_through = orig_block->fall_through;
  orig_block->fall_through = bottom_block->id;
  bottom_block->predecessors.push_back(orig_block->id);
  if (bottom_block->fall_through != NullBasicBlockId) {
    BasicBlock* bb_fall_through = GetBasicBlock(bottom_block->fall_through);
    bb_fall_through->ErasePredecessor(orig_block->id);
    bb_fall_through->predecessors.push_back(bottom_block->id);
  }

  /* Handle the successor list */
  if (orig_block->successor_block_list_type != kNotUsed) {
    bottom_block->successor_block_list_type = orig_block->successor_block_list_type;
    bottom_block->successor_blocks.swap(orig_block->successor_blocks);
    orig_block->successor_block_list_type = kNotUsed;
    DCHECK(orig_block->successor_blocks.empty());  // Empty after the swap() above.
    for (SuccessorBlockInfo* successor_block_info : bottom_block->successor_blocks) {
      BasicBlock* bb = GetBasicBlock(successor_block_info->block);
      if (bb != nullptr) {
        bb->ErasePredecessor(orig_block->id);
        bb->predecessors.push_back(bottom_block->id);
      }
    }
  }

  orig_block->last_mir_insn = prev;
  prev->next = nullptr;

  /*
   * Update the immediate predecessor block pointer so that outgoing edges
   * can be applied to the proper block.
   */
  if (immed_pred_block_p) {
    DCHECK_EQ(*immed_pred_block_p, orig_block);
    *immed_pred_block_p = bottom_block;
  }

  // Associate dex instructions in the bottom block with the new container.
  DCHECK(insn != nullptr);
  DCHECK(insn != orig_block->first_mir_insn);
  DCHECK(insn == bottom_block->first_mir_insn);
  DCHECK_EQ(insn->offset, bottom_block->start_offset);
  // Scan the "bottom" instructions, remapping them to the
  // newly created "bottom" block.
  MIR* p = insn;
  p->bb = bottom_block->id;
  while (p != bottom_block->last_mir_insn) {
    p = p->next;
    DCHECK(p != nullptr);
    p->bb = bottom_block->id;
  }

  return bottom_block;
}

/*
 * Given a code offset, find out the block that starts with it. If the offset
 * is in the middle of an existing block, split it into two.  If immed_pred_block_p
 * is not non-null and is the block being split, update *immed_pred_block_p to
 * point to the bottom block so that outgoing edges can be set up properly
 * (by the caller)
 * Utilizes a map for fast lookup of the typical cases.
 */
BasicBlock* MIRGraph::FindBlock(DexOffset code_offset, bool create,
                                BasicBlock** immed_pred_block_p,
                                ScopedArenaVector<uint16_t>* dex_pc_to_block_map) {
  if (UNLIKELY(code_offset >= current_code_item_->insns_size_in_code_units_)) {
    // There can be a fall-through out of the method code. We shall record such a block
    // here (assuming create==true) and check that it's dead at the end of InlineMethod().
    // Though we're only aware of the cases where code_offset is exactly the same as
    // insns_size_in_code_units_, treat greater code_offset the same just in case.
    code_offset = current_code_item_->insns_size_in_code_units_;
  }

  int block_id = (*dex_pc_to_block_map)[code_offset];
  BasicBlock* bb = GetBasicBlock(block_id);

  if ((bb != nullptr) && (bb->start_offset == code_offset)) {
    // Does this containing block start with the desired instruction?
    return bb;
  }

  // No direct hit.
  if (!create) {
    return nullptr;
  }

  if (bb != nullptr) {
    // The target exists somewhere in an existing block.
    BasicBlock* bottom_block = SplitBlock(code_offset, bb, bb == *immed_pred_block_p ?  immed_pred_block_p : nullptr);
    DCHECK(bottom_block != nullptr);
    MIR* p = bottom_block->first_mir_insn;
    BasicBlock* orig_block = bb;
    DCHECK_EQ((*dex_pc_to_block_map)[p->offset], orig_block->id);
    // Scan the "bottom" instructions, remapping them to the
    // newly created "bottom" block.
    (*dex_pc_to_block_map)[p->offset] = bottom_block->id;
    while (p != bottom_block->last_mir_insn) {
      p = p->next;
      DCHECK(p != nullptr);
      int opcode = p->dalvikInsn.opcode;
      /*
       * Some messiness here to ensure that we only enter real opcodes and only the
       * first half of a potentially throwing instruction that has been split into
       * CHECK and work portions. Since the 2nd half of a split operation is always
       * the first in a BasicBlock, we can't hit it here.
       */
      if ((opcode == kMirOpCheck) || !MIR::DecodedInstruction::IsPseudoMirOp(opcode)) {
        BasicBlockId mapped_id = (*dex_pc_to_block_map)[p->offset];
        // At first glance the instructions should all be mapped to orig_block.
        // However, multiple instructions may correspond to the same dex, hence an earlier
        // instruction may have already moved the mapping for dex to bottom_block.
        DCHECK((mapped_id == orig_block->id) || (mapped_id == bottom_block->id));
        (*dex_pc_to_block_map)[p->offset] = bottom_block->id;
      }
    }
    return bottom_block;
  }

  // Create a new block.
  bb = CreateNewBB(kDalvikByteCode);
  bb->start_offset = code_offset;
  (*dex_pc_to_block_map)[bb->start_offset] = bb->id;
  return bb;
}


/* Identify code range in try blocks and set up the empty catch blocks */
void MIRGraph::ProcessTryCatchBlocks(ScopedArenaVector<uint16_t>* dex_pc_to_block_map) {
  int tries_size = current_code_item_->tries_size_;
  DexOffset offset;

  if (tries_size == 0) {
    return;
  }

  for (int i = 0; i < tries_size; i++) {
    const DexFile::TryItem* pTry =
        DexFile::GetTryItems(*current_code_item_, i);
    DexOffset start_offset = pTry->start_addr_;
    DexOffset end_offset = start_offset + pTry->insn_count_;
    for (offset = start_offset; offset < end_offset; offset++) {
      try_block_addr_->SetBit(offset);
    }
  }

  // Iterate over each of the handlers to enqueue the empty Catch blocks.
  const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(*current_code_item_, 0);
  uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
  for (uint32_t idx = 0; idx < handlers_size; idx++) {
    CatchHandlerIterator iterator(handlers_ptr);
    for (; iterator.HasNext(); iterator.Next()) {
      uint32_t address = iterator.GetHandlerAddress();
      FindBlock(address, true /*create*/, /* immed_pred_block_p */ nullptr, dex_pc_to_block_map);
    }
    handlers_ptr = iterator.EndDataPointer();
  }
}

bool MIRGraph::IsBadMonitorExitCatch(NarrowDexOffset monitor_exit_offset,
                                     NarrowDexOffset catch_offset) {
  // Catches for monitor-exit during stack unwinding have the pattern
  //   move-exception (move)* (goto)? monitor-exit throw
  // In the currently generated dex bytecode we see these catching a bytecode range including
  // either its own or an identical monitor-exit, http://b/15745363 . This function checks if
  // it's the case for a given monitor-exit and catch block so that we can ignore it.
  // (We don't want to ignore all monitor-exit catches since one could enclose a synchronized
  // block in a try-block and catch the NPE, Error or Throwable and we should let it through;
  // even though a throwing monitor-exit certainly indicates a bytecode error.)
  const Instruction* monitor_exit = Instruction::At(current_code_item_->insns_ + monitor_exit_offset);
  DCHECK(monitor_exit->Opcode() == Instruction::MONITOR_EXIT);
  int monitor_reg = monitor_exit->VRegA_11x();
  const Instruction* check_insn = Instruction::At(current_code_item_->insns_ + catch_offset);
  if (check_insn->Opcode() == Instruction::MOVE_EXCEPTION) {
    if (check_insn->VRegA_11x() == monitor_reg) {
      // Unexpected move-exception to the same register. Probably not the pattern we're looking for.
      return false;
    }
    check_insn = check_insn->Next();
  }
  while (true) {
    int dest = -1;
    bool wide = false;
    switch (check_insn->Opcode()) {
      case Instruction::MOVE_WIDE:
        wide = true;
        FALLTHROUGH_INTENDED;
      case Instruction::MOVE_OBJECT:
      case Instruction::MOVE:
        dest = check_insn->VRegA_12x();
        break;

      case Instruction::MOVE_WIDE_FROM16:
        wide = true;
        FALLTHROUGH_INTENDED;
      case Instruction::MOVE_OBJECT_FROM16:
      case Instruction::MOVE_FROM16:
        dest = check_insn->VRegA_22x();
        break;

      case Instruction::MOVE_WIDE_16:
        wide = true;
        FALLTHROUGH_INTENDED;
      case Instruction::MOVE_OBJECT_16:
      case Instruction::MOVE_16:
        dest = check_insn->VRegA_32x();
        break;

      case Instruction::GOTO:
      case Instruction::GOTO_16:
      case Instruction::GOTO_32:
        check_insn = check_insn->RelativeAt(check_insn->GetTargetOffset());
        FALLTHROUGH_INTENDED;
      default:
        return check_insn->Opcode() == Instruction::MONITOR_EXIT &&
            check_insn->VRegA_11x() == monitor_reg;
    }

    if (dest == monitor_reg || (wide && dest + 1 == monitor_reg)) {
      return false;
    }

    check_insn = check_insn->Next();
  }
}

/* Process instructions with the kBranch flag */
BasicBlock* MIRGraph::ProcessCanBranch(BasicBlock* cur_block, MIR* insn, DexOffset cur_offset,
                                       int width, int flags, const uint16_t* code_ptr,
                                       const uint16_t* code_end,
                                       ScopedArenaVector<uint16_t>* dex_pc_to_block_map) {
  DexOffset target = cur_offset;
  switch (insn->dalvikInsn.opcode) {
    case Instruction::GOTO:
    case Instruction::GOTO_16:
    case Instruction::GOTO_32:
      target += insn->dalvikInsn.vA;
      break;
    case Instruction::IF_EQ:
    case Instruction::IF_NE:
    case Instruction::IF_LT:
    case Instruction::IF_GE:
    case Instruction::IF_GT:
    case Instruction::IF_LE:
      cur_block->conditional_branch = true;
      target += insn->dalvikInsn.vC;
      break;
    case Instruction::IF_EQZ:
    case Instruction::IF_NEZ:
    case Instruction::IF_LTZ:
    case Instruction::IF_GEZ:
    case Instruction::IF_GTZ:
    case Instruction::IF_LEZ:
      cur_block->conditional_branch = true;
      target += insn->dalvikInsn.vB;
      break;
    default:
      LOG(FATAL) << "Unexpected opcode(" << insn->dalvikInsn.opcode << ") with kBranch set";
  }
  CountBranch(target);
  BasicBlock* taken_block = FindBlock(target, /* create */ true,
                                      /* immed_pred_block_p */ &cur_block,
                                      dex_pc_to_block_map);
  DCHECK(taken_block != nullptr);
  cur_block->taken = taken_block->id;
  taken_block->predecessors.push_back(cur_block->id);

  /* Always terminate the current block for conditional branches */
  if (flags & Instruction::kContinue) {
    BasicBlock* fallthrough_block = FindBlock(cur_offset +  width,
                                             /* create */
                                             true,
                                             /* immed_pred_block_p */
                                             &cur_block,
                                             dex_pc_to_block_map);
    DCHECK(fallthrough_block != nullptr);
    cur_block->fall_through = fallthrough_block->id;
    fallthrough_block->predecessors.push_back(cur_block->id);
  } else if (code_ptr < code_end) {
    FindBlock(cur_offset + width, /* create */ true, /* immed_pred_block_p */ nullptr, dex_pc_to_block_map);
  }
  return cur_block;
}

/* Process instructions with the kSwitch flag */
BasicBlock* MIRGraph::ProcessCanSwitch(BasicBlock* cur_block, MIR* insn, DexOffset cur_offset,
                                       int width, int flags,
                                       ScopedArenaVector<uint16_t>* dex_pc_to_block_map) {
  UNUSED(flags);
  const uint16_t* switch_data =
      reinterpret_cast<const uint16_t*>(GetCurrentInsns() + cur_offset +
          static_cast<int32_t>(insn->dalvikInsn.vB));
  int size;
  const int* keyTable;
  const int* target_table;
  int i;
  int first_key;

  /*
   * Packed switch data format:
   *  ushort ident = 0x0100   magic value
   *  ushort size             number of entries in the table
   *  int first_key           first (and lowest) switch case value
   *  int targets[size]       branch targets, relative to switch opcode
   *
   * Total size is (4+size*2) 16-bit code units.
   */
  if (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) {
    DCHECK_EQ(static_cast<int>(switch_data[0]),
              static_cast<int>(Instruction::kPackedSwitchSignature));
    size = switch_data[1];
    first_key = switch_data[2] | (switch_data[3] << 16);
    target_table = reinterpret_cast<const int*>(&switch_data[4]);
    keyTable = nullptr;        // Make the compiler happy.
  /*
   * Sparse switch data format:
   *  ushort ident = 0x0200   magic value
   *  ushort size             number of entries in the table; > 0
   *  int keys[size]          keys, sorted low-to-high; 32-bit aligned
   *  int targets[size]       branch targets, relative to switch opcode
   *
   * Total size is (2+size*4) 16-bit code units.
   */
  } else {
    DCHECK_EQ(static_cast<int>(switch_data[0]),
              static_cast<int>(Instruction::kSparseSwitchSignature));
    size = switch_data[1];
    keyTable = reinterpret_cast<const int*>(&switch_data[2]);
    target_table = reinterpret_cast<const int*>(&switch_data[2 + size*2]);
    first_key = 0;   // To make the compiler happy.
  }

  if (cur_block->successor_block_list_type != kNotUsed) {
    LOG(FATAL) << "Successor block list already in use: "
               << static_cast<int>(cur_block->successor_block_list_type);
  }
  cur_block->successor_block_list_type =
      (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?  kPackedSwitch : kSparseSwitch;
  cur_block->successor_blocks.reserve(size);

  for (i = 0; i < size; i++) {
    BasicBlock* case_block = FindBlock(cur_offset + target_table[i],  /* create */ true,
                                       /* immed_pred_block_p */ &cur_block,
                                       dex_pc_to_block_map);
    DCHECK(case_block != nullptr);
    SuccessorBlockInfo* successor_block_info =
        static_cast<SuccessorBlockInfo*>(arena_->Alloc(sizeof(SuccessorBlockInfo),
                                                       kArenaAllocSuccessor));
    successor_block_info->block = case_block->id;
    successor_block_info->key =
        (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
        first_key + i : keyTable[i];
    cur_block->successor_blocks.push_back(successor_block_info);
    case_block->predecessors.push_back(cur_block->id);
  }

  /* Fall-through case */
  BasicBlock* fallthrough_block = FindBlock(cur_offset +  width, /* create */ true,
                                            /* immed_pred_block_p */ nullptr,
                                            dex_pc_to_block_map);
  DCHECK(fallthrough_block != nullptr);
  cur_block->fall_through = fallthrough_block->id;
  fallthrough_block->predecessors.push_back(cur_block->id);
  return cur_block;
}

/* Process instructions with the kThrow flag */
BasicBlock* MIRGraph::ProcessCanThrow(BasicBlock* cur_block, MIR* insn, DexOffset cur_offset,
                                      int width, int flags, ArenaBitVector* try_block_addr,
                                      const uint16_t* code_ptr, const uint16_t* code_end,
                                      ScopedArenaVector<uint16_t>* dex_pc_to_block_map) {
  UNUSED(flags);
  bool in_try_block = try_block_addr->IsBitSet(cur_offset);
  bool is_throw = (insn->dalvikInsn.opcode == Instruction::THROW);

  /* In try block */
  if (in_try_block) {
    CatchHandlerIterator iterator(*current_code_item_, cur_offset);

    if (cur_block->successor_block_list_type != kNotUsed) {
      LOG(INFO) << PrettyMethod(cu_->method_idx, *cu_->dex_file);
      LOG(FATAL) << "Successor block list already in use: "
                 << static_cast<int>(cur_block->successor_block_list_type);
    }

    for (; iterator.HasNext(); iterator.Next()) {
      BasicBlock* catch_block = FindBlock(iterator.GetHandlerAddress(), false /* create */,
                                          nullptr /* immed_pred_block_p */,
                                          dex_pc_to_block_map);
      if (insn->dalvikInsn.opcode == Instruction::MONITOR_EXIT &&
          IsBadMonitorExitCatch(insn->offset, catch_block->start_offset)) {
        // Don't allow monitor-exit to catch its own exception, http://b/15745363 .
        continue;
      }
      if (cur_block->successor_block_list_type == kNotUsed) {
        cur_block->successor_block_list_type = kCatch;
      }
      catch_block->catch_entry = true;
      if (kIsDebugBuild) {
        catches_.insert(catch_block->start_offset);
      }
      SuccessorBlockInfo* successor_block_info = reinterpret_cast<SuccessorBlockInfo*>
          (arena_->Alloc(sizeof(SuccessorBlockInfo), kArenaAllocSuccessor));
      successor_block_info->block = catch_block->id;
      successor_block_info->key = iterator.GetHandlerTypeIndex();
      cur_block->successor_blocks.push_back(successor_block_info);
      catch_block->predecessors.push_back(cur_block->id);
    }
    in_try_block = (cur_block->successor_block_list_type != kNotUsed);
  }
  bool build_all_edges =
      (cu_->disable_opt & (1 << kSuppressExceptionEdges)) || is_throw || in_try_block;
  if (!in_try_block && build_all_edges) {
    BasicBlock* eh_block = CreateNewBB(kExceptionHandling);
    cur_block->taken = eh_block->id;
    eh_block->start_offset = cur_offset;
    eh_block->predecessors.push_back(cur_block->id);
  }

  if (is_throw) {
    cur_block->explicit_throw = true;
    if (code_ptr < code_end) {
      // Force creation of new block following THROW via side-effect.
      FindBlock(cur_offset + width, /* create */ true, /* immed_pred_block_p */ nullptr, dex_pc_to_block_map);
    }
    if (!in_try_block) {
       // Don't split a THROW that can't rethrow - we're done.
      return cur_block;
    }
  }

  if (!build_all_edges) {
    /*
     * Even though there is an exception edge here, control cannot return to this
     * method.  Thus, for the purposes of dataflow analysis and optimization, we can
     * ignore the edge.  Doing this reduces compile time, and increases the scope
     * of the basic-block level optimization pass.
     */
    return cur_block;
  }

  /*
   * Split the potentially-throwing instruction into two parts.
   * The first half will be a pseudo-op that captures the exception
   * edges and terminates the basic block.  It always falls through.
   * Then, create a new basic block that begins with the throwing instruction
   * (minus exceptions).  Note: this new basic block must NOT be entered into
   * the block_map.  If the potentially-throwing instruction is the target of a
   * future branch, we need to find the check psuedo half.  The new
   * basic block containing the work portion of the instruction should
   * only be entered via fallthrough from the block containing the
   * pseudo exception edge MIR.  Note also that this new block is
   * not automatically terminated after the work portion, and may
   * contain following instructions.
   *
   * Note also that the dex_pc_to_block_map entry for the potentially
   * throwing instruction will refer to the original basic block.
   */
  BasicBlock* new_block = CreateNewBB(kDalvikByteCode);
  new_block->start_offset = insn->offset;
  cur_block->fall_through = new_block->id;
  new_block->predecessors.push_back(cur_block->id);
  MIR* new_insn = NewMIR();
  *new_insn = *insn;
  insn->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpCheck);
  // Associate the two halves.
  insn->meta.throw_insn = new_insn;
  new_block->AppendMIR(new_insn);
  return new_block;
}

/* Parse a Dex method and insert it into the MIRGraph at the current insert point. */
void MIRGraph::InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_flags,
                           InvokeType invoke_type ATTRIBUTE_UNUSED, uint16_t class_def_idx,
                           uint32_t method_idx, jobject class_loader, const DexFile& dex_file) {
  current_code_item_ = code_item;
  method_stack_.push_back(std::make_pair(current_method_, current_offset_));
  current_method_ = m_units_.size();
  current_offset_ = 0;
  // TODO: will need to snapshot stack image and use that as the mir context identification.
  m_units_.push_back(new (arena_) DexCompilationUnit(
      cu_, class_loader, Runtime::Current()->GetClassLinker(), dex_file,
      current_code_item_, class_def_idx, method_idx, access_flags,
      cu_->compiler_driver->GetVerifiedMethod(&dex_file, method_idx)));
  const uint16_t* code_ptr = current_code_item_->insns_;
  const uint16_t* code_end =
      current_code_item_->insns_ + current_code_item_->insns_size_in_code_units_;

  // TODO: need to rework expansion of block list & try_block_addr when inlining activated.
  // TUNING: use better estimate of basic blocks for following resize.
  block_list_.reserve(block_list_.size() + current_code_item_->insns_size_in_code_units_);
  // FindBlock lookup cache.
  ScopedArenaAllocator allocator(&cu_->arena_stack);
  ScopedArenaVector<uint16_t> dex_pc_to_block_map(allocator.Adapter());
  dex_pc_to_block_map.resize(current_code_item_->insns_size_in_code_units_ +
                             1 /* Fall-through on last insn; dead or punt to interpreter. */);

  // TODO: replace with explicit resize routine.  Using automatic extension side effect for now.
  try_block_addr_->SetBit(current_code_item_->insns_size_in_code_units_);
  try_block_addr_->ClearBit(current_code_item_->insns_size_in_code_units_);

  // If this is the first method, set up default entry and exit blocks.
  if (current_method_ == 0) {
    DCHECK(entry_block_ == nullptr);
    DCHECK(exit_block_ == nullptr);
    DCHECK_EQ(GetNumBlocks(), 0U);
    // Use id 0 to represent a null block.
    BasicBlock* null_block = CreateNewBB(kNullBlock);
    DCHECK_EQ(null_block->id, NullBasicBlockId);
    null_block->hidden = true;
    entry_block_ = CreateNewBB(kEntryBlock);
    exit_block_ = CreateNewBB(kExitBlock);
  } else {
    UNIMPLEMENTED(FATAL) << "Nested inlining not implemented.";
    /*
     * Will need to manage storage for ins & outs, push prevous state and update
     * insert point.
     */
  }

  /* Current block to record parsed instructions */
  BasicBlock* cur_block = CreateNewBB(kDalvikByteCode);
  DCHECK_EQ(current_offset_, 0U);
  cur_block->start_offset = current_offset_;
  // TODO: for inlining support, insert at the insert point rather than entry block.
  entry_block_->fall_through = cur_block->id;
  cur_block->predecessors.push_back(entry_block_->id);

  /* Identify code range in try blocks and set up the empty catch blocks */
  ProcessTryCatchBlocks(&dex_pc_to_block_map);

  uint64_t merged_df_flags = 0u;

  /* Parse all instructions and put them into containing basic blocks */
  while (code_ptr < code_end) {
    MIR *insn = NewMIR();
    insn->offset = current_offset_;
    insn->m_unit_index = current_method_;
    int width = ParseInsn(code_ptr, &insn->dalvikInsn);
    Instruction::Code opcode = insn->dalvikInsn.opcode;
    if (opcode_count_ != nullptr) {
      opcode_count_[static_cast<int>(opcode)]++;
    }

    int flags = insn->dalvikInsn.FlagsOf();
    int verify_flags = Instruction::VerifyFlagsOf(insn->dalvikInsn.opcode);

    uint64_t df_flags = GetDataFlowAttributes(insn);
    merged_df_flags |= df_flags;

    if (df_flags & DF_HAS_DEFS) {
      def_count_ += (df_flags & DF_A_WIDE) ? 2 : 1;
    }

    if (df_flags & DF_LVN) {
      cur_block->use_lvn = true;  // Run local value numbering on this basic block.
    }

    // Check for inline data block signatures.
    if (opcode == Instruction::NOP) {
      // A simple NOP will have a width of 1 at this point, embedded data NOP > 1.
      if ((width == 1) && ((current_offset_ & 0x1) == 0x1) && ((code_end - code_ptr) > 1)) {
        // Could be an aligning nop.  If an embedded data NOP follows, treat pair as single unit.
        uint16_t following_raw_instruction = code_ptr[1];
        if ((following_raw_instruction == Instruction::kSparseSwitchSignature) ||
            (following_raw_instruction == Instruction::kPackedSwitchSignature) ||
            (following_raw_instruction == Instruction::kArrayDataSignature)) {
          width += Instruction::At(code_ptr + 1)->SizeInCodeUnits();
        }
      }
      if (width == 1) {
        // It is a simple nop - treat normally.
        cur_block->AppendMIR(insn);
      } else {
        DCHECK(cur_block->fall_through == NullBasicBlockId);
        DCHECK(cur_block->taken == NullBasicBlockId);
        // Unreachable instruction, mark for no continuation and end basic block.
        flags &= ~Instruction::kContinue;
        FindBlock(current_offset_ + width, /* create */ true,
                  /* immed_pred_block_p */ nullptr, &dex_pc_to_block_map);
      }
    } else {
      cur_block->AppendMIR(insn);
    }

    // Associate the starting dex_pc for this opcode with its containing basic block.
    dex_pc_to_block_map[insn->offset] = cur_block->id;

    code_ptr += width;

    if (flags & Instruction::kBranch) {
      cur_block = ProcessCanBranch(cur_block, insn, current_offset_,
                                   width, flags, code_ptr, code_end, &dex_pc_to_block_map);
    } else if (flags & Instruction::kReturn) {
      cur_block->terminated_by_return = true;
      cur_block->fall_through = exit_block_->id;
      exit_block_->predecessors.push_back(cur_block->id);
      /*
       * Terminate the current block if there are instructions
       * afterwards.
       */
      if (code_ptr < code_end) {
        /*
         * Create a fallthrough block for real instructions
         * (incl. NOP).
         */
         FindBlock(current_offset_ + width, /* create */ true,
                   /* immed_pred_block_p */ nullptr, &dex_pc_to_block_map);
      }
    } else if (flags & Instruction::kThrow) {
      cur_block = ProcessCanThrow(cur_block, insn, current_offset_, width, flags, try_block_addr_,
                                  code_ptr, code_end, &dex_pc_to_block_map);
    } else if (flags & Instruction::kSwitch) {
      cur_block = ProcessCanSwitch(cur_block, insn, current_offset_, width,
                                   flags, &dex_pc_to_block_map);
    }
    if (verify_flags & Instruction::kVerifyVarArgRange ||
        verify_flags & Instruction::kVerifyVarArgRangeNonZero) {
      /*
       * The Quick backend's runtime model includes a gap between a method's
       * argument ("in") vregs and the rest of its vregs.  Handling a range instruction
       * which spans the gap is somewhat complicated, and should not happen
       * in normal usage of dx.  Punt to the interpreter.
       */
      int first_reg_in_range = insn->dalvikInsn.vC;
      int last_reg_in_range = first_reg_in_range + insn->dalvikInsn.vA - 1;
      if (IsInVReg(first_reg_in_range) != IsInVReg(last_reg_in_range)) {
        punt_to_interpreter_ = true;
      }
    }
    current_offset_ += width;
    BasicBlock* next_block = FindBlock(current_offset_, /* create */ false,
                                       /* immed_pred_block_p */ nullptr,
                                       &dex_pc_to_block_map);
    if (next_block) {
      /*
       * The next instruction could be the target of a previously parsed
       * forward branch so a block is already created. If the current
       * instruction is not an unconditional branch, connect them through
       * the fall-through link.
       */
      DCHECK(cur_block->fall_through == NullBasicBlockId ||
             GetBasicBlock(cur_block->fall_through) == next_block ||
             GetBasicBlock(cur_block->fall_through) == exit_block_);

      if ((cur_block->fall_through == NullBasicBlockId) && (flags & Instruction::kContinue)) {
        cur_block->fall_through = next_block->id;
        next_block->predecessors.push_back(cur_block->id);
      }
      cur_block = next_block;
    }
  }
  merged_df_flags_ = merged_df_flags;

  if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
    DumpCFG("/sdcard/1_post_parse_cfg/", true);
  }

  if (cu_->verbose) {
    DumpMIRGraph();
  }

  // Check if there's been a fall-through out of the method code.
  BasicBlockId out_bb_id = dex_pc_to_block_map[current_code_item_->insns_size_in_code_units_];
  if (UNLIKELY(out_bb_id != NullBasicBlockId)) {
    // Eagerly calculate DFS order to determine if the block is dead.
    DCHECK(!DfsOrdersUpToDate());
    ComputeDFSOrders();
    BasicBlock* out_bb = GetBasicBlock(out_bb_id);
    DCHECK(out_bb != nullptr);
    if (out_bb->block_type != kDead) {
      LOG(WARNING) << "Live fall-through out of method in " << PrettyMethod(method_idx, dex_file);
      SetPuntToInterpreter(true);
    }
  }
}

void MIRGraph::ShowOpcodeStats() {
  DCHECK(opcode_count_ != nullptr);
  LOG(INFO) << "Opcode Count";
  for (int i = 0; i < kNumPackedOpcodes; i++) {
    if (opcode_count_[i] != 0) {
      LOG(INFO) << "-C- " << Instruction::Name(static_cast<Instruction::Code>(i))
                << " " << opcode_count_[i];
    }
  }
}

uint64_t MIRGraph::GetDataFlowAttributes(Instruction::Code opcode) {
  DCHECK_LT((size_t) opcode, (sizeof(oat_data_flow_attributes_) / sizeof(oat_data_flow_attributes_[0])));
  return oat_data_flow_attributes_[opcode];
}

uint64_t MIRGraph::GetDataFlowAttributes(MIR* mir) {
  DCHECK(mir != nullptr);
  Instruction::Code opcode = mir->dalvikInsn.opcode;
  return GetDataFlowAttributes(opcode);
}

// The path can easily surpass FS limits because of parameters etc. Use pathconf to get FS
// restrictions here. Note that a successful invocation will return an actual value. If the path
// is too long for some reason, the return will be ENAMETOOLONG. Then cut off part of the name.
//
// It's possible the path is not valid, or some other errors appear. In that case return false.
static bool CreateDumpFile(std::string& fname, const char* dir_prefix, NarrowDexOffset start_offset,
                           const char *suffix, int nr, std::string* output) {
  std::string dir = StringPrintf("./%s", dir_prefix);
  int64_t max_name_length = pathconf(dir.c_str(), _PC_NAME_MAX);
  if (max_name_length <= 0) {
    PLOG(ERROR) << "Could not get file name restrictions for " << dir;
    return false;
  }

  std::string name = StringPrintf("%s%x%s_%d.dot", fname.c_str(), start_offset,
                                  suffix == nullptr ? "" : suffix, nr);
  std::string fpath;
  if (static_cast<int64_t>(name.size()) > max_name_length) {
    std::string suffix_str = StringPrintf("_%d.dot", nr);
    name = name.substr(0, static_cast<size_t>(max_name_length) - suffix_str.size()) + suffix_str;
  }
  // Sanity check.
  DCHECK_LE(name.size(), static_cast<size_t>(max_name_length));

  *output = StringPrintf("%s%s", dir_prefix, name.c_str());
  return true;
}

// TODO: use a configurable base prefix, and adjust callers to supply pass name.
/* Dump the CFG into a DOT graph */
void MIRGraph::DumpCFG(const char* dir_prefix, bool all_blocks, const char *suffix) {
  FILE* file;
  static AtomicInteger cnt(0);

  // Increment counter to get a unique file number.
  cnt++;
  int nr = cnt.LoadRelaxed();

  std::string fname(PrettyMethod(cu_->method_idx, *cu_->dex_file));
  ReplaceSpecialChars(fname);
  std::string fpath;
  if (!CreateDumpFile(fname, dir_prefix, GetBasicBlock(GetEntryBlock()->fall_through)->start_offset,
                      suffix, nr, &fpath)) {
    LOG(ERROR) << "Could not create dump file name for " << fname;
    return;
  }
  file = fopen(fpath.c_str(), "w");
  if (file == nullptr) {
    PLOG(ERROR) << "Could not open " << fpath << " for DumpCFG.";
    return;
  }
  fprintf(file, "digraph G {\n");

  fprintf(file, "  rankdir=TB\n");

  int num_blocks = all_blocks ? GetNumBlocks() : num_reachable_blocks_;
  int idx;

  for (idx = 0; idx < num_blocks; idx++) {
    int block_idx = all_blocks ? idx : dfs_order_[idx];
    BasicBlock* bb = GetBasicBlock(block_idx);
    if (bb == nullptr) continue;
    if (bb->block_type == kDead) continue;
    if (bb->hidden) continue;
    if (bb->block_type == kEntryBlock) {
      fprintf(file, "  entry_%d [shape=Mdiamond];\n", bb->id);
    } else if (bb->block_type == kExitBlock) {
      fprintf(file, "  exit_%d [shape=Mdiamond];\n", bb->id);
    } else if (bb->block_type == kDalvikByteCode) {
      fprintf(file, "  block%04x_%d [shape=record,label = \"{ \\\n",
              bb->start_offset, bb->id);
      const MIR* mir;
        fprintf(file, "    {block id %d\\l}%s\\\n", bb->id,
                bb->first_mir_insn ? " | " : " ");
        for (mir = bb->first_mir_insn; mir; mir = mir->next) {
            int opcode = mir->dalvikInsn.opcode;
            fprintf(file, "    {%04x %s %s %s %s %s %s %s %s %s\\l}%s\\\n", mir->offset,
                      mir->ssa_rep ? GetDalvikDisassembly(mir) :
                      !MIR::DecodedInstruction::IsPseudoMirOp(opcode) ?
                        Instruction::Name(mir->dalvikInsn.opcode) :
                        extended_mir_op_names_[opcode - kMirOpFirst],
                      (mir->optimization_flags & MIR_IGNORE_RANGE_CHECK) != 0 ? " no_rangecheck" : " ",
                      (mir->optimization_flags & MIR_IGNORE_NULL_CHECK) != 0 ? " no_nullcheck" : " ",
                      (mir->optimization_flags & MIR_IGNORE_SUSPEND_CHECK) != 0 ? " no_suspendcheck" : " ",
                      (mir->optimization_flags & MIR_STORE_NON_TEMPORAL) != 0 ? " non_temporal" : " ",
                      (mir->optimization_flags & MIR_CALLEE) != 0 ? " inlined" : " ",
                      (mir->optimization_flags & MIR_CLASS_IS_INITIALIZED) != 0 ? " cl_inited" : " ",
                      (mir->optimization_flags & MIR_CLASS_IS_IN_DEX_CACHE) != 0 ? " cl_in_cache" : " ",
                      (mir->optimization_flags & MIR_IGNORE_DIV_ZERO_CHECK) != 0 ? " no_div_check" : " ",
                      mir->next ? " | " : " ");
        }
        fprintf(file, "  }\"];\n\n");
    } else if (bb->block_type == kExceptionHandling) {
      char block_name[BLOCK_NAME_LEN];

      GetBlockName(bb, block_name);
      fprintf(file, "  %s [shape=invhouse];\n", block_name);
    }

    char block_name1[BLOCK_NAME_LEN], block_name2[BLOCK_NAME_LEN];

    if (bb->taken != NullBasicBlockId) {
      GetBlockName(bb, block_name1);
      GetBlockName(GetBasicBlock(bb->taken), block_name2);
      fprintf(file, "  %s:s -> %s:n [style=dotted]\n",
              block_name1, block_name2);
    }
    if (bb->fall_through != NullBasicBlockId) {
      GetBlockName(bb, block_name1);
      GetBlockName(GetBasicBlock(bb->fall_through), block_name2);
      fprintf(file, "  %s:s -> %s:n\n", block_name1, block_name2);
    }

    if (bb->successor_block_list_type != kNotUsed) {
      fprintf(file, "  succ%04x_%d [shape=%s,label = \"{ \\\n",
              bb->start_offset, bb->id,
              (bb->successor_block_list_type == kCatch) ?  "Mrecord" : "record");

      int last_succ_id = static_cast<int>(bb->successor_blocks.size() - 1u);
      int succ_id = 0;
      for (SuccessorBlockInfo* successor_block_info : bb->successor_blocks) {
        BasicBlock* dest_block = GetBasicBlock(successor_block_info->block);
        fprintf(file, "    {<f%d> %04x: %04x\\l}%s\\\n",
                succ_id,
                successor_block_info->key,
                dest_block->start_offset,
                (succ_id != last_succ_id) ? " | " : " ");
        ++succ_id;
      }
      fprintf(file, "  }\"];\n\n");

      GetBlockName(bb, block_name1);
      fprintf(file, "  %s:s -> succ%04x_%d:n [style=dashed]\n",
              block_name1, bb->start_offset, bb->id);

      // Link the successor pseudo-block with all of its potential targets.
      succ_id = 0;
      for (SuccessorBlockInfo* successor_block_info : bb->successor_blocks) {
        BasicBlock* dest_block = GetBasicBlock(successor_block_info->block);

        GetBlockName(dest_block, block_name2);
        fprintf(file, "  succ%04x_%d:f%d:e -> %s:n\n", bb->start_offset,
                bb->id, succ_id++, block_name2);
      }
    }
    fprintf(file, "\n");

    if (cu_->verbose) {
      /* Display the dominator tree */
      GetBlockName(bb, block_name1);
      fprintf(file, "  cfg%s [label=\"%s\", shape=none];\n",
              block_name1, block_name1);
      if (bb->i_dom) {
        GetBlockName(GetBasicBlock(bb->i_dom), block_name2);
        fprintf(file, "  cfg%s:s -> cfg%s:n\n\n", block_name2, block_name1);
      }
    }
  }
  fprintf(file, "}\n");
  fclose(file);
}

/* Insert an MIR instruction to the end of a basic block. */
void BasicBlock::AppendMIR(MIR* mir) {
  // Insert it after the last MIR.
  InsertMIRListAfter(last_mir_insn, mir, mir);
}

void BasicBlock::AppendMIRList(MIR* first_list_mir, MIR* last_list_mir) {
  // Insert it after the last MIR.
  InsertMIRListAfter(last_mir_insn, first_list_mir, last_list_mir);
}

void BasicBlock::AppendMIRList(const std::vector<MIR*>& insns) {
  for (std::vector<MIR*>::const_iterator it = insns.begin(); it != insns.end(); it++) {
    MIR* new_mir = *it;

    // Add a copy of each MIR.
    InsertMIRListAfter(last_mir_insn, new_mir, new_mir);
  }
}

/* Insert a MIR instruction after the specified MIR. */
void BasicBlock::InsertMIRAfter(MIR* current_mir, MIR* new_mir) {
  InsertMIRListAfter(current_mir, new_mir, new_mir);
}

void BasicBlock::InsertMIRListAfter(MIR* insert_after, MIR* first_list_mir, MIR* last_list_mir) {
  // If no MIR, we are done.
  if (first_list_mir == nullptr || last_list_mir == nullptr) {
    return;
  }

  // If insert_after is null, assume BB is empty.
  if (insert_after == nullptr) {
    first_mir_insn = first_list_mir;
    last_mir_insn = last_list_mir;
    last_list_mir->next = nullptr;
  } else {
    MIR* after_list = insert_after->next;
    insert_after->next = first_list_mir;
    last_list_mir->next = after_list;
    if (after_list == nullptr) {
      last_mir_insn = last_list_mir;
    }
  }

  // Set this BB to be the basic block of the MIRs.
  MIR* last = last_list_mir->next;
  for (MIR* mir = first_list_mir; mir != last; mir = mir->next) {
    mir->bb = id;
  }
}

/* Insert an MIR instruction to the head of a basic block. */
void BasicBlock::PrependMIR(MIR* mir) {
  InsertMIRListBefore(first_mir_insn, mir, mir);
}

void BasicBlock::PrependMIRList(MIR* first_list_mir, MIR* last_list_mir) {
  // Insert it before the first MIR.
  InsertMIRListBefore(first_mir_insn, first_list_mir, last_list_mir);
}

void BasicBlock::PrependMIRList(const std::vector<MIR*>& to_add) {
  for (std::vector<MIR*>::const_iterator it = to_add.begin(); it != to_add.end(); it++) {
    MIR* mir = *it;

    InsertMIRListBefore(first_mir_insn, mir, mir);
  }
}

/* Insert a MIR instruction before the specified MIR. */
void BasicBlock::InsertMIRBefore(MIR* current_mir, MIR* new_mir) {
  // Insert as a single element list.
  return InsertMIRListBefore(current_mir, new_mir, new_mir);
}

MIR* BasicBlock::FindPreviousMIR(MIR* mir) {
  MIR* current = first_mir_insn;

  while (current != nullptr) {
    MIR* next = current->next;

    if (next == mir) {
      return current;
    }

    current = next;
  }

  return nullptr;
}

void BasicBlock::InsertMIRListBefore(MIR* insert_before, MIR* first_list_mir, MIR* last_list_mir) {
  // If no MIR, we are done.
  if (first_list_mir == nullptr || last_list_mir == nullptr) {
    return;
  }

  // If insert_before is null, assume BB is empty.
  if (insert_before == nullptr) {
    first_mir_insn = first_list_mir;
    last_mir_insn = last_list_mir;
    last_list_mir->next = nullptr;
  } else {
    if (first_mir_insn == insert_before) {
      last_list_mir->next = first_mir_insn;
      first_mir_insn = first_list_mir;
    } else {
      // Find the preceding MIR.
      MIR* before_list = FindPreviousMIR(insert_before);
      DCHECK(before_list != nullptr);
      before_list->next = first_list_mir;
      last_list_mir->next = insert_before;
    }
  }

  // Set this BB to be the basic block of the MIRs.
  for (MIR* mir = first_list_mir; mir != last_list_mir->next; mir = mir->next) {
    mir->bb = id;
  }
}

bool BasicBlock::RemoveMIR(MIR* mir) {
  // Remove as a single element list.
  return RemoveMIRList(mir, mir);
}

bool BasicBlock::RemoveMIRList(MIR* first_list_mir, MIR* last_list_mir) {
  if (first_list_mir == nullptr) {
    return false;
  }

  // Try to find the MIR.
  MIR* before_list = nullptr;
  MIR* after_list = nullptr;

  // If we are removing from the beginning of the MIR list.
  if (first_mir_insn == first_list_mir) {
    before_list = nullptr;
  } else {
    before_list = FindPreviousMIR(first_list_mir);
    if (before_list == nullptr) {
      // We did not find the mir.
      return false;
    }
  }

  // Remove the BB information and also find the after_list.
  for (MIR* mir = first_list_mir; mir != last_list_mir->next; mir = mir->next) {
    mir->bb = NullBasicBlockId;
  }

  after_list = last_list_mir->next;

  // If there is nothing before the list, after_list is the first_mir.
  if (before_list == nullptr) {
    first_mir_insn = after_list;
  } else {
    before_list->next = after_list;
  }

  // If there is nothing after the list, before_list is last_mir.
  if (after_list == nullptr) {
    last_mir_insn = before_list;
  }

  return true;
}

MIR* BasicBlock::GetFirstNonPhiInsn() {
  MIR* mir = first_mir_insn;
  while (mir != nullptr && static_cast<int>(mir->dalvikInsn.opcode) == kMirOpPhi) {
    mir = mir->next;
  }
  return mir;
}

MIR* BasicBlock::GetNextUnconditionalMir(MIRGraph* mir_graph, MIR* current) {
  MIR* next_mir = nullptr;

  if (current != nullptr) {
    next_mir = current->next;
  }

  if (next_mir == nullptr) {
    // Only look for next MIR that follows unconditionally.
    if ((taken == NullBasicBlockId) && (fall_through != NullBasicBlockId)) {
      next_mir = mir_graph->GetBasicBlock(fall_through)->first_mir_insn;
    }
  }

  return next_mir;
}

static void FillTypeSizeString(uint32_t type_size, std::string* decoded_mir) {
  DCHECK(decoded_mir != nullptr);
  OpSize type = static_cast<OpSize>(type_size >> 16);
  uint16_t vect_size = (type_size & 0xFFFF);

  // Now print the type and vector size.
  std::stringstream ss;
  ss << " (type:";
  ss << type;
  ss << " vectsize:";
  ss << vect_size;
  ss << ")";

  decoded_mir->append(ss.str());
}

void MIRGraph::DisassembleExtendedInstr(const MIR* mir, std::string* decoded_mir) {
  DCHECK(decoded_mir != nullptr);
  int opcode = mir->dalvikInsn.opcode;
  SSARepresentation* ssa_rep = mir->ssa_rep;
  int defs = (ssa_rep != nullptr) ? ssa_rep->num_defs : 0;
  int uses = (ssa_rep != nullptr) ? ssa_rep->num_uses : 0;

  if (opcode < kMirOpFirst) {
    return;  // It is not an extended instruction.
  }

  decoded_mir->append(extended_mir_op_names_[opcode - kMirOpFirst]);

  switch (opcode) {
    case kMirOpPhi: {
      if (defs > 0 && uses > 0) {
        BasicBlockId* incoming = mir->meta.phi_incoming;
        decoded_mir->append(StringPrintf(" %s = (%s",
                           GetSSANameWithConst(ssa_rep->defs[0], true).c_str(),
                           GetSSANameWithConst(ssa_rep->uses[0], true).c_str()));
        decoded_mir->append(StringPrintf(":%d", incoming[0]));
        for (int i = 1; i < uses; i++) {
          decoded_mir->append(StringPrintf(", %s:%d", GetSSANameWithConst(ssa_rep->uses[i], true).c_str(), incoming[i]));
        }
        decoded_mir->append(")");
      }
      break;
    }
    case kMirOpCopy:
      if (ssa_rep != nullptr) {
        decoded_mir->append(" ");
        decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[0], false));
        if (defs > 1) {
          decoded_mir->append(", ");
          decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[1], false));
        }
        decoded_mir->append(" = ");
        decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[0], false));
        if (uses > 1) {
          decoded_mir->append(", ");
          decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[1], false));
        }
      } else {
        decoded_mir->append(StringPrintf(" v%d = v%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB));
      }
      break;
    case kMirOpFusedCmplFloat:
    case kMirOpFusedCmpgFloat:
    case kMirOpFusedCmplDouble:
    case kMirOpFusedCmpgDouble:
    case kMirOpFusedCmpLong:
      if (ssa_rep != nullptr) {
        decoded_mir->append(" ");
        decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[0], false));
        for (int i = 1; i < uses; i++) {
          decoded_mir->append(", ");
          decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[i], false));
        }
      } else {
        decoded_mir->append(StringPrintf(" v%d, v%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB));
      }
      break;
    case kMirOpMoveVector:
      decoded_mir->append(StringPrintf(" vect%d = vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB));
      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
      break;
    case kMirOpPackedAddition:
      decoded_mir->append(StringPrintf(" vect%d = vect%d + vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
      break;
    case kMirOpPackedMultiply:
      decoded_mir->append(StringPrintf(" vect%d = vect%d * vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
      break;
    case kMirOpPackedSubtract:
      decoded_mir->append(StringPrintf(" vect%d = vect%d - vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
      break;
    case kMirOpPackedAnd:
      decoded_mir->append(StringPrintf(" vect%d = vect%d & vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
      break;
    case kMirOpPackedOr:
      decoded_mir->append(StringPrintf(" vect%d = vect%d \\| vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
      break;
    case kMirOpPackedXor:
      decoded_mir->append(StringPrintf(" vect%d = vect%d ^ vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
      break;
    case kMirOpPackedShiftLeft:
      decoded_mir->append(StringPrintf(" vect%d = vect%d \\<\\< %d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
      break;
    case kMirOpPackedUnsignedShiftRight:
      decoded_mir->append(StringPrintf(" vect%d = vect%d \\>\\>\\> %d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
      break;
    case kMirOpPackedSignedShiftRight:
      decoded_mir->append(StringPrintf(" vect%d = vect%d \\>\\> %d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
      break;
    case kMirOpConstVector:
      decoded_mir->append(StringPrintf(" vect%d = %x, %x, %x, %x", mir->dalvikInsn.vA, mir->dalvikInsn.arg[0],
                                      mir->dalvikInsn.arg[1], mir->dalvikInsn.arg[2], mir->dalvikInsn.arg[3]));
      break;
    case kMirOpPackedSet:
      if (ssa_rep != nullptr) {
        decoded_mir->append(StringPrintf(" vect%d = %s", mir->dalvikInsn.vA,
              GetSSANameWithConst(ssa_rep->uses[0], false).c_str()));
        if (uses > 1) {
          decoded_mir->append(", ");
          decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[1], false));
        }
      } else {
        decoded_mir->append(StringPrintf(" vect%d = v%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB));
      }
      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
      break;
    case kMirOpPackedAddReduce:
      if (ssa_rep != nullptr) {
        decoded_mir->append(" ");
        decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[0], false));
        if (defs > 1) {
          decoded_mir->append(", ");
          decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[1], false));
        }
        decoded_mir->append(StringPrintf(" = vect%d + %s", mir->dalvikInsn.vB,
            GetSSANameWithConst(ssa_rep->uses[0], false).c_str()));
        if (uses > 1) {
          decoded_mir->append(", ");
          decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[1], false));
        }
      } else {
        decoded_mir->append(StringPrintf("v%d = vect%d + v%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB, mir->dalvikInsn.vA));
      }
      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
      break;
    case kMirOpPackedReduce:
      if (ssa_rep != nullptr) {
        decoded_mir->append(" ");
        decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[0], false));
        if (defs > 1) {
          decoded_mir->append(", ");
          decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[1], false));
        }
        decoded_mir->append(StringPrintf(" = vect%d (extr_idx:%d)", mir->dalvikInsn.vB, mir->dalvikInsn.arg[0]));
      } else {
        decoded_mir->append(StringPrintf(" v%d = vect%d (extr_idx:%d)", mir->dalvikInsn.vA,
                                         mir->dalvikInsn.vB, mir->dalvikInsn.arg[0]));
      }
      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
      break;
    case kMirOpReserveVectorRegisters:
    case kMirOpReturnVectorRegisters:
      decoded_mir->append(StringPrintf(" vect%d - vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB));
      break;
    case kMirOpMemBarrier: {
      decoded_mir->append(" type:");
      std::stringstream ss;
      ss << static_cast<MemBarrierKind>(mir->dalvikInsn.vA);
      decoded_mir->append(ss.str());
      break;
    }
    case kMirOpPackedArrayGet:
    case kMirOpPackedArrayPut:
      decoded_mir->append(StringPrintf(" vect%d", mir->dalvikInsn.vA));
      if (ssa_rep != nullptr) {
        decoded_mir->append(StringPrintf(", %s[%s]",
                                        GetSSANameWithConst(ssa_rep->uses[0], false).c_str(),
                                        GetSSANameWithConst(ssa_rep->uses[1], false).c_str()));
      } else {
        decoded_mir->append(StringPrintf(", v%d[v%d]", mir->dalvikInsn.vB, mir->dalvikInsn.vC));
      }
      FillTypeSizeString(mir->dalvikInsn.arg[0], decoded_mir);
      break;
    case kMirOpMaddInt:
    case kMirOpMsubInt:
    case kMirOpMaddLong:
    case kMirOpMsubLong:
      if (ssa_rep != nullptr) {
        decoded_mir->append(" ");
        decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[0], false));
        if (defs > 1) {
          decoded_mir->append(", ");
          decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[1], false));
        }
        for (int i = 0; i < uses; i++) {
          decoded_mir->append(", ");
          decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[i], false));
        }
      } else {
        decoded_mir->append(StringPrintf(" v%d, v%d, v%d, v%d",
                                         mir->dalvikInsn.vA, mir->dalvikInsn.vB,
                                         mir->dalvikInsn.vC, mir->dalvikInsn.arg[0]));
      }
      break;
    default:
      break;
  }
}

char* MIRGraph::GetDalvikDisassembly(const MIR* mir) {
  MIR::DecodedInstruction insn = mir->dalvikInsn;
  std::string str;
  int flags = 0;
  int opcode = insn.opcode;
  char* ret;
  bool nop = false;
  SSARepresentation* ssa_rep = mir->ssa_rep;
  Instruction::Format dalvik_format = Instruction::k10x;  // Default to no-operand format.

  // Handle special cases that recover the original dalvik instruction.
  if (opcode == kMirOpCheck) {
    str.append(extended_mir_op_names_[opcode - kMirOpFirst]);
    str.append(": ");
    // Recover the original Dex instruction.
    insn = mir->meta.throw_insn->dalvikInsn;
    ssa_rep = mir->meta.throw_insn->ssa_rep;
    opcode = insn.opcode;
  } else if (opcode == kMirOpNop) {
    str.append("[");
    if (mir->offset < current_code_item_->insns_size_in_code_units_) {
      // Recover original opcode.
      insn.opcode = Instruction::At(current_code_item_->insns_ + mir->offset)->Opcode();
      opcode = insn.opcode;
    }
    nop = true;
  }
  int defs = (ssa_rep != nullptr) ? ssa_rep->num_defs : 0;
  int uses = (ssa_rep != nullptr) ? ssa_rep->num_uses : 0;

  if (MIR::DecodedInstruction::IsPseudoMirOp(opcode)) {
    // Note that this does not check the MIR's opcode in all cases. In cases where it
    // recovered dalvik instruction, it uses opcode of that instead of the extended one.
    DisassembleExtendedInstr(mir, &str);
  } else {
    dalvik_format = Instruction::FormatOf(insn.opcode);
    flags = insn.FlagsOf();
    str.append(Instruction::Name(insn.opcode));

    // For invokes-style formats, treat wide regs as a pair of singles.
    bool show_singles = ((dalvik_format == Instruction::k35c) ||
                         (dalvik_format == Instruction::k3rc));
    if (defs != 0) {
      str.append(" ");
      str.append(GetSSANameWithConst(ssa_rep->defs[0], false));
      if (defs > 1) {
        str.append(", ");
        str.append(GetSSANameWithConst(ssa_rep->defs[1], false));
      }
      if (uses != 0) {
        str.append(", ");
      }
    }
    for (int i = 0; i < uses; i++) {
      str.append(" ");
      str.append(GetSSANameWithConst(ssa_rep->uses[i], show_singles));
      if (!show_singles && (reg_location_ != nullptr) && reg_location_[i].wide) {
        // For the listing, skip the high sreg.
        i++;
      }
      if (i != (uses - 1)) {
        str.append(",");
      }
    }

    switch (dalvik_format) {
      case Instruction::k11n:  // Add one immediate from vB.
      case Instruction::k21s:
      case Instruction::k31i:
      case Instruction::k21h:
        str.append(StringPrintf(", #0x%x", insn.vB));
        break;
      case Instruction::k51l:  // Add one wide immediate.
        str.append(StringPrintf(", #%" PRId64, insn.vB_wide));
        break;
      case Instruction::k21c:  // One register, one string/type/method index.
      case Instruction::k31c:
        str.append(StringPrintf(", index #0x%x", insn.vB));
        break;
      case Instruction::k22c:  // Two registers, one string/type/method index.
        str.append(StringPrintf(", index #0x%x", insn.vC));
        break;
      case Instruction::k22s:  // Add one immediate from vC.
      case Instruction::k22b:
        str.append(StringPrintf(", #0x%x", insn.vC));
        break;
      default:
        // Nothing left to print.
        break;
    }

    if ((flags & Instruction::kBranch) != 0) {
      // For branches, decode the instructions to print out the branch targets.
      int offset = 0;
      switch (dalvik_format) {
        case Instruction::k21t:
          offset = insn.vB;
          break;
        case Instruction::k22t:
          offset = insn.vC;
          break;
        case Instruction::k10t:
        case Instruction::k20t:
        case Instruction::k30t:
          offset = insn.vA;
          break;
        default:
          LOG(FATAL) << "Unexpected branch format " << dalvik_format << " from " << insn.opcode;
          break;
      }
      str.append(StringPrintf(", 0x%x (%c%x)", mir->offset + offset,
                              offset > 0 ? '+' : '-', offset > 0 ? offset : -offset));
    }

    if (nop) {
      str.append("]--optimized away");
    }
  }
  int length = str.length() + 1;
  ret = arena_->AllocArray<char>(length, kArenaAllocDFInfo);
  strncpy(ret, str.c_str(), length);
  return ret;
}

/* Turn method name into a legal Linux file name */
void MIRGraph::ReplaceSpecialChars(std::string& str) {
  static const struct { const char before; const char after; } match[] = {
    {'/', '-'}, {';', '#'}, {' ', '#'}, {'$', '+'},
    {'(', '@'}, {')', '@'}, {'<', '='}, {'>', '='}
  };
  for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) {
    std::replace(str.begin(), str.end(), match[i].before, match[i].after);
  }
}

std::string MIRGraph::GetSSAName(int ssa_reg) {
  // TODO: This value is needed for debugging. Currently, we compute this and then copy to the
  //       arena. We should be smarter and just place straight into the arena, or compute the
  //       value more lazily.
  int vreg = SRegToVReg(ssa_reg);
  if (vreg >= static_cast<int>(GetFirstTempVR())) {
    return StringPrintf("t%d_%d", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg));
  } else {
    return StringPrintf("v%d_%d", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg));
  }
}

// Similar to GetSSAName, but if ssa name represents an immediate show that as well.
std::string MIRGraph::GetSSANameWithConst(int ssa_reg, bool singles_only) {
  if (reg_location_ == nullptr) {
    // Pre-SSA - just use the standard name.
    return GetSSAName(ssa_reg);
  }
  if (IsConst(reg_location_[ssa_reg])) {
    if (!singles_only && reg_location_[ssa_reg].wide &&
        !reg_location_[ssa_reg].high_word) {
      return StringPrintf("v%d_%d#0x%" PRIx64, SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg),
                          ConstantValueWide(reg_location_[ssa_reg]));
    } else {
      return StringPrintf("v%d_%d#0x%x", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg),
                          ConstantValue(reg_location_[ssa_reg]));
    }
  } else {
    int vreg = SRegToVReg(ssa_reg);
    if (vreg >= static_cast<int>(GetFirstTempVR())) {
      return StringPrintf("t%d_%d", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg));
    } else {
      return StringPrintf("v%d_%d", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg));
    }
  }
}

void MIRGraph::GetBlockName(BasicBlock* bb, char* name) {
  switch (bb->block_type) {
    case kEntryBlock:
      snprintf(name, BLOCK_NAME_LEN, "entry_%d", bb->id);
      break;
    case kExitBlock:
      snprintf(name, BLOCK_NAME_LEN, "exit_%d", bb->id);
      break;
    case kDalvikByteCode:
      snprintf(name, BLOCK_NAME_LEN, "block%04x_%d", bb->start_offset, bb->id);
      break;
    case kExceptionHandling:
      snprintf(name, BLOCK_NAME_LEN, "exception%04x_%d", bb->start_offset,
               bb->id);
      break;
    default:
      snprintf(name, BLOCK_NAME_LEN, "_%d", bb->id);
      break;
  }
}

const char* MIRGraph::GetShortyFromMethodReference(const MethodReference& target_method) {
  const DexFile::MethodId& method_id =
      target_method.dex_file->GetMethodId(target_method.dex_method_index);
  return target_method.dex_file->GetShorty(method_id.proto_idx_);
}

/* Debug Utility - dump a compilation unit */
void MIRGraph::DumpMIRGraph() {
  const char* block_type_names[] = {
    "Null Block",
    "Entry Block",
    "Code Block",
    "Exit Block",
    "Exception Handling",
    "Catch Block"
  };

  LOG(INFO) << "Compiling " << PrettyMethod(cu_->method_idx, *cu_->dex_file);
  LOG(INFO) << GetInsns(0) << " insns";
  LOG(INFO) << GetNumBlocks() << " blocks in total";

  for (BasicBlock* bb : block_list_) {
    LOG(INFO) << StringPrintf("Block %d (%s) (insn %04x - %04x%s)",
        bb->id,
        block_type_names[bb->block_type],
        bb->start_offset,
        bb->last_mir_insn ? bb->last_mir_insn->offset : bb->start_offset,
        bb->last_mir_insn ? "" : " empty");
    if (bb->taken != NullBasicBlockId) {
      LOG(INFO) << "  Taken branch: block " << bb->taken
                << "(0x" << std::hex << GetBasicBlock(bb->taken)->start_offset << ")";
    }
    if (bb->fall_through != NullBasicBlockId) {
      LOG(INFO) << "  Fallthrough : block " << bb->fall_through
                << " (0x" << std::hex << GetBasicBlock(bb->fall_through)->start_offset << ")";
    }
  }
}

/*
 * Build an array of location records for the incoming arguments.
 * Note: one location record per word of arguments, with dummy
 * high-word loc for wide arguments.  Also pull up any following
 * MOVE_RESULT and incorporate it into the invoke.
 */
CallInfo* MIRGraph::NewMemCallInfo(BasicBlock* bb, MIR* mir, InvokeType type, bool is_range) {
  CallInfo* info = static_cast<CallInfo*>(arena_->Alloc(sizeof(CallInfo),
                                                        kArenaAllocMisc));
  MIR* move_result_mir = FindMoveResult(bb, mir);
  if (move_result_mir == nullptr) {
    info->result.location = kLocInvalid;
  } else {
    info->result = GetRawDest(move_result_mir);
    move_result_mir->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
  }
  info->num_arg_words = mir->ssa_rep->num_uses;
  info->args = (info->num_arg_words == 0) ? nullptr :
      arena_->AllocArray<RegLocation>(info->num_arg_words, kArenaAllocMisc);
  for (size_t i = 0; i < info->num_arg_words; i++) {
    info->args[i] = GetRawSrc(mir, i);
  }
  info->opt_flags = mir->optimization_flags;
  info->type = type;
  info->is_range = is_range;
  if (IsInstructionQuickInvoke(mir->dalvikInsn.opcode)) {
    const auto& method_info = GetMethodLoweringInfo(mir);
    info->method_ref = method_info.GetTargetMethod();
  } else {
    info->method_ref = MethodReference(GetCurrentDexCompilationUnit()->GetDexFile(),
                                       mir->dalvikInsn.vB);
  }
  info->index = mir->dalvikInsn.vB;
  info->offset = mir->offset;
  info->mir = mir;
  return info;
}

// Allocate a new MIR.
MIR* MIRGraph::NewMIR() {
  MIR* mir = new (arena_) MIR();
  return mir;
}

// Allocate a new basic block.
BasicBlock* MIRGraph::NewMemBB(BBType block_type, int block_id) {
  BasicBlock* bb = new (arena_) BasicBlock(block_id, block_type, arena_);

  // TUNING: better estimate of the exit block predecessors?
  bb->predecessors.reserve((block_type == kExitBlock) ? 2048 : 2);
  block_id_map_.Put(block_id, block_id);
  return bb;
}

void MIRGraph::InitializeConstantPropagation() {
  is_constant_v_ = new (arena_) ArenaBitVector(arena_, GetNumSSARegs(), false);
  constant_values_ = arena_->AllocArray<int>(GetNumSSARegs(), kArenaAllocDFInfo);
}

void MIRGraph::InitializeMethodUses() {
  // The gate starts by initializing the use counts.
  int num_ssa_regs = GetNumSSARegs();
  use_counts_.clear();
  use_counts_.reserve(num_ssa_regs + 32);
  use_counts_.resize(num_ssa_regs, 0u);
  raw_use_counts_.clear();
  raw_use_counts_.reserve(num_ssa_regs + 32);
  raw_use_counts_.resize(num_ssa_regs, 0u);
}

void MIRGraph::SSATransformationStart() {
  DCHECK(temp_scoped_alloc_.get() == nullptr);
  temp_scoped_alloc_.reset(ScopedArenaAllocator::Create(&cu_->arena_stack));
  temp_.ssa.num_vregs = GetNumOfCodeAndTempVRs();
  temp_.ssa.work_live_vregs = new (temp_scoped_alloc_.get()) ArenaBitVector(
      temp_scoped_alloc_.get(), temp_.ssa.num_vregs, false, kBitMapRegisterV);
}

void MIRGraph::SSATransformationEnd() {
  // Verify the dataflow information after the pass.
  if (cu_->enable_debug & (1 << kDebugVerifyDataflow)) {
    VerifyDataflow();
  }

  temp_.ssa.num_vregs = 0u;
  temp_.ssa.work_live_vregs = nullptr;
  DCHECK(temp_.ssa.def_block_matrix == nullptr);
  temp_.ssa.phi_node_blocks = nullptr;
  DCHECK(temp_scoped_alloc_.get() != nullptr);
  temp_scoped_alloc_.reset();

  // Update the maximum number of reachable blocks.
  max_num_reachable_blocks_ = num_reachable_blocks_;

  // Mark MIR SSA representations as up to date.
  mir_ssa_rep_up_to_date_ = true;
}

size_t MIRGraph::GetNumDalvikInsns() const {
  size_t cumulative_size = 0u;
  bool counted_current_item = false;
  const uint8_t size_for_null_code_item = 2u;

  for (auto it : m_units_) {
    const DexFile::CodeItem* code_item = it->GetCodeItem();
    // Even if the code item is null, we still count non-zero value so that
    // each m_unit is counted as having impact.
    cumulative_size += (code_item == nullptr ?
        size_for_null_code_item : code_item->insns_size_in_code_units_);
    if (code_item == current_code_item_) {
      counted_current_item = true;
    }
  }

  // If the current code item was not counted yet, count it now.
  // This can happen for example in unit tests where some fields like m_units_
  // are not initialized.
  if (counted_current_item == false) {
    cumulative_size += (current_code_item_ == nullptr ?
        size_for_null_code_item : current_code_item_->insns_size_in_code_units_);
  }

  return cumulative_size;
}

static BasicBlock* SelectTopologicalSortOrderFallBack(
    MIRGraph* mir_graph, const ArenaBitVector* current_loop,
    const ScopedArenaVector<size_t>* visited_cnt_values, ScopedArenaAllocator* allocator,
    ScopedArenaVector<BasicBlockId>* tmp_stack) {
  // No true loop head has been found but there may be true loop heads after the mess we need
  // to resolve. To avoid taking one of those, pick the candidate with the highest number of
  // reachable unvisited nodes. That candidate will surely be a part of a loop.
  BasicBlock* fall_back = nullptr;
  size_t fall_back_num_reachable = 0u;
  // Reuse the same bit vector for each candidate to mark reachable unvisited blocks.
  ArenaBitVector candidate_reachable(allocator, mir_graph->GetNumBlocks(), false, kBitMapMisc);
  AllNodesIterator iter(mir_graph);
  for (BasicBlock* candidate = iter.Next(); candidate != nullptr; candidate = iter.Next()) {
    if (candidate->hidden ||                            // Hidden, or
        candidate->visited ||                           // already processed, or
        (*visited_cnt_values)[candidate->id] == 0u ||   // no processed predecessors, or
        (current_loop != nullptr &&                     // outside current loop.
         !current_loop->IsBitSet(candidate->id))) {
      continue;
    }
    DCHECK(tmp_stack->empty());
    tmp_stack->push_back(candidate->id);
    candidate_reachable.ClearAllBits();
    size_t num_reachable = 0u;
    while (!tmp_stack->empty()) {
      BasicBlockId current_id = tmp_stack->back();
      tmp_stack->pop_back();
      BasicBlock* current_bb = mir_graph->GetBasicBlock(current_id);
      DCHECK(current_bb != nullptr);
      ChildBlockIterator child_iter(current_bb, mir_graph);
      BasicBlock* child_bb = child_iter.Next();
      for ( ; child_bb != nullptr; child_bb = child_iter.Next()) {
        DCHECK(!child_bb->hidden);
        if (child_bb->visited ||                            // Already processed, or
            (current_loop != nullptr &&                     // outside current loop.
             !current_loop->IsBitSet(child_bb->id))) {
          continue;
        }
        if (!candidate_reachable.IsBitSet(child_bb->id)) {
          candidate_reachable.SetBit(child_bb->id);
          tmp_stack->push_back(child_bb->id);
          num_reachable += 1u;
        }
      }
    }
    if (fall_back_num_reachable < num_reachable) {
      fall_back_num_reachable = num_reachable;
      fall_back = candidate;
    }
  }
  return fall_back;
}

// Compute from which unvisited blocks is bb_id reachable through unvisited blocks.
static void ComputeUnvisitedReachableFrom(MIRGraph* mir_graph, BasicBlockId bb_id,
                                          ArenaBitVector* reachable,
                                          ScopedArenaVector<BasicBlockId>* tmp_stack) {
  // NOTE: Loop heads indicated by the "visited" flag.
  DCHECK(tmp_stack->empty());
  reachable->ClearAllBits();
  tmp_stack->push_back(bb_id);
  while (!tmp_stack->empty()) {
    BasicBlockId current_id = tmp_stack->back();
    tmp_stack->pop_back();
    BasicBlock* current_bb = mir_graph->GetBasicBlock(current_id);
    DCHECK(current_bb != nullptr);
    for (BasicBlockId pred_id : current_bb->predecessors) {
      BasicBlock* pred_bb = mir_graph->GetBasicBlock(pred_id);
      DCHECK(pred_bb != nullptr);
      if (!pred_bb->visited && !reachable->IsBitSet(pred_bb->id)) {
        reachable->SetBit(pred_bb->id);
        tmp_stack->push_back(pred_bb->id);
      }
    }
  }
}

void MIRGraph::ComputeTopologicalSortOrder() {
  ScopedArenaAllocator allocator(&cu_->arena_stack);
  unsigned int num_blocks = GetNumBlocks();

  ScopedArenaQueue<BasicBlock*> q(allocator.Adapter());
  ScopedArenaVector<size_t> visited_cnt_values(num_blocks, 0u, allocator.Adapter());
  ScopedArenaVector<BasicBlockId> loop_head_stack(allocator.Adapter());
  size_t max_nested_loops = 0u;
  ArenaBitVector loop_exit_blocks(&allocator, num_blocks, false, kBitMapMisc);
  loop_exit_blocks.ClearAllBits();

  // Count the number of blocks to process and add the entry block(s).
  unsigned int num_blocks_to_process = 0u;
  for (BasicBlock* bb : block_list_) {
    if (bb->hidden == true) {
      continue;
    }

    num_blocks_to_process += 1u;

    if (bb->predecessors.size() == 0u) {
      // Add entry block to the queue.
      q.push(bb);
    }
  }

  // Clear the topological order arrays.
  topological_order_.clear();
  topological_order_.reserve(num_blocks);
  topological_order_loop_ends_.clear();
  topological_order_loop_ends_.resize(num_blocks, 0u);
  topological_order_indexes_.clear();
  topological_order_indexes_.resize(num_blocks, static_cast<uint16_t>(-1));

  // Mark all blocks as unvisited.
  ClearAllVisitedFlags();

  // For loop heads, keep track from which blocks they are reachable not going through other
  // loop heads. Other loop heads are excluded to detect the heads of nested loops. The children
  // in this set go into the loop body, the other children are jumping over the loop.
  ScopedArenaVector<ArenaBitVector*> loop_head_reachable_from(allocator.Adapter());
  loop_head_reachable_from.resize(num_blocks, nullptr);
  // Reuse the same temp stack whenever calculating a loop_head_reachable_from[loop_head_id].
  ScopedArenaVector<BasicBlockId> tmp_stack(allocator.Adapter());

  while (num_blocks_to_process != 0u) {
    BasicBlock* bb = nullptr;
    if (!q.empty()) {
      num_blocks_to_process -= 1u;
      // Get top.
      bb = q.front();
      q.pop();
      if (bb->visited) {
        // Loop head: it was already processed, mark end and copy exit blocks to the queue.
        DCHECK(q.empty()) << PrettyMethod(cu_->method_idx, *cu_->dex_file);
        uint16_t idx = static_cast<uint16_t>(topological_order_.size());
        topological_order_loop_ends_[topological_order_indexes_[bb->id]] = idx;
        DCHECK_EQ(loop_head_stack.back(), bb->id);
        loop_head_stack.pop_back();
        ArenaBitVector* reachable =
            loop_head_stack.empty() ? nullptr : loop_head_reachable_from[loop_head_stack.back()];
        for (BasicBlockId candidate_id : loop_exit_blocks.Indexes()) {
          if (reachable == nullptr || reachable->IsBitSet(candidate_id)) {
            q.push(GetBasicBlock(candidate_id));
            // NOTE: The BitVectorSet::IndexIterator will not check the pointed-to bit again,
            // so clearing the bit has no effect on the iterator.
            loop_exit_blocks.ClearBit(candidate_id);
          }
        }
        continue;
      }
    } else {
      // Find the new loop head.
      AllNodesIterator iter(this);
      while (true) {
        BasicBlock* candidate = iter.Next();
        if (candidate == nullptr) {
          // We did not find a true loop head, fall back to a reachable block in any loop.
          ArenaBitVector* current_loop =
              loop_head_stack.empty() ? nullptr : loop_head_reachable_from[loop_head_stack.back()];
          bb = SelectTopologicalSortOrderFallBack(this, current_loop, &visited_cnt_values,
                                                  &allocator, &tmp_stack);
          DCHECK(bb != nullptr) << PrettyMethod(cu_->method_idx, *cu_->dex_file);
          if (kIsDebugBuild && cu_->dex_file != nullptr) {
            LOG(INFO) << "Topological sort order: Using fall-back in "
                << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " BB #" << bb->id
                << " @0x" << std::hex << bb->start_offset
                << ", num_blocks = " << std::dec << num_blocks;
          }
          break;
        }
        if (candidate->hidden ||                            // Hidden, or
            candidate->visited ||                           // already processed, or
            visited_cnt_values[candidate->id] == 0u ||      // no processed predecessors, or
            (!loop_head_stack.empty() &&                    // outside current loop.
             !loop_head_reachable_from[loop_head_stack.back()]->IsBitSet(candidate->id))) {
          continue;
        }

        for (BasicBlockId pred_id : candidate->predecessors) {
          BasicBlock* pred_bb = GetBasicBlock(pred_id);
          DCHECK(pred_bb != nullptr);
          if (pred_bb != candidate && !pred_bb->visited &&
              !pred_bb->dominators->IsBitSet(candidate->id)) {
            candidate = nullptr;  // Set candidate to null to indicate failure.
            break;
          }
        }
        if (candidate != nullptr) {
          bb = candidate;
          break;
        }
      }
      // Compute blocks from which the loop head is reachable and process those blocks first.
      ArenaBitVector* reachable =
          new (&allocator) ArenaBitVector(&allocator, num_blocks, false, kBitMapMisc);
      loop_head_reachable_from[bb->id] = reachable;
      ComputeUnvisitedReachableFrom(this, bb->id, reachable, &tmp_stack);
      // Now mark as loop head. (Even if it's only a fall back when we don't find a true loop.)
      loop_head_stack.push_back(bb->id);
      max_nested_loops = std::max(max_nested_loops, loop_head_stack.size());
    }

    DCHECK_EQ(bb->hidden, false);
    DCHECK_EQ(bb->visited, false);
    bb->visited = true;
    bb->nesting_depth = loop_head_stack.size();

    // Now add the basic block.
    uint16_t idx = static_cast<uint16_t>(topological_order_.size());
    topological_order_indexes_[bb->id] = idx;
    topological_order_.push_back(bb->id);

    // Update visited_cnt_values for children.
    ChildBlockIterator succIter(bb, this);
    BasicBlock* successor = succIter.Next();
    for ( ; successor != nullptr; successor = succIter.Next()) {
      if (successor->hidden) {
        continue;
      }

      // One more predecessor was visited.
      visited_cnt_values[successor->id] += 1u;
      if (visited_cnt_values[successor->id] == successor->predecessors.size()) {
        if (loop_head_stack.empty() ||
            loop_head_reachable_from[loop_head_stack.back()]->IsBitSet(successor->id)) {
          q.push(successor);
        } else {
          DCHECK(!loop_exit_blocks.IsBitSet(successor->id));
          loop_exit_blocks.SetBit(successor->id);
        }
      }
    }
  }

  // Prepare the loop head stack for iteration.
  topological_order_loop_head_stack_.clear();
  topological_order_loop_head_stack_.reserve(max_nested_loops);
  max_nested_loops_ = max_nested_loops;
  topological_order_up_to_date_ = true;
}

bool BasicBlock::IsExceptionBlock() const {
  if (block_type == kExceptionHandling) {
    return true;
  }
  return false;
}

ChildBlockIterator::ChildBlockIterator(BasicBlock* bb, MIRGraph* mir_graph)
    : basic_block_(bb), mir_graph_(mir_graph), visited_fallthrough_(false),
      visited_taken_(false), have_successors_(false) {
  // Check if we actually do have successors.
  if (basic_block_ != 0 && basic_block_->successor_block_list_type != kNotUsed) {
    have_successors_ = true;
    successor_iter_ = basic_block_->successor_blocks.cbegin();
  }
}

BasicBlock* ChildBlockIterator::Next() {
  // We check if we have a basic block. If we don't we cannot get next child.
  if (basic_block_ == nullptr) {
    return nullptr;
  }

  // If we haven't visited fallthrough, return that.
  if (visited_fallthrough_ == false) {
    visited_fallthrough_ = true;

    BasicBlock* result = mir_graph_->GetBasicBlock(basic_block_->fall_through);
    if (result != nullptr) {
      return result;
    }
  }

  // If we haven't visited taken, return that.
  if (visited_taken_ == false) {
    visited_taken_ = true;

    BasicBlock* result = mir_graph_->GetBasicBlock(basic_block_->taken);
    if (result != nullptr) {
      return result;
    }
  }

  // We visited both taken and fallthrough. Now check if we have successors we need to visit.
  if (have_successors_ == true) {
    // Get information about next successor block.
    auto end = basic_block_->successor_blocks.cend();
    while (successor_iter_ != end) {
      SuccessorBlockInfo* successor_block_info = *successor_iter_;
      ++successor_iter_;
      // If block was replaced by zero block, take next one.
      if (successor_block_info->block != NullBasicBlockId) {
        return mir_graph_->GetBasicBlock(successor_block_info->block);
      }
    }
  }

  // We do not have anything.
  return nullptr;
}

BasicBlock* BasicBlock::Copy(CompilationUnit* c_unit) {
  MIRGraph* mir_graph = c_unit->mir_graph.get();
  return Copy(mir_graph);
}

BasicBlock* BasicBlock::Copy(MIRGraph* mir_graph) {
  BasicBlock* result_bb = mir_graph->CreateNewBB(block_type);

  // We don't do a memcpy style copy here because it would lead to a lot of things
  // to clean up. Let us do it by hand instead.
  // Copy in taken and fallthrough.
  result_bb->fall_through = fall_through;
  result_bb->taken = taken;

  // Copy successor links if needed.
  ArenaAllocator* arena = mir_graph->GetArena();

  result_bb->successor_block_list_type = successor_block_list_type;
  if (result_bb->successor_block_list_type != kNotUsed) {
    result_bb->successor_blocks.reserve(successor_blocks.size());
    for (SuccessorBlockInfo* sbi_old : successor_blocks) {
      SuccessorBlockInfo* sbi_new = static_cast<SuccessorBlockInfo*>(
          arena->Alloc(sizeof(SuccessorBlockInfo), kArenaAllocSuccessor));
      memcpy(sbi_new, sbi_old, sizeof(SuccessorBlockInfo));
      result_bb->successor_blocks.push_back(sbi_new);
    }
  }

  // Copy offset, method.
  result_bb->start_offset = start_offset;

  // Now copy instructions.
  for (MIR* mir = first_mir_insn; mir != 0; mir = mir->next) {
    // Get a copy first.
    MIR* copy = mir->Copy(mir_graph);

    // Append it.
    result_bb->AppendMIR(copy);
  }

  return result_bb;
}

MIR* MIR::Copy(MIRGraph* mir_graph) {
  MIR* res = mir_graph->NewMIR();
  *res = *this;

  // Remove links
  res->next = nullptr;
  res->bb = NullBasicBlockId;
  res->ssa_rep = nullptr;

  return res;
}

MIR* MIR::Copy(CompilationUnit* c_unit) {
  return Copy(c_unit->mir_graph.get());
}

uint32_t SSARepresentation::GetStartUseIndex(Instruction::Code opcode) {
  // Default result.
  int res = 0;

  // We are basically setting the iputs to their igets counterparts.
  switch (opcode) {
    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:
    case Instruction::APUT:
    case Instruction::APUT_OBJECT:
    case Instruction::APUT_BOOLEAN:
    case Instruction::APUT_BYTE:
    case Instruction::APUT_CHAR:
    case Instruction::APUT_SHORT:
    case Instruction::SPUT:
    case Instruction::SPUT_OBJECT:
    case Instruction::SPUT_BOOLEAN:
    case Instruction::SPUT_BYTE:
    case Instruction::SPUT_CHAR:
    case Instruction::SPUT_SHORT:
      // Skip the VR containing what to store.
      res = 1;
      break;
    case Instruction::IPUT_WIDE:
    case Instruction::IPUT_WIDE_QUICK:
    case Instruction::APUT_WIDE:
    case Instruction::SPUT_WIDE:
      // Skip the two VRs containing what to store.
      res = 2;
      break;
    default:
      // Do nothing in the general case.
      break;
  }

  return res;
}

/**
 * @brief Given a decoded instruction, it checks whether the instruction
 * sets a constant and if it does, more information is provided about the
 * constant being set.
 * @param ptr_value pointer to a 64-bit holder for the constant.
 * @param wide Updated by function whether a wide constant is being set by bytecode.
 * @return Returns false if the decoded instruction does not represent a constant bytecode.
 */
bool MIR::DecodedInstruction::GetConstant(int64_t* ptr_value, bool* wide) const {
  bool sets_const = true;
  int64_t value = vB;

  DCHECK(ptr_value != nullptr);
  DCHECK(wide != nullptr);

  switch (opcode) {
    case Instruction::CONST_4:
    case Instruction::CONST_16:
    case Instruction::CONST:
      *wide = false;
      value <<= 32;      // In order to get the sign extend.
      value >>= 32;
      break;
    case Instruction::CONST_HIGH16:
      *wide = false;
      value <<= 48;      // In order to get the sign extend.
      value >>= 32;
      break;
    case Instruction::CONST_WIDE_16:
    case Instruction::CONST_WIDE_32:
      *wide = true;
      value <<= 32;      // In order to get the sign extend.
      value >>= 32;
      break;
    case Instruction::CONST_WIDE:
      *wide = true;
      value = vB_wide;
      break;
    case Instruction::CONST_WIDE_HIGH16:
      *wide = true;
      value <<= 48;      // In order to get the sign extend.
      break;
    default:
      sets_const = false;
      break;
  }

  if (sets_const) {
    *ptr_value = value;
  }

  return sets_const;
}

void BasicBlock::ResetOptimizationFlags(uint16_t reset_flags) {
  // Reset flags for all MIRs in bb.
  for (MIR* mir = first_mir_insn; mir != nullptr; mir = mir->next) {
    mir->optimization_flags &= (~reset_flags);
  }
}

void BasicBlock::Kill(MIRGraph* mir_graph) {
  for (BasicBlockId pred_id : predecessors) {
    BasicBlock* pred_bb = mir_graph->GetBasicBlock(pred_id);
    DCHECK(pred_bb != nullptr);

    // Sadly we have to go through the children by hand here.
    pred_bb->ReplaceChild(id, NullBasicBlockId);
  }
  predecessors.clear();

  // Mark as dead and hidden.
  block_type = kDead;
  hidden = true;

  // Detach it from its MIRs so we don't generate code for them. Also detached MIRs
  // are updated to know that they no longer have a parent.
  for (MIR* mir = first_mir_insn; mir != nullptr; mir = mir->next) {
    mir->bb = NullBasicBlockId;
  }
  first_mir_insn = nullptr;
  last_mir_insn = nullptr;

  data_flow_info = nullptr;

  // Erase this bb from all children's predecessors and kill unreachable children.
  ChildBlockIterator iter(this, mir_graph);
  for (BasicBlock* succ_bb = iter.Next(); succ_bb != nullptr; succ_bb = iter.Next()) {
    succ_bb->ErasePredecessor(id);
  }

  // Remove links to children.
  fall_through = NullBasicBlockId;
  taken = NullBasicBlockId;
  successor_block_list_type = kNotUsed;

  if (kIsDebugBuild) {
    if (catch_entry) {
      DCHECK_EQ(mir_graph->catches_.count(start_offset), 1u);
      mir_graph->catches_.erase(start_offset);
    }
  }
}

bool BasicBlock::IsSSALiveOut(const CompilationUnit* c_unit, int ssa_reg) {
  // In order to determine if the ssa reg is live out, we scan all the MIRs. We remember
  // the last SSA number of the same dalvik register. At the end, if it is different than ssa_reg,
  // then it is not live out of this BB.
  int dalvik_reg = c_unit->mir_graph->SRegToVReg(ssa_reg);

  int last_ssa_reg = -1;

  // Walk through the MIRs backwards.
  for (MIR* mir = first_mir_insn; mir != nullptr; mir = mir->next) {
    // Get ssa rep.
    SSARepresentation *ssa_rep = mir->ssa_rep;

    // Go through the defines for this MIR.
    for (int i = 0; i < ssa_rep->num_defs; i++) {
      DCHECK(ssa_rep->defs != nullptr);

      // Get the ssa reg.
      int def_ssa_reg = ssa_rep->defs[i];

      // Get dalvik reg.
      int def_dalvik_reg = c_unit->mir_graph->SRegToVReg(def_ssa_reg);

      // Compare dalvik regs.
      if (dalvik_reg == def_dalvik_reg) {
        // We found a def of the register that we are being asked about.
        // Remember it.
        last_ssa_reg = def_ssa_reg;
      }
    }
  }

  if (last_ssa_reg == -1) {
    // If we get to this point we couldn't find a define of register user asked about.
    // Let's assume the user knows what he's doing so we can be safe and say that if we
    // couldn't find a def, it is live out.
    return true;
  }

  // If it is not -1, we found a match, is it ssa_reg?
  return (ssa_reg == last_ssa_reg);
}

bool BasicBlock::ReplaceChild(BasicBlockId old_bb, BasicBlockId new_bb) {
  // We need to check taken, fall_through, and successor_blocks to replace.
  bool found = false;
  if (taken == old_bb) {
    taken = new_bb;
    found = true;
  }

  if (fall_through == old_bb) {
    fall_through = new_bb;
    found = true;
  }

  if (successor_block_list_type != kNotUsed) {
    for (SuccessorBlockInfo* successor_block_info : successor_blocks) {
      if (successor_block_info->block == old_bb) {
        successor_block_info->block = new_bb;
        found = true;
      }
    }
  }

  return found;
}

void BasicBlock::ErasePredecessor(BasicBlockId old_pred) {
  auto pos = std::find(predecessors.begin(), predecessors.end(), old_pred);
  DCHECK(pos != predecessors.end());
  // It's faster to move the back() to *pos than erase(pos).
  *pos = predecessors.back();
  predecessors.pop_back();
  size_t idx = std::distance(predecessors.begin(), pos);
  for (MIR* mir = first_mir_insn; mir != nullptr; mir = mir->next) {
    if (static_cast<int>(mir->dalvikInsn.opcode) != kMirOpPhi) {
      break;
    }
    DCHECK_EQ(mir->ssa_rep->num_uses - 1u, predecessors.size());
    DCHECK_EQ(mir->meta.phi_incoming[idx], old_pred);
    mir->meta.phi_incoming[idx] = mir->meta.phi_incoming[predecessors.size()];
    mir->ssa_rep->uses[idx] = mir->ssa_rep->uses[predecessors.size()];
    mir->ssa_rep->num_uses = predecessors.size();
  }
}

void BasicBlock::UpdatePredecessor(BasicBlockId old_pred, BasicBlockId new_pred) {
  DCHECK_NE(new_pred, NullBasicBlockId);
  auto pos = std::find(predecessors.begin(), predecessors.end(), old_pred);
  DCHECK(pos != predecessors.end());
  *pos = new_pred;
  size_t idx = std::distance(predecessors.begin(), pos);
  for (MIR* mir = first_mir_insn; mir != nullptr; mir = mir->next) {
    if (static_cast<int>(mir->dalvikInsn.opcode) != kMirOpPhi) {
      break;
    }
    DCHECK_EQ(mir->meta.phi_incoming[idx], old_pred);
    mir->meta.phi_incoming[idx] = new_pred;
  }
}

// Create a new basic block with block_id as num_blocks_ that is
// post-incremented.
BasicBlock* MIRGraph::CreateNewBB(BBType block_type) {
  BasicBlockId id = static_cast<BasicBlockId>(block_list_.size());
  BasicBlock* res = NewMemBB(block_type, id);
  block_list_.push_back(res);
  return res;
}

void MIRGraph::CalculateBasicBlockInformation(const PassManager* const post_opt_pass_manager) {
  /* Create the pass driver and launch it */
  PassDriverMEPostOpt driver(post_opt_pass_manager, cu_);
  driver.Launch();
}

int MIR::DecodedInstruction::FlagsOf() const {
  // Calculate new index.
  int idx = static_cast<int>(opcode) - kNumPackedOpcodes;

  // Check if it is an extended or not.
  if (idx < 0) {
    return Instruction::FlagsOf(opcode);
  }

  // For extended, we use a switch.
  switch (static_cast<int>(opcode)) {
    case kMirOpPhi:
      return Instruction::kContinue;
    case kMirOpCopy:
      return Instruction::kContinue;
    case kMirOpFusedCmplFloat:
      return Instruction::kContinue | Instruction::kBranch;
    case kMirOpFusedCmpgFloat:
      return Instruction::kContinue | Instruction::kBranch;
    case kMirOpFusedCmplDouble:
      return Instruction::kContinue | Instruction::kBranch;
    case kMirOpFusedCmpgDouble:
      return Instruction::kContinue | Instruction::kBranch;
    case kMirOpFusedCmpLong:
      return Instruction::kContinue | Instruction::kBranch;
    case kMirOpNop:
      return Instruction::kContinue;
    case kMirOpNullCheck:
      return Instruction::kContinue | Instruction::kThrow;
    case kMirOpRangeCheck:
      return Instruction::kContinue | Instruction::kThrow;
    case kMirOpDivZeroCheck:
      return Instruction::kContinue | Instruction::kThrow;
    case kMirOpCheck:
      return Instruction::kContinue | Instruction::kThrow;
    case kMirOpSelect:
      return Instruction::kContinue;
    case kMirOpConstVector:
      return Instruction::kContinue;
    case kMirOpMoveVector:
      return Instruction::kContinue;
    case kMirOpPackedMultiply:
      return Instruction::kContinue;
    case kMirOpPackedAddition:
      return Instruction::kContinue;
    case kMirOpPackedSubtract:
      return Instruction::kContinue;
    case kMirOpPackedShiftLeft:
      return Instruction::kContinue;
    case kMirOpPackedSignedShiftRight:
      return Instruction::kContinue;
    case kMirOpPackedUnsignedShiftRight:
      return Instruction::kContinue;
    case kMirOpPackedAnd:
      return Instruction::kContinue;
    case kMirOpPackedOr:
      return Instruction::kContinue;
    case kMirOpPackedXor:
      return Instruction::kContinue;
    case kMirOpPackedAddReduce:
      return Instruction::kContinue;
    case kMirOpPackedReduce:
      return Instruction::kContinue;
    case kMirOpPackedSet:
      return Instruction::kContinue;
    case kMirOpReserveVectorRegisters:
      return Instruction::kContinue;
    case kMirOpReturnVectorRegisters:
      return Instruction::kContinue;
    case kMirOpMemBarrier:
      return Instruction::kContinue;
    case kMirOpPackedArrayGet:
      return Instruction::kContinue | Instruction::kThrow;
    case kMirOpPackedArrayPut:
      return Instruction::kContinue | Instruction::kThrow;
    case kMirOpMaddInt:
    case kMirOpMsubInt:
    case kMirOpMaddLong:
    case kMirOpMsubLong:
      return Instruction::kContinue;
    default:
      LOG(WARNING) << "ExtendedFlagsOf: Unhandled case: " << static_cast<int> (opcode);
      return 0;
  }
}

const uint16_t* MIRGraph::GetInsns(int m_unit_index) const {
  return m_units_[m_unit_index]->GetCodeItem()->insns_;
}

void MIRGraph::SetPuntToInterpreter(bool val) {
  punt_to_interpreter_ = val;
  if (val) {
    // Disable all subsequent optimizations. They may not be safe to run. (For example,
    // LVN/GVN assumes there are no conflicts found by the type inference pass.)
    cu_->disable_opt = ~static_cast<decltype(cu_->disable_opt)>(0);
  }
}

}  // namespace art
