mir_graph.cc revision 13735955f39b3b304c37d2b2840663c131262c18
1311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/*
2311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Copyright (C) 2013 The Android Open Source Project
3311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee *
4311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Licensed under the Apache License, Version 2.0 (the "License");
5311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * you may not use this file except in compliance with the License.
6311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * You may obtain a copy of the License at
7311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee *
8311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee *      http://www.apache.org/licenses/LICENSE-2.0
9311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee *
10311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Unless required by applicable law or agreed to in writing, software
11311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * distributed under the License is distributed on an "AS IS" BASIS,
12311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * See the License for the specific language governing permissions and
14311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * limitations under the License.
15311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee */
16311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
17f3e2cc4a38389aa75eb8ee3973a535254bf1c8d2Nicolas Geoffray#include "mir_graph.h"
18f3e2cc4a38389aa75eb8ee3973a535254bf1c8d2Nicolas Geoffray
19f3e2cc4a38389aa75eb8ee3973a535254bf1c8d2Nicolas Geoffray#include <inttypes.h>
2044e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler#include <queue>
21f3e2cc4a38389aa75eb8ee3973a535254bf1c8d2Nicolas Geoffray
22e77493c7217efdd1a0ecef521a6845a13da0305bIan Rogers#include "base/bit_vector-inl.h"
236282dc12440a2072dc06a616160027ff21bd895eIan Rogers#include "base/stl_util.h"
24311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee#include "compiler_internals.h"
25311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee#include "dex_file-inl.h"
2629a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers#include "dex_instruction-inl.h"
2795a059793c4c194f026afc74c713cc295d75d91aVladimir Marko#include "dex/global_value_numbering.h"
285816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko#include "dex/quick/dex_file_to_method_inliner_map.h"
295816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko#include "dex/quick/dex_file_method_inliner.h"
30f3e2cc4a38389aa75eb8ee3973a535254bf1c8d2Nicolas Geoffray#include "leb128.h"
312469e60e6ff08c2a0b4cd1e209246c5d91027679Jean Christophe Beyler#include "pass_driver_me_post_opt.h"
3253c913bb71b218714823c8c87a1f92830c336f61Andreas Gampe#include "stack.h"
33622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko#include "utils/scoped_arena_containers.h"
345816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko
35311ca169f4727d46a55bdc8dfa0059719fa72b65buzbeenamespace art {
36311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
37311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee#define MAX_PATTERN_LEN 5
38311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
391fd3346740dfb7f47be9922312b68a4227fada96buzbeeconst char* MIRGraph::extended_mir_op_names_[kMirOpLast - kMirOpFirst] = {
401fd3346740dfb7f47be9922312b68a4227fada96buzbee  "Phi",
411fd3346740dfb7f47be9922312b68a4227fada96buzbee  "Copy",
421fd3346740dfb7f47be9922312b68a4227fada96buzbee  "FusedCmplFloat",
431fd3346740dfb7f47be9922312b68a4227fada96buzbee  "FusedCmpgFloat",
441fd3346740dfb7f47be9922312b68a4227fada96buzbee  "FusedCmplDouble",
451fd3346740dfb7f47be9922312b68a4227fada96buzbee  "FusedCmpgDouble",
461fd3346740dfb7f47be9922312b68a4227fada96buzbee  "FusedCmpLong",
471fd3346740dfb7f47be9922312b68a4227fada96buzbee  "Nop",
481fd3346740dfb7f47be9922312b68a4227fada96buzbee  "OpNullCheck",
491fd3346740dfb7f47be9922312b68a4227fada96buzbee  "OpRangeCheck",
501fd3346740dfb7f47be9922312b68a4227fada96buzbee  "OpDivZeroCheck",
511fd3346740dfb7f47be9922312b68a4227fada96buzbee  "Check1",
521fd3346740dfb7f47be9922312b68a4227fada96buzbee  "Check2",
531fd3346740dfb7f47be9922312b68a4227fada96buzbee  "Select",
54d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "ConstVector",
55d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "MoveVector",
56d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedMultiply",
57d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedAddition",
58d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedSubtract",
59d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedShiftLeft",
60d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedSignedShiftRight",
61d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedUnsignedShiftRight",
62d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedAnd",
63d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedOr",
64d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedXor",
65d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedAddReduce",
66d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedReduce",
67d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedSet",
6860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  "ReserveVectorRegisters",
6960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  "ReturnVectorRegisters",
70b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler  "MemBarrier",
71b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A  "PackedArrayGet",
72b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A  "PackedArrayPut",
731fd3346740dfb7f47be9922312b68a4227fada96buzbee};
741fd3346740dfb7f47be9922312b68a4227fada96buzbee
75862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbeeMIRGraph::MIRGraph(CompilationUnit* cu, ArenaAllocator* arena)
761fd3346740dfb7f47be9922312b68a4227fada96buzbee    : reg_location_(NULL),
778081d2b8d7a743729557051d0294e040e61c747aVladimir Marko      block_id_map_(std::less<unsigned int>(), arena->Adapter()),
781fd3346740dfb7f47be9922312b68a4227fada96buzbee      cu_(cu),
79e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      ssa_base_vregs_(arena->Adapter(kArenaAllocSSAToDalvikMap)),
80e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      ssa_subscripts_(arena->Adapter(kArenaAllocSSAToDalvikMap)),
81311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      vreg_to_ssa_map_(NULL),
82311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      ssa_last_defs_(NULL),
83311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      is_constant_v_(NULL),
84311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      constant_values_(NULL),
85e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      use_counts_(arena->Adapter()),
86e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      raw_use_counts_(arena->Adapter()),
87311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      num_reachable_blocks_(0),
884896d7b6fb75add25f2d6ba84346ac83d8ba9d51Jean Christophe Beyler      max_num_reachable_blocks_(0),
89e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      dfs_order_(arena->Adapter(kArenaAllocDfsPreOrder)),
90e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      dfs_post_order_(arena->Adapter(kArenaAllocDfsPostOrder)),
91e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      dom_post_order_traversal_(arena->Adapter(kArenaAllocDomPostOrder)),
92e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      topological_order_(arena->Adapter(kArenaAllocTopologicalSortOrder)),
93e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      topological_order_loop_ends_(arena->Adapter(kArenaAllocTopologicalSortOrder)),
94e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      topological_order_indexes_(arena->Adapter(kArenaAllocTopologicalSortOrder)),
95e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      topological_order_loop_head_stack_(arena->Adapter(kArenaAllocTopologicalSortOrder)),
96311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      i_dom_list_(NULL),
97bfea9c29e809e04bde4a46591fea64c5a7b922fbVladimir Marko      temp_scoped_alloc_(),
98bfea9c29e809e04bde4a46591fea64c5a7b922fbVladimir Marko      temp_insn_data_(nullptr),
99bfea9c29e809e04bde4a46591fea64c5a7b922fbVladimir Marko      temp_bit_vector_size_(0u),
100bfea9c29e809e04bde4a46591fea64c5a7b922fbVladimir Marko      temp_bit_vector_(nullptr),
1015229cf17e3240d55f043c0a9308e22d967f897dcVladimir Marko      temp_bit_matrix_(nullptr),
10295a059793c4c194f026afc74c713cc295d75d91aVladimir Marko      temp_gvn_(),
103e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      block_list_(arena->Adapter(kArenaAllocBBList)),
104311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      try_block_addr_(NULL),
105311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      entry_block_(NULL),
106311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      exit_block_(NULL),
107311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      num_blocks_(0),
108311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      current_code_item_(NULL),
109e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      dex_pc_to_block_map_(arena->Adapter()),
1108081d2b8d7a743729557051d0294e040e61c747aVladimir Marko      m_units_(arena->Adapter()),
1118081d2b8d7a743729557051d0294e040e61c747aVladimir Marko      method_stack_(arena->Adapter()),
112311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      current_method_(kInvalidEntry),
113311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      current_offset_(kInvalidEntry),
114311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      def_count_(0),
115311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      opcode_count_(NULL),
1161fd3346740dfb7f47be9922312b68a4227fada96buzbee      num_ssa_regs_(0),
1178081d2b8d7a743729557051d0294e040e61c747aVladimir Marko      extended_basic_blocks_(arena->Adapter()),
1181fd3346740dfb7f47be9922312b68a4227fada96buzbee      method_sreg_(0),
119862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee      attributes_(METHOD_IS_LEAF),  // Start with leaf assumption, change on encountering invoke.
120862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee      checkstats_(NULL),
121b48819db07f9a0992a72173380c24249d7fc648abuzbee      arena_(arena),
122b48819db07f9a0992a72173380c24249d7fc648abuzbee      backward_branches_(0),
123da7a69b3fa7bb22d087567364b7eb5a75824efd8Razvan A Lupusoru      forward_branches_(0),
124da7a69b3fa7bb22d087567364b7eb5a75824efd8Razvan A Lupusoru      num_non_special_compiler_temps_(0),
1258d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru      max_available_special_compiler_temps_(1),  // We only need the method ptr as a special temp for now.
1268d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru      requested_backend_temp_(false),
1278d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru      compiler_temps_committed_(false),
128be0e546730e532ef0987cd4bde2c6f5a1b14dd2aVladimir Marko      punt_to_interpreter_(false),
1293d73ba2ce682edfaf41f29521bd6039c6499a1c5Vladimir Marko      merged_df_flags_(0u),
130e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      ifield_lowering_infos_(arena->Adapter(kArenaAllocLoweringInfo)),
131e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      sfield_lowering_infos_(arena->Adapter(kArenaAllocLoweringInfo)),
132e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      method_lowering_infos_(arena->Adapter(kArenaAllocLoweringInfo)),
133e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      gen_suspend_test_list_(arena->Adapter()) {
134e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  use_counts_.reserve(256);
135e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  raw_use_counts_.reserve(256);
136e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  block_list_.reserve(100);
137862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  try_block_addr_ = new (arena_) ArenaBitVector(arena_, 0, true /* expandable */);
1388d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru
1398d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru
1408d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru  if (cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) {
1418d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru    // X86 requires a temp to keep track of the method address.
1428d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru    // TODO For x86_64, addressing can be done with RIP. When that is implemented,
1438d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru    // this needs to be updated to reserve 0 temps for BE.
1448d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru    max_available_non_special_compiler_temps_ = cu_->target64 ? 2 : 1;
1458d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru    reserved_temps_for_backend_ = max_available_non_special_compiler_temps_;
1468d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru  } else {
1478d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru    // Other architectures do not have a known lower bound for non-special temps.
1488d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru    // We allow the update of the max to happen at BE initialization stage and simply set 0 for now.
1498d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru    max_available_non_special_compiler_temps_ = 0;
1508d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru    reserved_temps_for_backend_ = 0;
1518d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru  }
152311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
153311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
1546282dc12440a2072dc06a616160027ff21bd895eIan RogersMIRGraph::~MIRGraph() {
155e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  STLDeleteElements(&block_list_);
1566282dc12440a2072dc06a616160027ff21bd895eIan Rogers  STLDeleteElements(&m_units_);
1576282dc12440a2072dc06a616160027ff21bd895eIan Rogers}
1586282dc12440a2072dc06a616160027ff21bd895eIan Rogers
159311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/*
160311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Parse an instruction, return the length of the instruction
161311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee */
16229a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogersint MIRGraph::ParseInsn(const uint16_t* code_ptr, MIR::DecodedInstruction* decoded_instruction) {
16329a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  const Instruction* inst = Instruction::At(code_ptr);
16429a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  decoded_instruction->opcode = inst->Opcode();
16529a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  decoded_instruction->vA = inst->HasVRegA() ? inst->VRegA() : 0;
16629a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  decoded_instruction->vB = inst->HasVRegB() ? inst->VRegB() : 0;
16729a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  decoded_instruction->vB_wide = inst->HasWideVRegB() ? inst->WideVRegB() : 0;
16829a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  decoded_instruction->vC = inst->HasVRegC() ?  inst->VRegC() : 0;
16929a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  if (inst->HasVarArgs()) {
17029a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers    inst->GetVarArgs(decoded_instruction->arg);
17129a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  }
17229a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  return inst->SizeInCodeUnits();
173311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
174311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
175311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
176311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Split an existing block from the specified code offset into two */
1770d82948094d9a198e01aa95f64012bdedd5b6fc9buzbeeBasicBlock* MIRGraph::SplitBlock(DexOffset code_offset,
1782ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                 BasicBlock* orig_block, BasicBlock** immed_pred_block_p) {
1790d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  DCHECK_GT(code_offset, orig_block->start_offset);
180311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  MIR* insn = orig_block->first_mir_insn;
18133c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski  MIR* prev = NULL;  // Will be set to instruction before split.
182311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  while (insn) {
183311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (insn->offset == code_offset) break;
1840d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    prev = insn;
185311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    insn = insn->next;
186311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
187311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (insn == NULL) {
188311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    LOG(FATAL) << "Break split failed";
189311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
19033c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski  // Now insn is at the instruction where we want to split, namely
19133c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski  // insn will be the first instruction of the "bottom" block.
19233c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski  // Similarly, prev will be the last instruction of the "top" block
19333c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski
194e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  BasicBlock* bottom_block = CreateNewBB(kDalvikByteCode);
195311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
196311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  bottom_block->start_offset = code_offset;
197311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  bottom_block->first_mir_insn = insn;
198311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  bottom_block->last_mir_insn = orig_block->last_mir_insn;
199311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
20090223cc2e0bfb5a2b55e9ffed896ef327b9f3d2eJunmo Park  /* If this block was terminated by a return, conditional branch or throw,
20190223cc2e0bfb5a2b55e9ffed896ef327b9f3d2eJunmo Park   * the flag needs to go with the bottom block
20290223cc2e0bfb5a2b55e9ffed896ef327b9f3d2eJunmo Park   */
203311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  bottom_block->terminated_by_return = orig_block->terminated_by_return;
204311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  orig_block->terminated_by_return = false;
205311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
20690223cc2e0bfb5a2b55e9ffed896ef327b9f3d2eJunmo Park  bottom_block->conditional_branch = orig_block->conditional_branch;
20790223cc2e0bfb5a2b55e9ffed896ef327b9f3d2eJunmo Park  orig_block->conditional_branch = false;
20890223cc2e0bfb5a2b55e9ffed896ef327b9f3d2eJunmo Park
20990223cc2e0bfb5a2b55e9ffed896ef327b9f3d2eJunmo Park  bottom_block->explicit_throw = orig_block->explicit_throw;
21090223cc2e0bfb5a2b55e9ffed896ef327b9f3d2eJunmo Park  orig_block->explicit_throw = false;
21190223cc2e0bfb5a2b55e9ffed896ef327b9f3d2eJunmo Park
212311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /* Handle the taken path */
213311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  bottom_block->taken = orig_block->taken;
2140d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  if (bottom_block->taken != NullBasicBlockId) {
2150d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    orig_block->taken = NullBasicBlockId;
2160d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    BasicBlock* bb_taken = GetBasicBlock(bottom_block->taken);
217e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    bb_taken->ErasePredecessor(orig_block->id);
218e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    bb_taken->predecessors.push_back(bottom_block->id);
219311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
220311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
221311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /* Handle the fallthrough path */
222311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  bottom_block->fall_through = orig_block->fall_through;
2230d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  orig_block->fall_through = bottom_block->id;
224e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  bottom_block->predecessors.push_back(orig_block->id);
2250d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  if (bottom_block->fall_through != NullBasicBlockId) {
2260d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    BasicBlock* bb_fall_through = GetBasicBlock(bottom_block->fall_through);
227e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    bb_fall_through->ErasePredecessor(orig_block->id);
228e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    bb_fall_through->predecessors.push_back(bottom_block->id);
229311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
230311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
231311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /* Handle the successor list */
2320d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  if (orig_block->successor_block_list_type != kNotUsed) {
2330d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    bottom_block->successor_block_list_type = orig_block->successor_block_list_type;
234e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    bottom_block->successor_blocks.swap(orig_block->successor_blocks);
2350d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    orig_block->successor_block_list_type = kNotUsed;
236e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    DCHECK(orig_block->successor_blocks.empty());  // Empty after the swap() above.
237e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    for (SuccessorBlockInfo* successor_block_info : bottom_block->successor_blocks) {
2388512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      BasicBlock* bb = GetBasicBlock(successor_block_info->block);
239989367a47b015dd85f850cf756b436fb044b5aeaNiranjan Kumar      if (bb != nullptr) {
240e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko        bb->ErasePredecessor(orig_block->id);
241e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko        bb->predecessors.push_back(bottom_block->id);
242989367a47b015dd85f850cf756b436fb044b5aeaNiranjan Kumar      }
243311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
244311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
245311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
2460d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  orig_block->last_mir_insn = prev;
2473aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  prev->next = nullptr;
248311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
249311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /*
250311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * Update the immediate predecessor block pointer so that outgoing edges
251311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * can be applied to the proper block.
252311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   */
253311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (immed_pred_block_p) {
254311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    DCHECK_EQ(*immed_pred_block_p, orig_block);
255311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    *immed_pred_block_p = bottom_block;
256311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
257b48819db07f9a0992a72173380c24249d7fc648abuzbee
258b48819db07f9a0992a72173380c24249d7fc648abuzbee  // Associate dex instructions in the bottom block with the new container.
2594376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko  DCHECK(insn != nullptr);
2604376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko  DCHECK(insn != orig_block->first_mir_insn);
2614376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko  DCHECK(insn == bottom_block->first_mir_insn);
2624376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko  DCHECK_EQ(insn->offset, bottom_block->start_offset);
2634376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko  DCHECK(static_cast<int>(insn->dalvikInsn.opcode) == kMirOpCheck ||
2642ab40eb3c23559205ac7b9b039bd749458e8a761Jean Christophe Beyler         !MIR::DecodedInstruction::IsPseudoMirOp(insn->dalvikInsn.opcode));
265e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  DCHECK_EQ(dex_pc_to_block_map_[insn->offset], orig_block->id);
26633c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski  // Scan the "bottom" instructions, remapping them to the
26733c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski  // newly created "bottom" block.
2684376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko  MIR* p = insn;
26933c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski  p->bb = bottom_block->id;
270e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  dex_pc_to_block_map_[p->offset] = bottom_block->id;
2714376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko  while (p != bottom_block->last_mir_insn) {
2724376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko    p = p->next;
2734376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko    DCHECK(p != nullptr);
2743aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    p->bb = bottom_block->id;
275b48819db07f9a0992a72173380c24249d7fc648abuzbee    int opcode = p->dalvikInsn.opcode;
276b48819db07f9a0992a72173380c24249d7fc648abuzbee    /*
277b48819db07f9a0992a72173380c24249d7fc648abuzbee     * Some messiness here to ensure that we only enter real opcodes and only the
278b48819db07f9a0992a72173380c24249d7fc648abuzbee     * first half of a potentially throwing instruction that has been split into
2794376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko     * CHECK and work portions. Since the 2nd half of a split operation is always
2804376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko     * the first in a BasicBlock, we can't hit it here.
281b48819db07f9a0992a72173380c24249d7fc648abuzbee     */
2822ab40eb3c23559205ac7b9b039bd749458e8a761Jean Christophe Beyler    if ((opcode == kMirOpCheck) || !MIR::DecodedInstruction::IsPseudoMirOp(opcode)) {
28333c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski      BasicBlockId mapped_id = dex_pc_to_block_map_[p->offset];
28433c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski      // At first glance the instructions should all be mapped to orig_block.
28533c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski      // However, multiple instructions may correspond to the same dex, hence an earlier
28633c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski      // instruction may have already moved the mapping for dex to bottom_block.
28733c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski      DCHECK((mapped_id == orig_block->id) || (mapped_id == bottom_block->id));
288e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      dex_pc_to_block_map_[p->offset] = bottom_block->id;
289b48819db07f9a0992a72173380c24249d7fc648abuzbee    }
290b48819db07f9a0992a72173380c24249d7fc648abuzbee  }
291b48819db07f9a0992a72173380c24249d7fc648abuzbee
292311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  return bottom_block;
293311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
294311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
295311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/*
296311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Given a code offset, find out the block that starts with it. If the offset
297311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * is in the middle of an existing block, split it into two.  If immed_pred_block_p
298311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * is not non-null and is the block being split, update *immed_pred_block_p to
299311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * point to the bottom block so that outgoing edges can be set up properly
300311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * (by the caller)
301311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Utilizes a map for fast lookup of the typical cases.
302311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee */
3030d82948094d9a198e01aa95f64012bdedd5b6fc9buzbeeBasicBlock* MIRGraph::FindBlock(DexOffset code_offset, bool split, bool create,
3042ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                BasicBlock** immed_pred_block_p) {
30509ae022f55ab27edf4802baf7a05e76d7dc823a9Razvan A Lupusoru  if (code_offset >= current_code_item_->insns_size_in_code_units_) {
306311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    return NULL;
307311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
308b48819db07f9a0992a72173380c24249d7fc648abuzbee
309e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  int block_id = dex_pc_to_block_map_[code_offset];
310e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  BasicBlock* bb = GetBasicBlock(block_id);
311b48819db07f9a0992a72173380c24249d7fc648abuzbee
312b48819db07f9a0992a72173380c24249d7fc648abuzbee  if ((bb != NULL) && (bb->start_offset == code_offset)) {
313b48819db07f9a0992a72173380c24249d7fc648abuzbee    // Does this containing block start with the desired instruction?
314bd663de599b16229085759366c56e2ed5a1dc7ecbuzbee    return bb;
315bd663de599b16229085759366c56e2ed5a1dc7ecbuzbee  }
316311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
317b48819db07f9a0992a72173380c24249d7fc648abuzbee  // No direct hit.
318b48819db07f9a0992a72173380c24249d7fc648abuzbee  if (!create) {
319b48819db07f9a0992a72173380c24249d7fc648abuzbee    return NULL;
320b48819db07f9a0992a72173380c24249d7fc648abuzbee  }
321b48819db07f9a0992a72173380c24249d7fc648abuzbee
322b48819db07f9a0992a72173380c24249d7fc648abuzbee  if (bb != NULL) {
323b48819db07f9a0992a72173380c24249d7fc648abuzbee    // The target exists somewhere in an existing block.
324b48819db07f9a0992a72173380c24249d7fc648abuzbee    return SplitBlock(code_offset, bb, bb == *immed_pred_block_p ?  immed_pred_block_p : NULL);
325311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
326311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
327b48819db07f9a0992a72173380c24249d7fc648abuzbee  // Create a new block.
328e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  bb = CreateNewBB(kDalvikByteCode);
329311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  bb->start_offset = code_offset;
330e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  dex_pc_to_block_map_[bb->start_offset] = bb->id;
331311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  return bb;
332311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
333311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
334b48819db07f9a0992a72173380c24249d7fc648abuzbee
335311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Identify code range in try blocks and set up the empty catch blocks */
3362ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MIRGraph::ProcessTryCatchBlocks() {
337311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  int tries_size = current_code_item_->tries_size_;
3380d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  DexOffset offset;
339311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
340311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (tries_size == 0) {
341311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    return;
342311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
343311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
344311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  for (int i = 0; i < tries_size; i++) {
345311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    const DexFile::TryItem* pTry =
346311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        DexFile::GetTryItems(*current_code_item_, i);
3470d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    DexOffset start_offset = pTry->start_addr_;
3480d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    DexOffset end_offset = start_offset + pTry->insn_count_;
349311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    for (offset = start_offset; offset < end_offset; offset++) {
350862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee      try_block_addr_->SetBit(offset);
351311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
352311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
353311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
3548512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Iterate over each of the handlers to enqueue the empty Catch blocks.
35513735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(*current_code_item_, 0);
356311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
357311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  for (uint32_t idx = 0; idx < handlers_size; idx++) {
358311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    CatchHandlerIterator iterator(handlers_ptr);
359311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    for (; iterator.HasNext(); iterator.Next()) {
360311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      uint32_t address = iterator.GetHandlerAddress();
361311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      FindBlock(address, false /* split */, true /*create*/,
362311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                /* immed_pred_block_p */ NULL);
363311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
364311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    handlers_ptr = iterator.EndDataPointer();
365311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
366311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
367311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
368e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Markobool MIRGraph::IsBadMonitorExitCatch(NarrowDexOffset monitor_exit_offset,
369e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko                                     NarrowDexOffset catch_offset) {
370e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  // Catches for monitor-exit during stack unwinding have the pattern
371e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  //   move-exception (move)* (goto)? monitor-exit throw
372e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  // In the currently generated dex bytecode we see these catching a bytecode range including
373e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  // either its own or an identical monitor-exit, http://b/15745363 . This function checks if
374e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  // it's the case for a given monitor-exit and catch block so that we can ignore it.
375e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  // (We don't want to ignore all monitor-exit catches since one could enclose a synchronized
376e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  // block in a try-block and catch the NPE, Error or Throwable and we should let it through;
377e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  // even though a throwing monitor-exit certainly indicates a bytecode error.)
37809ae022f55ab27edf4802baf7a05e76d7dc823a9Razvan A Lupusoru  const Instruction* monitor_exit = Instruction::At(current_code_item_->insns_ + monitor_exit_offset);
379e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  DCHECK(monitor_exit->Opcode() == Instruction::MONITOR_EXIT);
380e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  int monitor_reg = monitor_exit->VRegA_11x();
38109ae022f55ab27edf4802baf7a05e76d7dc823a9Razvan A Lupusoru  const Instruction* check_insn = Instruction::At(current_code_item_->insns_ + catch_offset);
382e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  DCHECK(check_insn->Opcode() == Instruction::MOVE_EXCEPTION);
383e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  if (check_insn->VRegA_11x() == monitor_reg) {
384e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    // Unexpected move-exception to the same register. Probably not the pattern we're looking for.
385e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    return false;
386e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  }
387e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  check_insn = check_insn->Next();
388e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  while (true) {
389e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    int dest = -1;
390e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    bool wide = false;
391e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    switch (check_insn->Opcode()) {
392e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::MOVE_WIDE:
393e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        wide = true;
394e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        // Intentional fall-through.
395e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::MOVE_OBJECT:
396e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::MOVE:
397e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        dest = check_insn->VRegA_12x();
398e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        break;
399e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko
400e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::MOVE_WIDE_FROM16:
401e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        wide = true;
402e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        // Intentional fall-through.
403e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::MOVE_OBJECT_FROM16:
404e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::MOVE_FROM16:
405e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        dest = check_insn->VRegA_22x();
406e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        break;
407e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko
408e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::MOVE_WIDE_16:
409e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        wide = true;
410e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        // Intentional fall-through.
411e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::MOVE_OBJECT_16:
412e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::MOVE_16:
413e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        dest = check_insn->VRegA_32x();
414e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        break;
415e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko
416e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::GOTO:
417e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::GOTO_16:
418e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::GOTO_32:
419e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        check_insn = check_insn->RelativeAt(check_insn->GetTargetOffset());
420e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        // Intentional fall-through.
421e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      default:
422e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        return check_insn->Opcode() == Instruction::MONITOR_EXIT &&
423e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko            check_insn->VRegA_11x() == monitor_reg;
424e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    }
425e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko
426e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    if (dest == monitor_reg || (wide && dest + 1 == monitor_reg)) {
427e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      return false;
428e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    }
429e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko
430e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    check_insn = check_insn->Next();
431e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  }
432e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko}
433e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko
434311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Process instructions with the kBranch flag */
4350d82948094d9a198e01aa95f64012bdedd5b6fc9buzbeeBasicBlock* MIRGraph::ProcessCanBranch(BasicBlock* cur_block, MIR* insn, DexOffset cur_offset,
4360d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee                                       int width, int flags, const uint16_t* code_ptr,
4372ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                       const uint16_t* code_end) {
4380d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  DexOffset target = cur_offset;
439311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  switch (insn->dalvikInsn.opcode) {
440311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::GOTO:
441311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::GOTO_16:
442311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::GOTO_32:
443311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      target += insn->dalvikInsn.vA;
444311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      break;
445311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_EQ:
446311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_NE:
447311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_LT:
448311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_GE:
449311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_GT:
450311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_LE:
451311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      cur_block->conditional_branch = true;
452311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      target += insn->dalvikInsn.vC;
453311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      break;
454311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_EQZ:
455311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_NEZ:
456311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_LTZ:
457311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_GEZ:
458311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_GTZ:
459311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_LEZ:
460311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      cur_block->conditional_branch = true;
461311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      target += insn->dalvikInsn.vB;
462311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      break;
463311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    default:
464311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      LOG(FATAL) << "Unexpected opcode(" << insn->dalvikInsn.opcode << ") with kBranch set";
465311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
466b48819db07f9a0992a72173380c24249d7fc648abuzbee  CountBranch(target);
4678512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  BasicBlock* taken_block = FindBlock(target, /* split */ true, /* create */ true,
468311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                      /* immed_pred_block_p */ &cur_block);
4690d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  cur_block->taken = taken_block->id;
470e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  taken_block->predecessors.push_back(cur_block->id);
471311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
472311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /* Always terminate the current block for conditional branches */
473311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (flags & Instruction::kContinue) {
4742469e60e6ff08c2a0b4cd1e209246c5d91027679Jean Christophe Beyler    BasicBlock* fallthrough_block = FindBlock(cur_offset +  width,
475311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                             /*
476311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                              * If the method is processed
477311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                              * in sequential order from the
478311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                              * beginning, we don't need to
479311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                              * specify split for continue
480311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                              * blocks. However, this
481311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                              * routine can be called by
482311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                              * compileLoop, which starts
483311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                              * parsing the method from an
484311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                              * arbitrary address in the
485311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                              * method body.
486311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                              */
487311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                             true,
488311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                             /* create */
489311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                             true,
490311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                             /* immed_pred_block_p */
491311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                             &cur_block);
4920d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    cur_block->fall_through = fallthrough_block->id;
493e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    fallthrough_block->predecessors.push_back(cur_block->id);
494311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  } else if (code_ptr < code_end) {
4952724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee    FindBlock(cur_offset + width, /* split */ false, /* create */ true,
496311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                /* immed_pred_block_p */ NULL);
497311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
498311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  return cur_block;
499311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
500311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
501311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Process instructions with the kSwitch flag */
50217189ac098b2f156713db1821b49db7b2f018bbebuzbeeBasicBlock* MIRGraph::ProcessCanSwitch(BasicBlock* cur_block, MIR* insn, DexOffset cur_offset,
50317189ac098b2f156713db1821b49db7b2f018bbebuzbee                                       int width, int flags) {
504311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  const uint16_t* switch_data =
505311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      reinterpret_cast<const uint16_t*>(GetCurrentInsns() + cur_offset + insn->dalvikInsn.vB);
506311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  int size;
507311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  const int* keyTable;
508311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  const int* target_table;
509311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  int i;
510311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  int first_key;
511311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
512311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /*
513311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * Packed switch data format:
514311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *  ushort ident = 0x0100   magic value
515311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *  ushort size             number of entries in the table
516311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *  int first_key           first (and lowest) switch case value
517311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *  int targets[size]       branch targets, relative to switch opcode
518311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *
519311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * Total size is (4+size*2) 16-bit code units.
520311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   */
521311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) {
522311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    DCHECK_EQ(static_cast<int>(switch_data[0]),
523311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee              static_cast<int>(Instruction::kPackedSwitchSignature));
524311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    size = switch_data[1];
525311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    first_key = switch_data[2] | (switch_data[3] << 16);
526311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    target_table = reinterpret_cast<const int*>(&switch_data[4]);
5278512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    keyTable = NULL;        // Make the compiler happy.
528311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /*
529311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * Sparse switch data format:
530311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *  ushort ident = 0x0200   magic value
531311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *  ushort size             number of entries in the table; > 0
532311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *  int keys[size]          keys, sorted low-to-high; 32-bit aligned
533311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *  int targets[size]       branch targets, relative to switch opcode
534311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *
535311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * Total size is (2+size*4) 16-bit code units.
536311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   */
537311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  } else {
538311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    DCHECK_EQ(static_cast<int>(switch_data[0]),
539311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee              static_cast<int>(Instruction::kSparseSwitchSignature));
540311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    size = switch_data[1];
541311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    keyTable = reinterpret_cast<const int*>(&switch_data[2]);
542311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    target_table = reinterpret_cast<const int*>(&switch_data[2 + size*2]);
5438512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    first_key = 0;   // To make the compiler happy.
544311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
545311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
5460d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  if (cur_block->successor_block_list_type != kNotUsed) {
547311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    LOG(FATAL) << "Successor block list already in use: "
5480d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee               << static_cast<int>(cur_block->successor_block_list_type);
549311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
5500d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  cur_block->successor_block_list_type =
5510d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee      (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?  kPackedSwitch : kSparseSwitch;
552e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  cur_block->successor_blocks.reserve(size);
553311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
554311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  for (i = 0; i < size; i++) {
5558512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    BasicBlock* case_block = FindBlock(cur_offset + target_table[i], /* split */ true,
556311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                      /* create */ true, /* immed_pred_block_p */ &cur_block);
5578512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    SuccessorBlockInfo* successor_block_info =
558f6c4b3ba3825de1dbb3e747a68b809c6cc8eb4dbMathieu Chartier        static_cast<SuccessorBlockInfo*>(arena_->Alloc(sizeof(SuccessorBlockInfo),
55983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko                                                       kArenaAllocSuccessor));
5600d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    successor_block_info->block = case_block->id;
561311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    successor_block_info->key =
562311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
563311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        first_key + i : keyTable[i];
564e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    cur_block->successor_blocks.push_back(successor_block_info);
565e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    case_block->predecessors.push_back(cur_block->id);
566311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
567311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
568311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /* Fall-through case */
569df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  BasicBlock* fallthrough_block = FindBlock(cur_offset +  width, /* split */ false,
570df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom                                            /* create */ true, /* immed_pred_block_p */ NULL);
5710d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  cur_block->fall_through = fallthrough_block->id;
572e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  fallthrough_block->predecessors.push_back(cur_block->id);
57317189ac098b2f156713db1821b49db7b2f018bbebuzbee  return cur_block;
574311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
575311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
576311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Process instructions with the kThrow flag */
5770d82948094d9a198e01aa95f64012bdedd5b6fc9buzbeeBasicBlock* MIRGraph::ProcessCanThrow(BasicBlock* cur_block, MIR* insn, DexOffset cur_offset,
5780d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee                                      int width, int flags, ArenaBitVector* try_block_addr,
5792ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                      const uint16_t* code_ptr, const uint16_t* code_end) {
580862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  bool in_try_block = try_block_addr->IsBitSet(cur_offset);
58117189ac098b2f156713db1821b49db7b2f018bbebuzbee  bool is_throw = (insn->dalvikInsn.opcode == Instruction::THROW);
582311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
583311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /* In try block */
584311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (in_try_block) {
585311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    CatchHandlerIterator iterator(*current_code_item_, cur_offset);
586311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
5870d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    if (cur_block->successor_block_list_type != kNotUsed) {
588311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      LOG(INFO) << PrettyMethod(cu_->method_idx, *cu_->dex_file);
589311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      LOG(FATAL) << "Successor block list already in use: "
5900d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee                 << static_cast<int>(cur_block->successor_block_list_type);
591311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
592311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
59302c8cc6d1312a2b55533f02f6369dc7c94672f90Brian Carlstrom    for (; iterator.HasNext(); iterator.Next()) {
5948512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      BasicBlock* catch_block = FindBlock(iterator.GetHandlerAddress(), false /* split*/,
595311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                         false /* creat */, NULL  /* immed_pred_block_p */);
596e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      if (insn->dalvikInsn.opcode == Instruction::MONITOR_EXIT &&
597e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko          IsBadMonitorExitCatch(insn->offset, catch_block->start_offset)) {
598e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        // Don't allow monitor-exit to catch its own exception, http://b/15745363 .
599e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        continue;
600e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      }
601e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      if (cur_block->successor_block_list_type == kNotUsed) {
602e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        cur_block->successor_block_list_type = kCatch;
603e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      }
604311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      catch_block->catch_entry = true;
605311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      if (kIsDebugBuild) {
606311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        catches_.insert(catch_block->start_offset);
607311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      }
6088512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      SuccessorBlockInfo* successor_block_info = reinterpret_cast<SuccessorBlockInfo*>
60983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko          (arena_->Alloc(sizeof(SuccessorBlockInfo), kArenaAllocSuccessor));
6100d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee      successor_block_info->block = catch_block->id;
611311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      successor_block_info->key = iterator.GetHandlerTypeIndex();
612e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      cur_block->successor_blocks.push_back(successor_block_info);
613e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      catch_block->predecessors.push_back(cur_block->id);
614311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
615e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    in_try_block = (cur_block->successor_block_list_type != kNotUsed);
616e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  }
617e767f6ce3997f7634b26e7651bc7b90c060d3965Vladimir Marko  bool build_all_edges =
618e767f6ce3997f7634b26e7651bc7b90c060d3965Vladimir Marko      (cu_->disable_opt & (1 << kSuppressExceptionEdges)) || is_throw || in_try_block;
619e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  if (!in_try_block && build_all_edges) {
620e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    BasicBlock* eh_block = CreateNewBB(kExceptionHandling);
6210d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    cur_block->taken = eh_block->id;
622311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    eh_block->start_offset = cur_offset;
623e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    eh_block->predecessors.push_back(cur_block->id);
624311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
625311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
62617189ac098b2f156713db1821b49db7b2f018bbebuzbee  if (is_throw) {
627311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    cur_block->explicit_throw = true;
6282724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee    if (code_ptr < code_end) {
6298512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      // Force creation of new block following THROW via side-effect.
630311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      FindBlock(cur_offset + width, /* split */ false, /* create */ true,
631311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                /* immed_pred_block_p */ NULL);
632311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
633311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (!in_try_block) {
634311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       // Don't split a THROW that can't rethrow - we're done.
635311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      return cur_block;
636311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
637311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
638311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
63917189ac098b2f156713db1821b49db7b2f018bbebuzbee  if (!build_all_edges) {
64017189ac098b2f156713db1821b49db7b2f018bbebuzbee    /*
64117189ac098b2f156713db1821b49db7b2f018bbebuzbee     * Even though there is an exception edge here, control cannot return to this
64217189ac098b2f156713db1821b49db7b2f018bbebuzbee     * method.  Thus, for the purposes of dataflow analysis and optimization, we can
64317189ac098b2f156713db1821b49db7b2f018bbebuzbee     * ignore the edge.  Doing this reduces compile time, and increases the scope
64417189ac098b2f156713db1821b49db7b2f018bbebuzbee     * of the basic-block level optimization pass.
64517189ac098b2f156713db1821b49db7b2f018bbebuzbee     */
64617189ac098b2f156713db1821b49db7b2f018bbebuzbee    return cur_block;
64717189ac098b2f156713db1821b49db7b2f018bbebuzbee  }
64817189ac098b2f156713db1821b49db7b2f018bbebuzbee
649311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /*
650311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * Split the potentially-throwing instruction into two parts.
651311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * The first half will be a pseudo-op that captures the exception
652311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * edges and terminates the basic block.  It always falls through.
653311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * Then, create a new basic block that begins with the throwing instruction
654311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * (minus exceptions).  Note: this new basic block must NOT be entered into
655311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * the block_map.  If the potentially-throwing instruction is the target of a
656311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * future branch, we need to find the check psuedo half.  The new
657311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * basic block containing the work portion of the instruction should
658311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * only be entered via fallthrough from the block containing the
659311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * pseudo exception edge MIR.  Note also that this new block is
660311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * not automatically terminated after the work portion, and may
661311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * contain following instructions.
662b48819db07f9a0992a72173380c24249d7fc648abuzbee   *
663b48819db07f9a0992a72173380c24249d7fc648abuzbee   * Note also that the dex_pc_to_block_map_ entry for the potentially
664b48819db07f9a0992a72173380c24249d7fc648abuzbee   * throwing instruction will refer to the original basic block.
665311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   */
666e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  BasicBlock* new_block = CreateNewBB(kDalvikByteCode);
667311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  new_block->start_offset = insn->offset;
6680d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  cur_block->fall_through = new_block->id;
669e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  new_block->predecessors.push_back(cur_block->id);
6703aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  MIR* new_insn = NewMIR();
671311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  *new_insn = *insn;
67235ba7f3a78d38885ec54e61ed060d2771eeceea7buzbee  insn->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpCheck);
6738512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Associate the two halves.
674311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  insn->meta.throw_insn = new_insn;
675cdacac4a8196bdc620185079ec9e886329606f3dJean Christophe Beyler  new_block->AppendMIR(new_insn);
676311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  return new_block;
677311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
678311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
679311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Parse a Dex method and insert it into the MIRGraph at the current insert point. */
680311ca169f4727d46a55bdc8dfa0059719fa72b65buzbeevoid MIRGraph::InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_flags,
6818b2c0b9abc3f520495f4387ea040132ba85cae69Ian Rogers                           InvokeType invoke_type, uint16_t class_def_idx,
6822ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                           uint32_t method_idx, jobject class_loader, const DexFile& dex_file) {
683311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  current_code_item_ = code_item;
684311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  method_stack_.push_back(std::make_pair(current_method_, current_offset_));
685311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  current_method_ = m_units_.size();
686311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  current_offset_ = 0;
687311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  // TODO: will need to snapshot stack image and use that as the mir context identification.
688311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  m_units_.push_back(new DexCompilationUnit(cu_, class_loader, Runtime::Current()->GetClassLinker(),
6892730db03beee4d6687ddfb5000c33c0370fbc6ebVladimir Marko                     dex_file, current_code_item_, class_def_idx, method_idx, access_flags,
6902730db03beee4d6687ddfb5000c33c0370fbc6ebVladimir Marko                     cu_->compiler_driver->GetVerifiedMethod(&dex_file, method_idx)));
691311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  const uint16_t* code_ptr = current_code_item_->insns_;
692311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  const uint16_t* code_end =
693311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      current_code_item_->insns_ + current_code_item_->insns_size_in_code_units_;
694311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
695311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  // TODO: need to rework expansion of block list & try_block_addr when inlining activated.
696b48819db07f9a0992a72173380c24249d7fc648abuzbee  // TUNING: use better estimate of basic blocks for following resize.
697e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  block_list_.reserve(block_list_.size() + current_code_item_->insns_size_in_code_units_);
698e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  dex_pc_to_block_map_.resize(dex_pc_to_block_map_.size() + current_code_item_->insns_size_in_code_units_);
699bd663de599b16229085759366c56e2ed5a1dc7ecbuzbee
700311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  // TODO: replace with explicit resize routine.  Using automatic extension side effect for now.
701862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  try_block_addr_->SetBit(current_code_item_->insns_size_in_code_units_);
702862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  try_block_addr_->ClearBit(current_code_item_->insns_size_in_code_units_);
703311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
704311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  // If this is the first method, set up default entry and exit blocks.
705311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (current_method_ == 0) {
706311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    DCHECK(entry_block_ == NULL);
707311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    DCHECK(exit_block_ == NULL);
7084439596b00c91f565370bf0813cc2f9165093693Andreas Gampe    DCHECK_EQ(num_blocks_, 0U);
7090d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    // Use id 0 to represent a null block.
710e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    BasicBlock* null_block = CreateNewBB(kNullBlock);
7110d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    DCHECK_EQ(null_block->id, NullBasicBlockId);
7120d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    null_block->hidden = true;
713e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    entry_block_ = CreateNewBB(kEntryBlock);
714e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    exit_block_ = CreateNewBB(kExitBlock);
715311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    // TODO: deprecate all "cu->" fields; move what's left to wherever CompilationUnit is allocated.
716311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    cu_->dex_file = &dex_file;
717311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    cu_->class_def_idx = class_def_idx;
718311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    cu_->method_idx = method_idx;
719311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    cu_->access_flags = access_flags;
720311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    cu_->invoke_type = invoke_type;
721311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    cu_->shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
722311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  } else {
723311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    UNIMPLEMENTED(FATAL) << "Nested inlining not implemented.";
724311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    /*
725311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee     * Will need to manage storage for ins & outs, push prevous state and update
726311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee     * insert point.
727311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee     */
728311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
729311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
730311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /* Current block to record parsed instructions */
731e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  BasicBlock* cur_block = CreateNewBB(kDalvikByteCode);
7320d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  DCHECK_EQ(current_offset_, 0U);
733311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  cur_block->start_offset = current_offset_;
7340d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  // TODO: for inlining support, insert at the insert point rather than entry block.
7350d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  entry_block_->fall_through = cur_block->id;
736e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  cur_block->predecessors.push_back(entry_block_->id);
737311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
7383d73ba2ce682edfaf41f29521bd6039c6499a1c5Vladimir Marko  /* Identify code range in try blocks and set up the empty catch blocks */
739311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  ProcessTryCatchBlocks();
740311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
7413d73ba2ce682edfaf41f29521bd6039c6499a1c5Vladimir Marko  uint64_t merged_df_flags = 0u;
7423d73ba2ce682edfaf41f29521bd6039c6499a1c5Vladimir Marko
743311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /* Parse all instructions and put them into containing basic blocks */
744311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  while (code_ptr < code_end) {
7453aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    MIR *insn = NewMIR();
746311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    insn->offset = current_offset_;
747311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    insn->m_unit_index = current_method_;
748311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    int width = ParseInsn(code_ptr, &insn->dalvikInsn);
749311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    Instruction::Code opcode = insn->dalvikInsn.opcode;
750311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (opcode_count_ != NULL) {
751311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      opcode_count_[static_cast<int>(opcode)]++;
752311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
753311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
754fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    int flags = insn->dalvikInsn.FlagsOf();
755b1f1d642093418612c0a27ce4203b421bb6eb767buzbee    int verify_flags = Instruction::VerifyFlagsOf(insn->dalvikInsn.opcode);
756311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
757cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler    uint64_t df_flags = GetDataFlowAttributes(insn);
7583d73ba2ce682edfaf41f29521bd6039c6499a1c5Vladimir Marko    merged_df_flags |= df_flags;
759311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
760311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (df_flags & DF_HAS_DEFS) {
761311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      def_count_ += (df_flags & DF_A_WIDE) ? 2 : 1;
762311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
763311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
7641da1e2fceb0030b4b76b43510b1710a9613e0c2ebuzbee    if (df_flags & DF_LVN) {
7651da1e2fceb0030b4b76b43510b1710a9613e0c2ebuzbee      cur_block->use_lvn = true;  // Run local value numbering on this basic block.
7661da1e2fceb0030b4b76b43510b1710a9613e0c2ebuzbee    }
7671da1e2fceb0030b4b76b43510b1710a9613e0c2ebuzbee
7688512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Check for inline data block signatures.
7692724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee    if (opcode == Instruction::NOP) {
7702724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee      // A simple NOP will have a width of 1 at this point, embedded data NOP > 1.
7712724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee      if ((width == 1) && ((current_offset_ & 0x1) == 0x1) && ((code_end - code_ptr) > 1)) {
7722724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee        // Could be an aligning nop.  If an embedded data NOP follows, treat pair as single unit.
7732724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee        uint16_t following_raw_instruction = code_ptr[1];
7742724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee        if ((following_raw_instruction == Instruction::kSparseSwitchSignature) ||
7752724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee            (following_raw_instruction == Instruction::kPackedSwitchSignature) ||
7762724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee            (following_raw_instruction == Instruction::kArrayDataSignature)) {
7772724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee          width += Instruction::At(code_ptr + 1)->SizeInCodeUnits();
7782724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee        }
7792724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee      }
7802724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee      if (width == 1) {
7812724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee        // It is a simple nop - treat normally.
782cdacac4a8196bdc620185079ec9e886329606f3dJean Christophe Beyler        cur_block->AppendMIR(insn);
7832724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee      } else {
7840d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee        DCHECK(cur_block->fall_through == NullBasicBlockId);
7850d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee        DCHECK(cur_block->taken == NullBasicBlockId);
7862724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee        // Unreachable instruction, mark for no continuation.
7872724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee        flags &= ~Instruction::kContinue;
7882724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee      }
7892724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee    } else {
790cdacac4a8196bdc620185079ec9e886329606f3dJean Christophe Beyler      cur_block->AppendMIR(insn);
7912724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee    }
7922724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee
793b48819db07f9a0992a72173380c24249d7fc648abuzbee    // Associate the starting dex_pc for this opcode with its containing basic block.
794e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    dex_pc_to_block_map_[insn->offset] = cur_block->id;
795b48819db07f9a0992a72173380c24249d7fc648abuzbee
7962724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee    code_ptr += width;
7972724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee
798311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (flags & Instruction::kBranch) {
799311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      cur_block = ProcessCanBranch(cur_block, insn, current_offset_,
800311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                   width, flags, code_ptr, code_end);
801311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    } else if (flags & Instruction::kReturn) {
802311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      cur_block->terminated_by_return = true;
8030d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee      cur_block->fall_through = exit_block_->id;
804e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      exit_block_->predecessors.push_back(cur_block->id);
805311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      /*
806311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       * Terminate the current block if there are instructions
807311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       * afterwards.
808311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       */
809311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      if (code_ptr < code_end) {
810311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        /*
811311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee         * Create a fallthrough block for real instructions
812311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee         * (incl. NOP).
813311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee         */
8142724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee         FindBlock(current_offset_ + width, /* split */ false, /* create */ true,
8152724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee                   /* immed_pred_block_p */ NULL);
816311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      }
817311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    } else if (flags & Instruction::kThrow) {
818311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      cur_block = ProcessCanThrow(cur_block, insn, current_offset_, width, flags, try_block_addr_,
819311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                  code_ptr, code_end);
820311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    } else if (flags & Instruction::kSwitch) {
82117189ac098b2f156713db1821b49db7b2f018bbebuzbee      cur_block = ProcessCanSwitch(cur_block, insn, current_offset_, width, flags);
822311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
823688e7c5c9f36573dd4da2edd889470d930b0054bAlexei Zavjalov    if (verify_flags & Instruction::kVerifyVarArgRange ||
824688e7c5c9f36573dd4da2edd889470d930b0054bAlexei Zavjalov        verify_flags & Instruction::kVerifyVarArgRangeNonZero) {
825b1f1d642093418612c0a27ce4203b421bb6eb767buzbee      /*
826b1f1d642093418612c0a27ce4203b421bb6eb767buzbee       * The Quick backend's runtime model includes a gap between a method's
827b1f1d642093418612c0a27ce4203b421bb6eb767buzbee       * argument ("in") vregs and the rest of its vregs.  Handling a range instruction
828b1f1d642093418612c0a27ce4203b421bb6eb767buzbee       * which spans the gap is somewhat complicated, and should not happen
829b1f1d642093418612c0a27ce4203b421bb6eb767buzbee       * in normal usage of dx.  Punt to the interpreter.
830b1f1d642093418612c0a27ce4203b421bb6eb767buzbee       */
831b1f1d642093418612c0a27ce4203b421bb6eb767buzbee      int first_reg_in_range = insn->dalvikInsn.vC;
832b1f1d642093418612c0a27ce4203b421bb6eb767buzbee      int last_reg_in_range = first_reg_in_range + insn->dalvikInsn.vA - 1;
833b1f1d642093418612c0a27ce4203b421bb6eb767buzbee      if (IsInVReg(first_reg_in_range) != IsInVReg(last_reg_in_range)) {
834b1f1d642093418612c0a27ce4203b421bb6eb767buzbee        punt_to_interpreter_ = true;
835b1f1d642093418612c0a27ce4203b421bb6eb767buzbee      }
836b1f1d642093418612c0a27ce4203b421bb6eb767buzbee    }
837311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    current_offset_ += width;
8382469e60e6ff08c2a0b4cd1e209246c5d91027679Jean Christophe Beyler    BasicBlock* next_block = FindBlock(current_offset_, /* split */ false, /* create */
839311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                      false, /* immed_pred_block_p */ NULL);
840311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (next_block) {
841311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      /*
842311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       * The next instruction could be the target of a previously parsed
843311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       * forward branch so a block is already created. If the current
844311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       * instruction is not an unconditional branch, connect them through
845311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       * the fall-through link.
846311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       */
8470d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee      DCHECK(cur_block->fall_through == NullBasicBlockId ||
8480d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee             GetBasicBlock(cur_block->fall_through) == next_block ||
8490d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee             GetBasicBlock(cur_block->fall_through) == exit_block_);
850311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
8510d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee      if ((cur_block->fall_through == NullBasicBlockId) && (flags & Instruction::kContinue)) {
8520d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee        cur_block->fall_through = next_block->id;
853e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko        next_block->predecessors.push_back(cur_block->id);
854311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      }
855311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      cur_block = next_block;
856311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
857311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
8583d73ba2ce682edfaf41f29521bd6039c6499a1c5Vladimir Marko  merged_df_flags_ = merged_df_flags;
8595816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko
860311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
861311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    DumpCFG("/sdcard/1_post_parse_cfg/", true);
862311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
863311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
864311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (cu_->verbose) {
8651fd3346740dfb7f47be9922312b68a4227fada96buzbee    DumpMIRGraph();
866311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
867311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
868311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
8692ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MIRGraph::ShowOpcodeStats() {
870311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  DCHECK(opcode_count_ != NULL);
871311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  LOG(INFO) << "Opcode Count";
872311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  for (int i = 0; i < kNumPackedOpcodes; i++) {
873311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (opcode_count_[i] != 0) {
874311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      LOG(INFO) << "-C- " << Instruction::Name(static_cast<Instruction::Code>(i))
875311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                << " " << opcode_count_[i];
876311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
877311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
878311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
879311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
880cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyleruint64_t MIRGraph::GetDataFlowAttributes(Instruction::Code opcode) {
881cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler  DCHECK_LT((size_t) opcode, (sizeof(oat_data_flow_attributes_) / sizeof(oat_data_flow_attributes_[0])));
882cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler  return oat_data_flow_attributes_[opcode];
883cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler}
884cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler
885cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyleruint64_t MIRGraph::GetDataFlowAttributes(MIR* mir) {
886cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler  DCHECK(mir != nullptr);
887cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler  Instruction::Code opcode = mir->dalvikInsn.opcode;
888cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler  return GetDataFlowAttributes(opcode);
889cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler}
890cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler
891311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee// TODO: use a configurable base prefix, and adjust callers to supply pass name.
892311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Dump the CFG into a DOT graph */
893d0a515562772d7c637160e8779c4f253ee169c3aJean Christophe Beylervoid MIRGraph::DumpCFG(const char* dir_prefix, bool all_blocks, const char *suffix) {
894311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  FILE* file;
895a8869e60d93ba9eed36a5b53553b7609f58fc05bJean Christophe Beyler  static AtomicInteger cnt(0);
896a8869e60d93ba9eed36a5b53553b7609f58fc05bJean Christophe Beyler
897a8869e60d93ba9eed36a5b53553b7609f58fc05bJean Christophe Beyler  // Increment counter to get a unique file number.
898a8869e60d93ba9eed36a5b53553b7609f58fc05bJean Christophe Beyler  cnt++;
899a8869e60d93ba9eed36a5b53553b7609f58fc05bJean Christophe Beyler
900311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  std::string fname(PrettyMethod(cu_->method_idx, *cu_->dex_file));
901311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  ReplaceSpecialChars(fname);
902a8869e60d93ba9eed36a5b53553b7609f58fc05bJean Christophe Beyler  fname = StringPrintf("%s%s%x%s_%d.dot", dir_prefix, fname.c_str(),
903d0a515562772d7c637160e8779c4f253ee169c3aJean Christophe Beyler                      GetBasicBlock(GetEntryBlock()->fall_through)->start_offset,
904a8869e60d93ba9eed36a5b53553b7609f58fc05bJean Christophe Beyler                      suffix == nullptr ? "" : suffix,
905a8869e60d93ba9eed36a5b53553b7609f58fc05bJean Christophe Beyler                      cnt.LoadRelaxed());
906311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  file = fopen(fname.c_str(), "w");
907311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (file == NULL) {
908311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    return;
909311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
910311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  fprintf(file, "digraph G {\n");
911311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
912311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  fprintf(file, "  rankdir=TB\n");
913311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
914311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  int num_blocks = all_blocks ? GetNumBlocks() : num_reachable_blocks_;
915311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  int idx;
916311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
917311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  for (idx = 0; idx < num_blocks; idx++) {
918e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    int block_idx = all_blocks ? idx : dfs_order_[idx];
9198512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    BasicBlock* bb = GetBasicBlock(block_idx);
92025bc279080a56546b0f8a33342a853b2778eed0dRazvan A Lupusoru    if (bb == NULL) continue;
921311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (bb->block_type == kDead) continue;
922a8869e60d93ba9eed36a5b53553b7609f58fc05bJean Christophe Beyler    if (bb->hidden) continue;
923311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (bb->block_type == kEntryBlock) {
924311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  entry_%d [shape=Mdiamond];\n", bb->id);
925311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    } else if (bb->block_type == kExitBlock) {
926311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  exit_%d [shape=Mdiamond];\n", bb->id);
927311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    } else if (bb->block_type == kDalvikByteCode) {
928311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  block%04x_%d [shape=record,label = \"{ \\\n",
929311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee              bb->start_offset, bb->id);
9308512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      const MIR* mir;
931311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        fprintf(file, "    {block id %d\\l}%s\\\n", bb->id,
932311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                bb->first_mir_insn ? " | " : " ");
933311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        for (mir = bb->first_mir_insn; mir; mir = mir->next) {
934311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee            int opcode = mir->dalvikInsn.opcode;
9351500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru            fprintf(file, "    {%04x %s %s %s %s %s %s %s\\l}%s\\\n", mir->offset,
936d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell                      mir->ssa_rep ? GetDalvikDisassembly(mir) :
9372ab40eb3c23559205ac7b9b039bd749458e8a761Jean Christophe Beyler                      !MIR::DecodedInstruction::IsPseudoMirOp(opcode) ?
9382ab40eb3c23559205ac7b9b039bd749458e8a761Jean Christophe Beyler                        Instruction::Name(mir->dalvikInsn.opcode) :
939d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell                        extended_mir_op_names_[opcode - kMirOpFirst],
940d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell                      (mir->optimization_flags & MIR_IGNORE_RANGE_CHECK) != 0 ? " no_rangecheck" : " ",
941d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell                      (mir->optimization_flags & MIR_IGNORE_NULL_CHECK) != 0 ? " no_nullcheck" : " ",
94260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji                      (mir->optimization_flags & MIR_IGNORE_SUSPEND_CHECK) != 0 ? " no_suspendcheck" : " ",
943b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler                      (mir->optimization_flags & MIR_STORE_NON_TEMPORAL) != 0 ? " non_temporal" : " ",
9441500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru                      (mir->optimization_flags & MIR_CALLEE) != 0 ? " inlined" : " ",
9451500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru                      (mir->optimization_flags & MIR_IGNORE_CLINIT_CHECK) != 0 ? " no_clinit" : " ",
946d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell                      mir->next ? " | " : " ");
947311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        }
948311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        fprintf(file, "  }\"];\n\n");
949311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    } else if (bb->block_type == kExceptionHandling) {
950311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      char block_name[BLOCK_NAME_LEN];
951311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
952311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      GetBlockName(bb, block_name);
953311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  %s [shape=invhouse];\n", block_name);
954311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
955311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
956311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    char block_name1[BLOCK_NAME_LEN], block_name2[BLOCK_NAME_LEN];
957311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
9580d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    if (bb->taken != NullBasicBlockId) {
959311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      GetBlockName(bb, block_name1);
9600d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee      GetBlockName(GetBasicBlock(bb->taken), block_name2);
961311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  %s:s -> %s:n [style=dotted]\n",
962311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee              block_name1, block_name2);
963311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
9640d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    if (bb->fall_through != NullBasicBlockId) {
965311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      GetBlockName(bb, block_name1);
9660d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee      GetBlockName(GetBasicBlock(bb->fall_through), block_name2);
967311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  %s:s -> %s:n\n", block_name1, block_name2);
968311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
969311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
9700d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    if (bb->successor_block_list_type != kNotUsed) {
971311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  succ%04x_%d [shape=%s,label = \"{ \\\n",
972311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee              bb->start_offset, bb->id,
9730d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee              (bb->successor_block_list_type == kCatch) ?  "Mrecord" : "record");
974311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
975e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      int last_succ_id = static_cast<int>(bb->successor_blocks.size() - 1u);
976311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      int succ_id = 0;
977e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      for (SuccessorBlockInfo* successor_block_info : bb->successor_blocks) {
9788512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler        BasicBlock* dest_block = GetBasicBlock(successor_block_info->block);
979311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        fprintf(file, "    {<f%d> %04x: %04x\\l}%s\\\n",
980e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko                succ_id,
981311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                successor_block_info->key,
982311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                dest_block->start_offset,
983e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko                (succ_id != last_succ_id) ? " | " : " ");
984e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko        ++succ_id;
985311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      }
986311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  }\"];\n\n");
987311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
988311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      GetBlockName(bb, block_name1);
989311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  %s:s -> succ%04x_%d:n [style=dashed]\n",
990311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee              block_name1, bb->start_offset, bb->id);
991311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
99225bc279080a56546b0f8a33342a853b2778eed0dRazvan A Lupusoru      // Link the successor pseudo-block with all of its potential targets.
99325bc279080a56546b0f8a33342a853b2778eed0dRazvan A Lupusoru      succ_id = 0;
994e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      for (SuccessorBlockInfo* successor_block_info : bb->successor_blocks) {
99525bc279080a56546b0f8a33342a853b2778eed0dRazvan A Lupusoru        BasicBlock* dest_block = GetBasicBlock(successor_block_info->block);
996311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
99725bc279080a56546b0f8a33342a853b2778eed0dRazvan A Lupusoru        GetBlockName(dest_block, block_name2);
99825bc279080a56546b0f8a33342a853b2778eed0dRazvan A Lupusoru        fprintf(file, "  succ%04x_%d:f%d:e -> %s:n\n", bb->start_offset,
99925bc279080a56546b0f8a33342a853b2778eed0dRazvan A Lupusoru                bb->id, succ_id++, block_name2);
1000311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      }
1001311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
1002311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    fprintf(file, "\n");
1003311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
1004311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (cu_->verbose) {
1005311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      /* Display the dominator tree */
1006311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      GetBlockName(bb, block_name1);
1007311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  cfg%s [label=\"%s\", shape=none];\n",
1008311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee              block_name1, block_name1);
1009311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      if (bb->i_dom) {
10100d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee        GetBlockName(GetBasicBlock(bb->i_dom), block_name2);
1011311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        fprintf(file, "  cfg%s:s -> cfg%s:n\n\n", block_name2, block_name1);
1012311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      }
1013311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
1014311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
1015311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  fprintf(file, "}\n");
1016311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  fclose(file);
1017311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
1018311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
10193aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler/* Insert an MIR instruction to the end of a basic block. */
1020cdacac4a8196bdc620185079ec9e886329606f3dJean Christophe Beylervoid BasicBlock::AppendMIR(MIR* mir) {
10218512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Insert it after the last MIR.
10228512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  InsertMIRListAfter(last_mir_insn, mir, mir);
10238512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
10248512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
10258512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::AppendMIRList(MIR* first_list_mir, MIR* last_list_mir) {
10268512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Insert it after the last MIR.
10278512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  InsertMIRListAfter(last_mir_insn, first_list_mir, last_list_mir);
10288512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
10298512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
10308512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::AppendMIRList(const std::vector<MIR*>& insns) {
10318512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  for (std::vector<MIR*>::const_iterator it = insns.begin(); it != insns.end(); it++) {
10328512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    MIR* new_mir = *it;
10338512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
10348512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Add a copy of each MIR.
10358512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    InsertMIRListAfter(last_mir_insn, new_mir, new_mir);
10368512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
10378512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
10388512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
10398512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler/* Insert a MIR instruction after the specified MIR. */
10408512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::InsertMIRAfter(MIR* current_mir, MIR* new_mir) {
10418512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  InsertMIRListAfter(current_mir, new_mir, new_mir);
10428512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
10438512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
10448512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::InsertMIRListAfter(MIR* insert_after, MIR* first_list_mir, MIR* last_list_mir) {
10458512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // If no MIR, we are done.
10468512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (first_list_mir == nullptr || last_list_mir == nullptr) {
10478512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    return;
10488512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
10498512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
10508512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // If insert_after is null, assume BB is empty.
10518512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (insert_after == nullptr) {
10528512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    first_mir_insn = first_list_mir;
10538512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    last_mir_insn = last_list_mir;
10548512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    last_list_mir->next = nullptr;
10551fd3346740dfb7f47be9922312b68a4227fada96buzbee  } else {
10568512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    MIR* after_list = insert_after->next;
10578512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    insert_after->next = first_list_mir;
10588512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    last_list_mir->next = after_list;
10598512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    if (after_list == nullptr) {
10608512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      last_mir_insn = last_list_mir;
10618512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    }
10621fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
10633aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
10648512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Set this BB to be the basic block of the MIRs.
10658512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  MIR* last = last_list_mir->next;
10668512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  for (MIR* mir = first_list_mir; mir != last; mir = mir->next) {
10678512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    mir->bb = id;
10688512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
10691fd3346740dfb7f47be9922312b68a4227fada96buzbee}
10701fd3346740dfb7f47be9922312b68a4227fada96buzbee
10713aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler/* Insert an MIR instruction to the head of a basic block. */
1072cdacac4a8196bdc620185079ec9e886329606f3dJean Christophe Beylervoid BasicBlock::PrependMIR(MIR* mir) {
10738512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  InsertMIRListBefore(first_mir_insn, mir, mir);
10748512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
10753aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
10768512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::PrependMIRList(MIR* first_list_mir, MIR* last_list_mir) {
10778512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Insert it before the first MIR.
10788512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  InsertMIRListBefore(first_mir_insn, first_list_mir, last_list_mir);
10791fd3346740dfb7f47be9922312b68a4227fada96buzbee}
10801fd3346740dfb7f47be9922312b68a4227fada96buzbee
10818512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::PrependMIRList(const std::vector<MIR*>& to_add) {
10828512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  for (std::vector<MIR*>::const_iterator it = to_add.begin(); it != to_add.end(); it++) {
10838512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    MIR* mir = *it;
10841fd3346740dfb7f47be9922312b68a4227fada96buzbee
10858512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    InsertMIRListBefore(first_mir_insn, mir, mir);
10861fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
10878512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
10883aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
10898512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler/* Insert a MIR instruction before the specified MIR. */
10908512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::InsertMIRBefore(MIR* current_mir, MIR* new_mir) {
10918512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Insert as a single element list.
10928512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  return InsertMIRListBefore(current_mir, new_mir, new_mir);
10933aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler}
10943aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
10953aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe BeylerMIR* BasicBlock::FindPreviousMIR(MIR* mir) {
10963aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  MIR* current = first_mir_insn;
10973aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
10983aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  while (current != nullptr) {
10993aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    MIR* next = current->next;
11003aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
11013aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    if (next == mir) {
11023aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler      return current;
11033aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    }
11043aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
11053aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    current = next;
11063aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  }
11073aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
11083aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  return nullptr;
11093aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler}
11103aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
11118512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::InsertMIRListBefore(MIR* insert_before, MIR* first_list_mir, MIR* last_list_mir) {
11128512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // If no MIR, we are done.
11138512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (first_list_mir == nullptr || last_list_mir == nullptr) {
11148512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    return;
11158512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
11168512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
11178512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // If insert_before is null, assume BB is empty.
11188512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (insert_before == nullptr) {
11198512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    first_mir_insn = first_list_mir;
11208512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    last_mir_insn = last_list_mir;
11218512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    last_list_mir->next = nullptr;
11228512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  } else {
11238512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    if (first_mir_insn == insert_before) {
11248512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      last_list_mir->next = first_mir_insn;
11258512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      first_mir_insn = first_list_mir;
11268512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    } else {
11278512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      // Find the preceding MIR.
11288512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      MIR* before_list = FindPreviousMIR(insert_before);
11298512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      DCHECK(before_list != nullptr);
11308512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      before_list->next = first_list_mir;
11318512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      last_list_mir->next = insert_before;
11328512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    }
11338512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
11348512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
11358512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Set this BB to be the basic block of the MIRs.
11368512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  for (MIR* mir = first_list_mir; mir != last_list_mir->next; mir = mir->next) {
11378512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    mir->bb = id;
11383aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  }
11398512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
11408512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
11418512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylerbool BasicBlock::RemoveMIR(MIR* mir) {
11428512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Remove as a single element list.
11438512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  return RemoveMIRList(mir, mir);
11448512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
11458512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
11468512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylerbool BasicBlock::RemoveMIRList(MIR* first_list_mir, MIR* last_list_mir) {
11478512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (first_list_mir == nullptr) {
11488512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    return false;
11498512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
11508512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
11518512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Try to find the MIR.
11528512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  MIR* before_list = nullptr;
11538512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  MIR* after_list = nullptr;
11543aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
11558512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // If we are removing from the beginning of the MIR list.
11568512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (first_mir_insn == first_list_mir) {
11578512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    before_list = nullptr;
11588512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  } else {
11598512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    before_list = FindPreviousMIR(first_list_mir);
11608512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    if (before_list == nullptr) {
11618512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      // We did not find the mir.
11628512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      return false;
11638512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    }
11648512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
11658512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
1166a4307aca310aac0ac62dcb5435daa02b1f950558Jean Christophe Beyler  // Remove the BB information and also find the after_list.
1167590c6a4ded1deb378baa253c86070d8eeffdc820Chao-ying Fu  for (MIR* mir = first_list_mir; mir != last_list_mir->next; mir = mir->next) {
11688512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    mir->bb = NullBasicBlockId;
11698512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
11708512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
11718512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  after_list = last_list_mir->next;
11728512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
1173a4307aca310aac0ac62dcb5435daa02b1f950558Jean Christophe Beyler  // If there is nothing before the list, after_list is the first_mir.
11748512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (before_list == nullptr) {
11758512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    first_mir_insn = after_list;
1176a4307aca310aac0ac62dcb5435daa02b1f950558Jean Christophe Beyler  } else {
1177a4307aca310aac0ac62dcb5435daa02b1f950558Jean Christophe Beyler    before_list->next = after_list;
11788512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
11793aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
1180a4307aca310aac0ac62dcb5435daa02b1f950558Jean Christophe Beyler  // If there is nothing after the list, before_list is last_mir.
11818512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (after_list == nullptr) {
11828512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    last_mir_insn = before_list;
11833aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  }
11848512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
11858512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  return true;
11861fd3346740dfb7f47be9922312b68a4227fada96buzbee}
11871fd3346740dfb7f47be9922312b68a4227fada96buzbee
1188cdacac4a8196bdc620185079ec9e886329606f3dJean Christophe BeylerMIR* BasicBlock::GetNextUnconditionalMir(MIRGraph* mir_graph, MIR* current) {
11893bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru  MIR* next_mir = nullptr;
11903bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru
11913bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru  if (current != nullptr) {
11923bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru    next_mir = current->next;
11933bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru  }
11943bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru
11953bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru  if (next_mir == nullptr) {
11963bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru    // Only look for next MIR that follows unconditionally.
1197cdacac4a8196bdc620185079ec9e886329606f3dJean Christophe Beyler    if ((taken == NullBasicBlockId) && (fall_through != NullBasicBlockId)) {
1198cdacac4a8196bdc620185079ec9e886329606f3dJean Christophe Beyler      next_mir = mir_graph->GetBasicBlock(fall_through)->first_mir_insn;
11993bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru    }
12003bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru  }
12013bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru
12023bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru  return next_mir;
12033bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru}
12043bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru
12051500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusorustatic void FillTypeSizeString(uint32_t type_size, std::string* decoded_mir) {
12061500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  DCHECK(decoded_mir != nullptr);
12071500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  OpSize type = static_cast<OpSize>(type_size >> 16);
12081500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  uint16_t vect_size = (type_size & 0xFFFF);
12091500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru
12101500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  // Now print the type and vector size.
12111500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  std::stringstream ss;
12121500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  ss << " (type:";
12131500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  ss << type;
12141500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  ss << " vectsize:";
12151500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  ss << vect_size;
12161500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  ss << ")";
12171500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru
12181500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  decoded_mir->append(ss.str());
12191500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru}
12201500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru
12211500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoruvoid MIRGraph::DisassembleExtendedInstr(const MIR* mir, std::string* decoded_mir) {
12221500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  DCHECK(decoded_mir != nullptr);
12231500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  int opcode = mir->dalvikInsn.opcode;
12241500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  SSARepresentation* ssa_rep = mir->ssa_rep;
12251500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  int defs = (ssa_rep != nullptr) ? ssa_rep->num_defs : 0;
12261500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  int uses = (ssa_rep != nullptr) ? ssa_rep->num_uses : 0;
12271500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru
12281500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  decoded_mir->append(extended_mir_op_names_[opcode - kMirOpFirst]);
12291500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru
12301500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  switch (opcode) {
12311500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPhi: {
12321500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      if (defs > 0 && uses > 0) {
12331500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        BasicBlockId* incoming = mir->meta.phi_incoming;
12341500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(StringPrintf(" %s = (%s",
12351500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru                           GetSSANameWithConst(ssa_rep->defs[0], true).c_str(),
12361500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru                           GetSSANameWithConst(ssa_rep->uses[0], true).c_str()));
12371500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(StringPrintf(":%d", incoming[0]));
12381500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        for (int i = 1; i < uses; i++) {
12391500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(StringPrintf(", %s:%d", GetSSANameWithConst(ssa_rep->uses[i], true).c_str(), incoming[i]));
12401500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        }
12411500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(")");
12421500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      }
12431500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
12441500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    }
12451500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpCopy:
12461500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      if (ssa_rep != nullptr) {
12471500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(" ");
12481500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[0], false));
12491500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        if (defs > 1) {
12501500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(", ");
12511500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[1], false));
12521500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        }
12531500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(" = ");
12541500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[0], false));
12551500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        if (uses > 1) {
12561500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(", ");
12571500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[1], false));
12581500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        }
12591500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      } else {
12601500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(StringPrintf(" v%d = v%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB));
12611500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      }
12621500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
12631500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpFusedCmplFloat:
12641500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpFusedCmpgFloat:
12651500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpFusedCmplDouble:
12661500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpFusedCmpgDouble:
12671500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpFusedCmpLong:
12681500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      if (ssa_rep != nullptr) {
12691500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(" ");
12701500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[0], false));
12711500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        for (int i = 1; i < uses; i++) {
12721500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(", ");
12731500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[i], false));
12741500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        }
12751500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      } else {
12761500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(StringPrintf(" v%d, v%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB));
12771500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      }
12781500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
12791500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpMoveVector:
12801500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB));
12811500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
12821500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
12831500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedAddition:
12841500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d + vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
12851500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
12861500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
12871500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedMultiply:
12881500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d * vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
12891500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
12901500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
12911500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedSubtract:
12921500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d - vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
12931500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
12941500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
12951500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedAnd:
12961500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d & vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
12971500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
12981500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
12991500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedOr:
13001500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d \\| vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13011500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
13021500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13031500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedXor:
13041500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d ^ vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13051500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
13061500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13071500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedShiftLeft:
13081500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d \\<\\< %d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13091500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
13101500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13111500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedUnsignedShiftRight:
13121500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d \\>\\>\\> %d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13131500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
13141500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13151500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedSignedShiftRight:
13161500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d \\>\\> %d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13171500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
13181500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13191500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpConstVector:
13201500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = %x, %x, %x, %x", mir->dalvikInsn.vA, mir->dalvikInsn.arg[0],
13211500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru                                      mir->dalvikInsn.arg[1], mir->dalvikInsn.arg[2], mir->dalvikInsn.arg[3]));
13221500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13231500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedSet:
13241500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      if (ssa_rep != nullptr) {
13251500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(StringPrintf(" vect%d = %s", mir->dalvikInsn.vA,
13261500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru              GetSSANameWithConst(ssa_rep->uses[0], false).c_str()));
13271500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        if (uses > 1) {
13281500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(", ");
13291500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[1], false));
13301500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        }
13311500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      } else {
13321500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(StringPrintf(" vect%d = v%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13331500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      }
13341500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
13351500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13361500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedAddReduce:
13371500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      if (ssa_rep != nullptr) {
13381500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(" ");
13391500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[0], false));
13401500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        if (defs > 1) {
13411500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(", ");
13421500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[1], false));
13431500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        }
13441500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(StringPrintf(" = vect%d + %s", mir->dalvikInsn.vB,
13451500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru            GetSSANameWithConst(ssa_rep->uses[0], false).c_str()));
13461500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        if (uses > 1) {
13471500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(", ");
13481500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[1], false));
13491500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        }
13501500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      } else {
13511500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(StringPrintf("v%d = vect%d + v%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB, mir->dalvikInsn.vA));
13521500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      }
13531500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
13541500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13551500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedReduce:
13561500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      if (ssa_rep != nullptr) {
13571500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(" ");
13581500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[0], false));
13591500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        if (defs > 1) {
13601500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(", ");
13611500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[1], false));
13621500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        }
13631500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(StringPrintf(" = vect%d", mir->dalvikInsn.vB));
13641500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      } else {
13651500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(StringPrintf(" v%d = vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13661500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      }
13671500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
13681500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13691500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpReserveVectorRegisters:
13701500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpReturnVectorRegisters:
13711500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d - vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13721500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13731500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpMemBarrier: {
13741500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(" type:");
13751500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      std::stringstream ss;
13761500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      ss << static_cast<MemBarrierKind>(mir->dalvikInsn.vA);
13771500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(ss.str());
13781500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13791500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    }
1380b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A    case kMirOpPackedArrayGet:
1381b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A    case kMirOpPackedArrayPut:
1382b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A      decoded_mir->append(StringPrintf(" vect%d", mir->dalvikInsn.vA));
1383b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A      if (ssa_rep != nullptr) {
1384b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A        decoded_mir->append(StringPrintf(", %s[%s]",
1385b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A                                        GetSSANameWithConst(ssa_rep->uses[0], false).c_str(),
1386b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A                                        GetSSANameWithConst(ssa_rep->uses[1], false).c_str()));
1387b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A      } else {
1388b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A        decoded_mir->append(StringPrintf(", v%d[v%d]", mir->dalvikInsn.vB, mir->dalvikInsn.vC));
1389b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A      }
1390b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A      FillTypeSizeString(mir->dalvikInsn.arg[0], decoded_mir);
1391b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A      break;
13921500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    default:
13931500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13941500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  }
13951500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru}
13961500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru
13972ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromchar* MIRGraph::GetDalvikDisassembly(const MIR* mir) {
139829a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  MIR::DecodedInstruction insn = mir->dalvikInsn;
13991fd3346740dfb7f47be9922312b68a4227fada96buzbee  std::string str;
14001fd3346740dfb7f47be9922312b68a4227fada96buzbee  int flags = 0;
14011fd3346740dfb7f47be9922312b68a4227fada96buzbee  int opcode = insn.opcode;
14021fd3346740dfb7f47be9922312b68a4227fada96buzbee  char* ret;
14031fd3346740dfb7f47be9922312b68a4227fada96buzbee  bool nop = false;
14041fd3346740dfb7f47be9922312b68a4227fada96buzbee  SSARepresentation* ssa_rep = mir->ssa_rep;
14058512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  Instruction::Format dalvik_format = Instruction::k10x;  // Default to no-operand format.
14061fd3346740dfb7f47be9922312b68a4227fada96buzbee
14071500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  // Handle special cases that recover the original dalvik instruction.
14081fd3346740dfb7f47be9922312b68a4227fada96buzbee  if ((opcode == kMirOpCheck) || (opcode == kMirOpCheckPart2)) {
14091fd3346740dfb7f47be9922312b68a4227fada96buzbee    str.append(extended_mir_op_names_[opcode - kMirOpFirst]);
14101fd3346740dfb7f47be9922312b68a4227fada96buzbee    str.append(": ");
14118512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Recover the original Dex instruction.
14121fd3346740dfb7f47be9922312b68a4227fada96buzbee    insn = mir->meta.throw_insn->dalvikInsn;
14131fd3346740dfb7f47be9922312b68a4227fada96buzbee    ssa_rep = mir->meta.throw_insn->ssa_rep;
14141fd3346740dfb7f47be9922312b68a4227fada96buzbee    opcode = insn.opcode;
14151fd3346740dfb7f47be9922312b68a4227fada96buzbee  } else if (opcode == kMirOpNop) {
14161fd3346740dfb7f47be9922312b68a4227fada96buzbee    str.append("[");
1417750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru    if (mir->offset < current_code_item_->insns_size_in_code_units_) {
1418750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru      // Recover original opcode.
1419750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru      insn.opcode = Instruction::At(current_code_item_->insns_ + mir->offset)->Opcode();
1420750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru      opcode = insn.opcode;
1421750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru    }
14221fd3346740dfb7f47be9922312b68a4227fada96buzbee    nop = true;
14231fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
14240f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov  int defs = (ssa_rep != NULL) ? ssa_rep->num_defs : 0;
14250f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov  int uses = (ssa_rep != NULL) ? ssa_rep->num_uses : 0;
14261fd3346740dfb7f47be9922312b68a4227fada96buzbee
14272ab40eb3c23559205ac7b9b039bd749458e8a761Jean Christophe Beyler  if (MIR::DecodedInstruction::IsPseudoMirOp(opcode)) {
14281500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    // Note that this does not check the MIR's opcode in all cases. In cases where it
14291500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    // recovered dalvik instruction, it uses opcode of that instead of the extended one.
14301500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    DisassembleExtendedInstr(mir, &str);
14311fd3346740dfb7f47be9922312b68a4227fada96buzbee  } else {
14321fd3346740dfb7f47be9922312b68a4227fada96buzbee    dalvik_format = Instruction::FormatOf(insn.opcode);
1433fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    flags = insn.FlagsOf();
14341fd3346740dfb7f47be9922312b68a4227fada96buzbee    str.append(Instruction::Name(insn.opcode));
14351fd3346740dfb7f47be9922312b68a4227fada96buzbee
14368512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // For invokes-style formats, treat wide regs as a pair of singles.
14371fd3346740dfb7f47be9922312b68a4227fada96buzbee    bool show_singles = ((dalvik_format == Instruction::k35c) ||
14381fd3346740dfb7f47be9922312b68a4227fada96buzbee                         (dalvik_format == Instruction::k3rc));
14391fd3346740dfb7f47be9922312b68a4227fada96buzbee    if (defs != 0) {
14401500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      str.append(" ");
14411500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      str.append(GetSSANameWithConst(ssa_rep->defs[0], false));
14421500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      if (defs > 1) {
14431500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        str.append(", ");
14441500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        str.append(GetSSANameWithConst(ssa_rep->defs[1], false));
14451500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      }
14461fd3346740dfb7f47be9922312b68a4227fada96buzbee      if (uses != 0) {
14471fd3346740dfb7f47be9922312b68a4227fada96buzbee        str.append(", ");
14481fd3346740dfb7f47be9922312b68a4227fada96buzbee      }
14491fd3346740dfb7f47be9922312b68a4227fada96buzbee    }
14501fd3346740dfb7f47be9922312b68a4227fada96buzbee    for (int i = 0; i < uses; i++) {
14511500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      str.append(" ");
14521500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      str.append(GetSSANameWithConst(ssa_rep->uses[i], show_singles));
14531fd3346740dfb7f47be9922312b68a4227fada96buzbee      if (!show_singles && (reg_location_ != NULL) && reg_location_[i].wide) {
14541fd3346740dfb7f47be9922312b68a4227fada96buzbee        // For the listing, skip the high sreg.
14551fd3346740dfb7f47be9922312b68a4227fada96buzbee        i++;
14561fd3346740dfb7f47be9922312b68a4227fada96buzbee      }
14571500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      if (i != (uses - 1)) {
14581fd3346740dfb7f47be9922312b68a4227fada96buzbee        str.append(",");
14591fd3346740dfb7f47be9922312b68a4227fada96buzbee      }
14601fd3346740dfb7f47be9922312b68a4227fada96buzbee    }
14611500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru
14621fd3346740dfb7f47be9922312b68a4227fada96buzbee    switch (dalvik_format) {
14638512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      case Instruction::k11n:  // Add one immediate from vB.
14641fd3346740dfb7f47be9922312b68a4227fada96buzbee      case Instruction::k21s:
14651fd3346740dfb7f47be9922312b68a4227fada96buzbee      case Instruction::k31i:
14661fd3346740dfb7f47be9922312b68a4227fada96buzbee      case Instruction::k21h:
14671500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        str.append(StringPrintf(", #0x%x", insn.vB));
14681fd3346740dfb7f47be9922312b68a4227fada96buzbee        break;
14698512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      case Instruction::k51l:  // Add one wide immediate.
147023b03b5b5fdaa517eda3b8b358752672cf6046b1Ian Rogers        str.append(StringPrintf(", #%" PRId64, insn.vB_wide));
14711fd3346740dfb7f47be9922312b68a4227fada96buzbee        break;
14728512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      case Instruction::k21c:  // One register, one string/type/method index.
14731fd3346740dfb7f47be9922312b68a4227fada96buzbee      case Instruction::k31c:
14741500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        str.append(StringPrintf(", index #0x%x", insn.vB));
14751fd3346740dfb7f47be9922312b68a4227fada96buzbee        break;
14768512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      case Instruction::k22c:  // Two registers, one string/type/method index.
14771500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        str.append(StringPrintf(", index #0x%x", insn.vC));
14781fd3346740dfb7f47be9922312b68a4227fada96buzbee        break;
14798512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      case Instruction::k22s:  // Add one immediate from vC.
14801fd3346740dfb7f47be9922312b68a4227fada96buzbee      case Instruction::k22b:
14811500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        str.append(StringPrintf(", #0x%x", insn.vC));
14821fd3346740dfb7f47be9922312b68a4227fada96buzbee        break;
14831500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      default:
14848512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler        // Nothing left to print.
14851500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        break;
148602c8cc6d1312a2b55533f02f6369dc7c94672f90Brian Carlstrom    }
14871500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru
14880f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov    if ((flags & Instruction::kBranch) != 0) {
14890f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov      // For branches, decode the instructions to print out the branch targets.
14900f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov      int offset = 0;
14910f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov      switch (dalvik_format) {
14920f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov        case Instruction::k21t:
14930f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov          offset = insn.vB;
14940f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov          break;
14950f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov        case Instruction::k22t:
14960f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov          offset = insn.vC;
14970f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov          break;
14980f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov        case Instruction::k10t:
14990f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov        case Instruction::k20t:
15000f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov        case Instruction::k30t:
15010f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov          offset = insn.vA;
15020f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov          break;
15030f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov        default:
15040f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov          LOG(FATAL) << "Unexpected branch format " << dalvik_format << " from " << insn.opcode;
15051500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          break;
15060f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov      }
15071500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      str.append(StringPrintf(", 0x%x (%c%x)", mir->offset + offset,
15080f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov                              offset > 0 ? '+' : '-', offset > 0 ? offset : -offset));
15090f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov    }
15101500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru
15111500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    if (nop) {
15121500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      str.append("]--optimized away");
15131500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    }
15141fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
15151fd3346740dfb7f47be9922312b68a4227fada96buzbee  int length = str.length() + 1;
151683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko  ret = static_cast<char*>(arena_->Alloc(length, kArenaAllocDFInfo));
15171fd3346740dfb7f47be9922312b68a4227fada96buzbee  strncpy(ret, str.c_str(), length);
15181fd3346740dfb7f47be9922312b68a4227fada96buzbee  return ret;
15191fd3346740dfb7f47be9922312b68a4227fada96buzbee}
15201fd3346740dfb7f47be9922312b68a4227fada96buzbee
15211fd3346740dfb7f47be9922312b68a4227fada96buzbee/* Turn method name into a legal Linux file name */
15222ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MIRGraph::ReplaceSpecialChars(std::string& str) {
15239b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  static const struct { const char before; const char after; } match[] = {
15249b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom    {'/', '-'}, {';', '#'}, {' ', '#'}, {'$', '+'},
15259b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom    {'(', '@'}, {')', '@'}, {'<', '='}, {'>', '='}
15269b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  };
15271fd3346740dfb7f47be9922312b68a4227fada96buzbee  for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) {
15281fd3346740dfb7f47be9922312b68a4227fada96buzbee    std::replace(str.begin(), str.end(), match[i].before, match[i].after);
15291fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
15301fd3346740dfb7f47be9922312b68a4227fada96buzbee}
15311fd3346740dfb7f47be9922312b68a4227fada96buzbee
15322ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromstd::string MIRGraph::GetSSAName(int ssa_reg) {
153339ebcb800aabedd0ffa6aa4aeac8aa4194c66e61Ian Rogers  // TODO: This value is needed for LLVM and debugging. Currently, we compute this and then copy to
153439ebcb800aabedd0ffa6aa4aeac8aa4194c66e61Ian Rogers  //       the arena. We should be smarter and just place straight into the arena, or compute the
153539ebcb800aabedd0ffa6aa4aeac8aa4194c66e61Ian Rogers  //       value more lazily.
15361500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  int vreg = SRegToVReg(ssa_reg);
15371500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  if (vreg >= static_cast<int>(GetFirstTempVR())) {
15381500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    return StringPrintf("t%d_%d", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg));
15391500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  } else {
15401500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    return StringPrintf("v%d_%d", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg));
15411500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  }
15421fd3346740dfb7f47be9922312b68a4227fada96buzbee}
15431fd3346740dfb7f47be9922312b68a4227fada96buzbee
15441fd3346740dfb7f47be9922312b68a4227fada96buzbee// Similar to GetSSAName, but if ssa name represents an immediate show that as well.
15452ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromstd::string MIRGraph::GetSSANameWithConst(int ssa_reg, bool singles_only) {
15461fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (reg_location_ == NULL) {
15478512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Pre-SSA - just use the standard name.
15481fd3346740dfb7f47be9922312b68a4227fada96buzbee    return GetSSAName(ssa_reg);
15491fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
15501fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (IsConst(reg_location_[ssa_reg])) {
15519944b3b792103cb72df1953b5502ced9bf128305Mark Mendell    if (!singles_only && reg_location_[ssa_reg].wide &&
15529944b3b792103cb72df1953b5502ced9bf128305Mark Mendell        !reg_location_[ssa_reg].high_word) {
155323b03b5b5fdaa517eda3b8b358752672cf6046b1Ian Rogers      return StringPrintf("v%d_%d#0x%" PRIx64, SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg),
15541fd3346740dfb7f47be9922312b68a4227fada96buzbee                          ConstantValueWide(reg_location_[ssa_reg]));
15551fd3346740dfb7f47be9922312b68a4227fada96buzbee    } else {
1556b1eba213afaf7fa6445de863ddc9680ab99762eaBrian Carlstrom      return StringPrintf("v%d_%d#0x%x", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg),
15571fd3346740dfb7f47be9922312b68a4227fada96buzbee                          ConstantValue(reg_location_[ssa_reg]));
15581fd3346740dfb7f47be9922312b68a4227fada96buzbee    }
15591fd3346740dfb7f47be9922312b68a4227fada96buzbee  } else {
15601500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    int vreg = SRegToVReg(ssa_reg);
15611500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    if (vreg >= static_cast<int>(GetFirstTempVR())) {
15621500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      return StringPrintf("t%d_%d", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg));
15631500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    } else {
15641500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      return StringPrintf("v%d_%d", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg));
15651500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    }
15661fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
15671fd3346740dfb7f47be9922312b68a4227fada96buzbee}
15681fd3346740dfb7f47be9922312b68a4227fada96buzbee
15692ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MIRGraph::GetBlockName(BasicBlock* bb, char* name) {
15701fd3346740dfb7f47be9922312b68a4227fada96buzbee  switch (bb->block_type) {
15711fd3346740dfb7f47be9922312b68a4227fada96buzbee    case kEntryBlock:
15721fd3346740dfb7f47be9922312b68a4227fada96buzbee      snprintf(name, BLOCK_NAME_LEN, "entry_%d", bb->id);
15731fd3346740dfb7f47be9922312b68a4227fada96buzbee      break;
15741fd3346740dfb7f47be9922312b68a4227fada96buzbee    case kExitBlock:
15751fd3346740dfb7f47be9922312b68a4227fada96buzbee      snprintf(name, BLOCK_NAME_LEN, "exit_%d", bb->id);
15761fd3346740dfb7f47be9922312b68a4227fada96buzbee      break;
15771fd3346740dfb7f47be9922312b68a4227fada96buzbee    case kDalvikByteCode:
15781fd3346740dfb7f47be9922312b68a4227fada96buzbee      snprintf(name, BLOCK_NAME_LEN, "block%04x_%d", bb->start_offset, bb->id);
15791fd3346740dfb7f47be9922312b68a4227fada96buzbee      break;
15801fd3346740dfb7f47be9922312b68a4227fada96buzbee    case kExceptionHandling:
15811fd3346740dfb7f47be9922312b68a4227fada96buzbee      snprintf(name, BLOCK_NAME_LEN, "exception%04x_%d", bb->start_offset,
15821fd3346740dfb7f47be9922312b68a4227fada96buzbee               bb->id);
15831fd3346740dfb7f47be9922312b68a4227fada96buzbee      break;
15841fd3346740dfb7f47be9922312b68a4227fada96buzbee    default:
15851fd3346740dfb7f47be9922312b68a4227fada96buzbee      snprintf(name, BLOCK_NAME_LEN, "_%d", bb->id);
15861fd3346740dfb7f47be9922312b68a4227fada96buzbee      break;
15871fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
15881fd3346740dfb7f47be9922312b68a4227fada96buzbee}
15891fd3346740dfb7f47be9922312b68a4227fada96buzbee
15902ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromconst char* MIRGraph::GetShortyFromTargetIdx(int target_idx) {
15910d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  // TODO: for inlining support, use current code unit.
15921fd3346740dfb7f47be9922312b68a4227fada96buzbee  const DexFile::MethodId& method_id = cu_->dex_file->GetMethodId(target_idx);
15931fd3346740dfb7f47be9922312b68a4227fada96buzbee  return cu_->dex_file->GetShorty(method_id.proto_idx_);
15941fd3346740dfb7f47be9922312b68a4227fada96buzbee}
15951fd3346740dfb7f47be9922312b68a4227fada96buzbee
15961fd3346740dfb7f47be9922312b68a4227fada96buzbee/* Debug Utility - dump a compilation unit */
15972ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MIRGraph::DumpMIRGraph() {
15981fd3346740dfb7f47be9922312b68a4227fada96buzbee  const char* block_type_names[] = {
159917189ac098b2f156713db1821b49db7b2f018bbebuzbee    "Null Block",
16001fd3346740dfb7f47be9922312b68a4227fada96buzbee    "Entry Block",
16011fd3346740dfb7f47be9922312b68a4227fada96buzbee    "Code Block",
16021fd3346740dfb7f47be9922312b68a4227fada96buzbee    "Exit Block",
16031fd3346740dfb7f47be9922312b68a4227fada96buzbee    "Exception Handling",
16041fd3346740dfb7f47be9922312b68a4227fada96buzbee    "Catch Block"
16051fd3346740dfb7f47be9922312b68a4227fada96buzbee  };
16061fd3346740dfb7f47be9922312b68a4227fada96buzbee
16071fd3346740dfb7f47be9922312b68a4227fada96buzbee  LOG(INFO) << "Compiling " << PrettyMethod(cu_->method_idx, *cu_->dex_file);
16088d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru  LOG(INFO) << GetInsns(0) << " insns";
16091fd3346740dfb7f47be9922312b68a4227fada96buzbee  LOG(INFO) << GetNumBlocks() << " blocks in total";
16101fd3346740dfb7f47be9922312b68a4227fada96buzbee
1611e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  for (BasicBlock* bb : block_list_) {
16121fd3346740dfb7f47be9922312b68a4227fada96buzbee    LOG(INFO) << StringPrintf("Block %d (%s) (insn %04x - %04x%s)",
16131fd3346740dfb7f47be9922312b68a4227fada96buzbee        bb->id,
16141fd3346740dfb7f47be9922312b68a4227fada96buzbee        block_type_names[bb->block_type],
16151fd3346740dfb7f47be9922312b68a4227fada96buzbee        bb->start_offset,
16161fd3346740dfb7f47be9922312b68a4227fada96buzbee        bb->last_mir_insn ? bb->last_mir_insn->offset : bb->start_offset,
16171fd3346740dfb7f47be9922312b68a4227fada96buzbee        bb->last_mir_insn ? "" : " empty");
16180d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    if (bb->taken != NullBasicBlockId) {
16190d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee      LOG(INFO) << "  Taken branch: block " << bb->taken
16200d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee                << "(0x" << std::hex << GetBasicBlock(bb->taken)->start_offset << ")";
16211fd3346740dfb7f47be9922312b68a4227fada96buzbee    }
16220d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    if (bb->fall_through != NullBasicBlockId) {
16230d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee      LOG(INFO) << "  Fallthrough : block " << bb->fall_through
16240d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee                << " (0x" << std::hex << GetBasicBlock(bb->fall_through)->start_offset << ")";
16251fd3346740dfb7f47be9922312b68a4227fada96buzbee    }
16261fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
16271fd3346740dfb7f47be9922312b68a4227fada96buzbee}
16281fd3346740dfb7f47be9922312b68a4227fada96buzbee
16291fd3346740dfb7f47be9922312b68a4227fada96buzbee/*
16301fd3346740dfb7f47be9922312b68a4227fada96buzbee * Build an array of location records for the incoming arguments.
16311fd3346740dfb7f47be9922312b68a4227fada96buzbee * Note: one location record per word of arguments, with dummy
16321fd3346740dfb7f47be9922312b68a4227fada96buzbee * high-word loc for wide arguments.  Also pull up any following
16331fd3346740dfb7f47be9922312b68a4227fada96buzbee * MOVE_RESULT and incorporate it into the invoke.
16341fd3346740dfb7f47be9922312b68a4227fada96buzbee */
16351fd3346740dfb7f47be9922312b68a4227fada96buzbeeCallInfo* MIRGraph::NewMemCallInfo(BasicBlock* bb, MIR* mir, InvokeType type,
16362ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                  bool is_range) {
1637f6c4b3ba3825de1dbb3e747a68b809c6cc8eb4dbMathieu Chartier  CallInfo* info = static_cast<CallInfo*>(arena_->Alloc(sizeof(CallInfo),
163883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko                                                        kArenaAllocMisc));
16391fd3346740dfb7f47be9922312b68a4227fada96buzbee  MIR* move_result_mir = FindMoveResult(bb, mir);
16401fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (move_result_mir == NULL) {
16411fd3346740dfb7f47be9922312b68a4227fada96buzbee    info->result.location = kLocInvalid;
16421fd3346740dfb7f47be9922312b68a4227fada96buzbee  } else {
16431fd3346740dfb7f47be9922312b68a4227fada96buzbee    info->result = GetRawDest(move_result_mir);
16441fd3346740dfb7f47be9922312b68a4227fada96buzbee    move_result_mir->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
16451fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
16461fd3346740dfb7f47be9922312b68a4227fada96buzbee  info->num_arg_words = mir->ssa_rep->num_uses;
16471fd3346740dfb7f47be9922312b68a4227fada96buzbee  info->args = (info->num_arg_words == 0) ? NULL : static_cast<RegLocation*>
164883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko      (arena_->Alloc(sizeof(RegLocation) * info->num_arg_words, kArenaAllocMisc));
16491fd3346740dfb7f47be9922312b68a4227fada96buzbee  for (int i = 0; i < info->num_arg_words; i++) {
16501fd3346740dfb7f47be9922312b68a4227fada96buzbee    info->args[i] = GetRawSrc(mir, i);
16511fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
16521fd3346740dfb7f47be9922312b68a4227fada96buzbee  info->opt_flags = mir->optimization_flags;
16531fd3346740dfb7f47be9922312b68a4227fada96buzbee  info->type = type;
16541fd3346740dfb7f47be9922312b68a4227fada96buzbee  info->is_range = is_range;
16551fd3346740dfb7f47be9922312b68a4227fada96buzbee  info->index = mir->dalvikInsn.vB;
16561fd3346740dfb7f47be9922312b68a4227fada96buzbee  info->offset = mir->offset;
1657f096aad9203d7c50b2f9cbe1c1215a50c265a059Vladimir Marko  info->mir = mir;
16581fd3346740dfb7f47be9922312b68a4227fada96buzbee  return info;
16591fd3346740dfb7f47be9922312b68a4227fada96buzbee}
16601fd3346740dfb7f47be9922312b68a4227fada96buzbee
16613aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler// Allocate a new MIR.
16623aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe BeylerMIR* MIRGraph::NewMIR() {
16633aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  MIR* mir = new (arena_) MIR();
16643aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  return mir;
16653aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler}
16663aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
1667862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee// Allocate a new basic block.
16682ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromBasicBlock* MIRGraph::NewMemBB(BBType block_type, int block_id) {
1669e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  BasicBlock* bb = new (arena_) BasicBlock(block_id, block_type, arena_);
16708512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
1671862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  // TUNING: better estimate of the exit block predecessors?
1672e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  bb->predecessors.reserve((block_type == kExitBlock) ? 2048 : 2);
1673862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  block_id_map_.Put(block_id, block_id);
1674862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  return bb;
1675862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee}
16761fd3346740dfb7f47be9922312b68a4227fada96buzbee
16774e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beylervoid MIRGraph::InitializeConstantPropagation() {
16784e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler  is_constant_v_ = new (arena_) ArenaBitVector(arena_, GetNumSSARegs(), false);
167983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko  constant_values_ = static_cast<int*>(arena_->Alloc(sizeof(int) * GetNumSSARegs(), kArenaAllocDFInfo));
16804e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler}
16814e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
16824e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beylervoid MIRGraph::InitializeMethodUses() {
16838512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // The gate starts by initializing the use counts.
16844e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler  int num_ssa_regs = GetNumSSARegs();
1685e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  use_counts_.clear();
1686e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  use_counts_.reserve(num_ssa_regs + 32);
1687e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  use_counts_.resize(num_ssa_regs, 0u);
1688e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  raw_use_counts_.clear();
1689e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  raw_use_counts_.reserve(num_ssa_regs + 32);
1690e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  raw_use_counts_.resize(num_ssa_regs, 0u);
16914e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler}
16924e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
1693a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Markovoid MIRGraph::SSATransformationStart() {
1694a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko  DCHECK(temp_scoped_alloc_.get() == nullptr);
1695a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko  temp_scoped_alloc_.reset(ScopedArenaAllocator::Create(&cu_->arena_stack));
16968d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru  temp_bit_vector_size_ = GetNumOfCodeAndTempVRs();
1697a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko  temp_bit_vector_ = new (temp_scoped_alloc_.get()) ArenaBitVector(
1698a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko      temp_scoped_alloc_.get(), temp_bit_vector_size_, false, kBitMapRegisterV);
16994e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler}
17004e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
1701a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Markovoid MIRGraph::SSATransformationEnd() {
1702a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko  // Verify the dataflow information after the pass.
1703a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko  if (cu_->enable_debug & (1 << kDebugVerifyDataflow)) {
1704a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko    VerifyDataflow();
1705a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko  }
1706a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko
1707a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko  temp_bit_vector_size_ = 0u;
1708a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko  temp_bit_vector_ = nullptr;
17095229cf17e3240d55f043c0a9308e22d967f897dcVladimir Marko  temp_bit_matrix_ = nullptr;  // Def block matrix.
1710a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko  DCHECK(temp_scoped_alloc_.get() != nullptr);
1711a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko  temp_scoped_alloc_.reset();
1712c029c98cc056bc247b69160f413ee7ce9a93d8c3Johnny Qiu
1713c029c98cc056bc247b69160f413ee7ce9a93d8c3Johnny Qiu  // Update the maximum number of reachable blocks.
1714c029c98cc056bc247b69160f413ee7ce9a93d8c3Johnny Qiu  max_num_reachable_blocks_ = num_reachable_blocks_;
1715a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko}
1716a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko
1717750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusorusize_t MIRGraph::GetNumDalvikInsns() const {
1718750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  size_t cumulative_size = 0u;
1719750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  bool counted_current_item = false;
1720750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  const uint8_t size_for_null_code_item = 2u;
1721750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru
1722750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  for (auto it : m_units_) {
1723750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru    const DexFile::CodeItem* code_item = it->GetCodeItem();
1724750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru    // Even if the code item is null, we still count non-zero value so that
1725750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru    // each m_unit is counted as having impact.
1726750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru    cumulative_size += (code_item == nullptr ?
1727750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru        size_for_null_code_item : code_item->insns_size_in_code_units_);
1728750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru    if (code_item == current_code_item_) {
1729750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru      counted_current_item = true;
1730750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru    }
1731750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  }
1732750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru
1733750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  // If the current code item was not counted yet, count it now.
1734750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  // This can happen for example in unit tests where some fields like m_units_
1735750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  // are not initialized.
1736750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  if (counted_current_item == false) {
1737750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru    cumulative_size += (current_code_item_ == nullptr ?
1738750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru        size_for_null_code_item : current_code_item_->insns_size_in_code_units_);
1739750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  }
1740750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru
1741750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  return cumulative_size;
1742750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru}
1743750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru
174455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Markostatic BasicBlock* SelectTopologicalSortOrderFallBack(
174555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    MIRGraph* mir_graph, const ArenaBitVector* current_loop,
174655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    const ScopedArenaVector<size_t>* visited_cnt_values, ScopedArenaAllocator* allocator,
174755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    ScopedArenaVector<BasicBlockId>* tmp_stack) {
174855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // No true loop head has been found but there may be true loop heads after the mess we need
174955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // to resolve. To avoid taking one of those, pick the candidate with the highest number of
175055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // reachable unvisited nodes. That candidate will surely be a part of a loop.
175155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  BasicBlock* fall_back = nullptr;
175255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  size_t fall_back_num_reachable = 0u;
175355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // Reuse the same bit vector for each candidate to mark reachable unvisited blocks.
175455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  ArenaBitVector candidate_reachable(allocator, mir_graph->GetNumBlocks(), false, kBitMapMisc);
175555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  AllNodesIterator iter(mir_graph);
175655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  for (BasicBlock* candidate = iter.Next(); candidate != nullptr; candidate = iter.Next()) {
175755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    if (candidate->hidden ||                            // Hidden, or
175855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        candidate->visited ||                           // already processed, or
175955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        (*visited_cnt_values)[candidate->id] == 0u ||   // no processed predecessors, or
176055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        (current_loop != nullptr &&                     // outside current loop.
176155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko         !current_loop->IsBitSet(candidate->id))) {
176255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      continue;
176355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    }
176455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    DCHECK(tmp_stack->empty());
176555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    tmp_stack->push_back(candidate->id);
176655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    candidate_reachable.ClearAllBits();
176755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    size_t num_reachable = 0u;
176855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    while (!tmp_stack->empty()) {
176955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      BasicBlockId current_id = tmp_stack->back();
177055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      tmp_stack->pop_back();
177155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      BasicBlock* current_bb = mir_graph->GetBasicBlock(current_id);
177255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      DCHECK(current_bb != nullptr);
177355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      ChildBlockIterator child_iter(current_bb, mir_graph);
177455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      BasicBlock* child_bb = child_iter.Next();
177555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      for ( ; child_bb != nullptr; child_bb = child_iter.Next()) {
177655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        DCHECK(!child_bb->hidden);
177755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        if (child_bb->visited ||                            // Already processed, or
177855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            (current_loop != nullptr &&                     // outside current loop.
177955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko             !current_loop->IsBitSet(child_bb->id))) {
178055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          continue;
178155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        }
178255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        if (!candidate_reachable.IsBitSet(child_bb->id)) {
178355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          candidate_reachable.SetBit(child_bb->id);
178455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          tmp_stack->push_back(child_bb->id);
178555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          num_reachable += 1u;
178655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        }
178755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      }
178855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    }
178955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    if (fall_back_num_reachable < num_reachable) {
179055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      fall_back_num_reachable = num_reachable;
179155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      fall_back = candidate;
179255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    }
179355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  }
179455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  return fall_back;
179555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko}
179644e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
179755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko// Compute from which unvisited blocks is bb_id reachable through unvisited blocks.
179855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Markostatic void ComputeUnvisitedReachableFrom(MIRGraph* mir_graph, BasicBlockId bb_id,
179955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko                                          ArenaBitVector* reachable,
180055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko                                          ScopedArenaVector<BasicBlockId>* tmp_stack) {
180155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // NOTE: Loop heads indicated by the "visited" flag.
180255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  DCHECK(tmp_stack->empty());
180355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  reachable->ClearAllBits();
180455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  tmp_stack->push_back(bb_id);
180555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  while (!tmp_stack->empty()) {
180655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    BasicBlockId current_id = tmp_stack->back();
180755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    tmp_stack->pop_back();
180855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    BasicBlock* current_bb = mir_graph->GetBasicBlock(current_id);
180955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    DCHECK(current_bb != nullptr);
1810e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    for (BasicBlockId pred_id : current_bb->predecessors) {
1811e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      BasicBlock* pred_bb = mir_graph->GetBasicBlock(pred_id);
1812e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      DCHECK(pred_bb != nullptr);
181355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      if (!pred_bb->visited && !reachable->IsBitSet(pred_bb->id)) {
181455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        reachable->SetBit(pred_bb->id);
181555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        tmp_stack->push_back(pred_bb->id);
181655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      }
181755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    }
181844e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler  }
181955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko}
182044e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
182155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Markovoid MIRGraph::ComputeTopologicalSortOrder() {
1822622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko  ScopedArenaAllocator allocator(&cu_->arena_stack);
182355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  unsigned int num_blocks = GetNumBlocks();
182455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko
1825622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko  ScopedArenaQueue<BasicBlock*> q(allocator.Adapter());
182655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  ScopedArenaVector<size_t> visited_cnt_values(num_blocks, 0u, allocator.Adapter());
182755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  ScopedArenaVector<BasicBlockId> loop_head_stack(allocator.Adapter());
182855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  size_t max_nested_loops = 0u;
182955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  ArenaBitVector loop_exit_blocks(&allocator, num_blocks, false, kBitMapMisc);
183055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  loop_exit_blocks.ClearAllBits();
1831622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko
183255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // Count the number of blocks to process and add the entry block(s).
183355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  unsigned int num_blocks_to_process = 0u;
1834e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  for (BasicBlock* bb : block_list_) {
183544e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler    if (bb->hidden == true) {
183644e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler      continue;
183744e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler    }
183844e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
183955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    num_blocks_to_process += 1u;
1840622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko
1841e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    if (bb->predecessors.size() == 0u) {
184255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      // Add entry block to the queue.
184344e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler      q.push(bb);
184444e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler    }
184544e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler  }
184644e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
1847e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  // Clear the topological order arrays.
1848e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  topological_order_.clear();
1849e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  topological_order_.reserve(num_blocks);
1850e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  topological_order_loop_ends_.clear();
1851e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  topological_order_loop_ends_.resize(num_blocks, 0u);
1852e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  topological_order_indexes_.clear();
1853e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  topological_order_indexes_.resize(num_blocks, static_cast<uint16_t>(-1));
185455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko
185555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // Mark all blocks as unvisited.
185655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  ClearAllVisitedFlags();
185755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko
185855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // For loop heads, keep track from which blocks they are reachable not going through other
185955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // loop heads. Other loop heads are excluded to detect the heads of nested loops. The children
186055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // in this set go into the loop body, the other children are jumping over the loop.
186155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  ScopedArenaVector<ArenaBitVector*> loop_head_reachable_from(allocator.Adapter());
186255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  loop_head_reachable_from.resize(num_blocks, nullptr);
186355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // Reuse the same temp stack whenever calculating a loop_head_reachable_from[loop_head_id].
186455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  ScopedArenaVector<BasicBlockId> tmp_stack(allocator.Adapter());
186555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko
186655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  while (num_blocks_to_process != 0u) {
1867622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    BasicBlock* bb = nullptr;
1868622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    if (!q.empty()) {
186955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      num_blocks_to_process -= 1u;
1870622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko      // Get top.
1871622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko      bb = q.front();
1872622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko      q.pop();
187355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      if (bb->visited) {
187455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        // Loop head: it was already processed, mark end and copy exit blocks to the queue.
187555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        DCHECK(q.empty()) << PrettyMethod(cu_->method_idx, *cu_->dex_file);
1876e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko        uint16_t idx = static_cast<uint16_t>(topological_order_.size());
1877e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko        topological_order_loop_ends_[topological_order_indexes_[bb->id]] = idx;
187855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        DCHECK_EQ(loop_head_stack.back(), bb->id);
187955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        loop_head_stack.pop_back();
188055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        ArenaBitVector* reachable =
188155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            loop_head_stack.empty() ? nullptr : loop_head_reachable_from[loop_head_stack.back()];
188255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        for (BasicBlockId candidate_id : loop_exit_blocks.Indexes()) {
188355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          if (reachable == nullptr || reachable->IsBitSet(candidate_id)) {
188455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            q.push(GetBasicBlock(candidate_id));
188555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            // NOTE: The BitVectorSet::IndexIterator will not check the pointed-to bit again,
188655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            // so clearing the bit has no effect on the iterator.
188755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            loop_exit_blocks.ClearBit(candidate_id);
188855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          }
188955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        }
189055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        continue;
189155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      }
1892622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    } else {
189355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      // Find the new loop head.
189455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      AllNodesIterator iter(this);
189555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      while (true) {
189655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        BasicBlock* candidate = iter.Next();
189755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        if (candidate == nullptr) {
189855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          // We did not find a true loop head, fall back to a reachable block in any loop.
189955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          ArenaBitVector* current_loop =
190055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko              loop_head_stack.empty() ? nullptr : loop_head_reachable_from[loop_head_stack.back()];
190155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          bb = SelectTopologicalSortOrderFallBack(this, current_loop, &visited_cnt_values,
190255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko                                                  &allocator, &tmp_stack);
190355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          DCHECK(bb != nullptr) << PrettyMethod(cu_->method_idx, *cu_->dex_file);
190455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          if (kIsDebugBuild && cu_->dex_file != nullptr) {
190555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            LOG(INFO) << "Topological sort order: Using fall-back in "
190655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko                << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " BB #" << bb->id
190755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko                << " @0x" << std::hex << bb->start_offset
190855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko                << ", num_blocks = " << std::dec << num_blocks;
190955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          }
191055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          break;
191155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        }
191255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        if (candidate->hidden ||                            // Hidden, or
191355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            candidate->visited ||                           // already processed, or
191455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            visited_cnt_values[candidate->id] == 0u ||      // no processed predecessors, or
191555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            (!loop_head_stack.empty() &&                    // outside current loop.
191655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko             !loop_head_reachable_from[loop_head_stack.back()]->IsBitSet(candidate->id))) {
1917622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko          continue;
1918622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko        }
191955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko
1920e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko        for (BasicBlockId pred_id : candidate->predecessors) {
1921e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko          BasicBlock* pred_bb = GetBasicBlock(pred_id);
1922e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko          DCHECK(pred_bb != nullptr);
192355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          if (pred_bb != candidate && !pred_bb->visited &&
192455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko              !pred_bb->dominators->IsBitSet(candidate->id)) {
1925e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko            candidate = nullptr;  // Set candidate to null to indicate failure.
1926e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko            break;
1927622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko          }
1928622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko        }
1929e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko        if (candidate != nullptr) {
193055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          bb = candidate;
193155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          break;
193255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        }
1933622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko      }
193455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      // Compute blocks from which the loop head is reachable and process those blocks first.
193555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      ArenaBitVector* reachable =
193655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          new (&allocator) ArenaBitVector(&allocator, num_blocks, false, kBitMapMisc);
193755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      loop_head_reachable_from[bb->id] = reachable;
193855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      ComputeUnvisitedReachableFrom(this, bb->id, reachable, &tmp_stack);
193955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      // Now mark as loop head. (Even if it's only a fall back when we don't find a true loop.)
194055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      loop_head_stack.push_back(bb->id);
194155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      max_nested_loops = std::max(max_nested_loops, loop_head_stack.size());
1942622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    }
194344e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
194444e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler    DCHECK_EQ(bb->hidden, false);
1945622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    DCHECK_EQ(bb->visited, false);
1946622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    bb->visited = true;
194744e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
1948622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    // Now add the basic block.
1949e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    uint16_t idx = static_cast<uint16_t>(topological_order_.size());
1950e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    topological_order_indexes_[bb->id] = idx;
1951e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    topological_order_.push_back(bb->id);
195244e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
195355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    // Update visited_cnt_values for children.
1954622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    ChildBlockIterator succIter(bb, this);
1955622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    BasicBlock* successor = succIter.Next();
1956622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    for ( ; successor != nullptr; successor = succIter.Next()) {
195755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      if (successor->hidden) {
1958622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko        continue;
1959622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko      }
196044e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
196155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      // One more predecessor was visited.
196255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      visited_cnt_values[successor->id] += 1u;
1963e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      if (visited_cnt_values[successor->id] == successor->predecessors.size()) {
196455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        if (loop_head_stack.empty() ||
196555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            loop_head_reachable_from[loop_head_stack.back()]->IsBitSet(successor->id)) {
196655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          q.push(successor);
196755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        } else {
196855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          DCHECK(!loop_exit_blocks.IsBitSet(successor->id));
196955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          loop_exit_blocks.SetBit(successor->id);
197055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        }
197144e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler      }
197244e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler    }
197344e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler  }
197455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko
197555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // Prepare the loop head stack for iteration.
1976e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  topological_order_loop_head_stack_.clear();
1977e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  topological_order_loop_head_stack_.reserve(max_nested_loops);
197844e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler}
197944e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
198044e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beylerbool BasicBlock::IsExceptionBlock() const {
198144e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler  if (block_type == kExceptionHandling) {
198244e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler    return true;
198344e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler  }
198444e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler  return false;
198544e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler}
198644e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
198704f4d8abe45d6e79eca983e057de76aea24b7df9Wei Jinbool MIRGraph::HasSuspendTestBetween(BasicBlock* source, BasicBlockId target_id) {
198804f4d8abe45d6e79eca983e057de76aea24b7df9Wei Jin  BasicBlock* target = GetBasicBlock(target_id);
198904f4d8abe45d6e79eca983e057de76aea24b7df9Wei Jin
199004f4d8abe45d6e79eca983e057de76aea24b7df9Wei Jin  if (source == nullptr || target == nullptr)
199104f4d8abe45d6e79eca983e057de76aea24b7df9Wei Jin    return false;
199204f4d8abe45d6e79eca983e057de76aea24b7df9Wei Jin
199304f4d8abe45d6e79eca983e057de76aea24b7df9Wei Jin  int idx;
1994e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  for (idx = gen_suspend_test_list_.size() - 1; idx >= 0; idx--) {
1995e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    BasicBlock* bb = gen_suspend_test_list_[idx];
199604f4d8abe45d6e79eca983e057de76aea24b7df9Wei Jin    if (bb == source)
199704f4d8abe45d6e79eca983e057de76aea24b7df9Wei Jin      return true;  // The block has been inserted by a suspend check before.
199804f4d8abe45d6e79eca983e057de76aea24b7df9Wei Jin    if (source->dominators->IsBitSet(bb->id) && bb->dominators->IsBitSet(target_id))
199904f4d8abe45d6e79eca983e057de76aea24b7df9Wei Jin      return true;
200004f4d8abe45d6e79eca983e057de76aea24b7df9Wei Jin  }
200104f4d8abe45d6e79eca983e057de76aea24b7df9Wei Jin
200204f4d8abe45d6e79eca983e057de76aea24b7df9Wei Jin  return false;
200304f4d8abe45d6e79eca983e057de76aea24b7df9Wei Jin}
200404f4d8abe45d6e79eca983e057de76aea24b7df9Wei Jin
2005f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe BeylerChildBlockIterator::ChildBlockIterator(BasicBlock* bb, MIRGraph* mir_graph)
2006f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    : basic_block_(bb), mir_graph_(mir_graph), visited_fallthrough_(false),
2007f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler      visited_taken_(false), have_successors_(false) {
2008f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  // Check if we actually do have successors.
2009f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  if (basic_block_ != 0 && basic_block_->successor_block_list_type != kNotUsed) {
2010f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    have_successors_ = true;
2011e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    successor_iter_ = basic_block_->successor_blocks.cbegin();
2012f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  }
2013f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler}
2014f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler
2015f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe BeylerBasicBlock* ChildBlockIterator::Next() {
2016f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  // We check if we have a basic block. If we don't we cannot get next child.
2017f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  if (basic_block_ == nullptr) {
2018f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    return nullptr;
2019f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  }
2020f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler
2021f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  // If we haven't visited fallthrough, return that.
2022f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  if (visited_fallthrough_ == false) {
2023f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    visited_fallthrough_ = true;
2024f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler
2025f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    BasicBlock* result = mir_graph_->GetBasicBlock(basic_block_->fall_through);
2026f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    if (result != nullptr) {
2027f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler      return result;
2028f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    }
2029f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  }
2030f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler
2031f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  // If we haven't visited taken, return that.
2032f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  if (visited_taken_ == false) {
2033f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    visited_taken_ = true;
2034f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler
2035f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    BasicBlock* result = mir_graph_->GetBasicBlock(basic_block_->taken);
2036f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    if (result != nullptr) {
2037f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler      return result;
2038f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    }
2039f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  }
2040f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler
2041f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  // We visited both taken and fallthrough. Now check if we have successors we need to visit.
2042f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  if (have_successors_ == true) {
2043f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    // Get information about next successor block.
2044e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    auto end = basic_block_->successor_blocks.cend();
2045e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    while (successor_iter_ != end) {
2046e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      SuccessorBlockInfo* successor_block_info = *successor_iter_;
2047e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      ++successor_iter_;
2048989367a47b015dd85f850cf756b436fb044b5aeaNiranjan Kumar      // If block was replaced by zero block, take next one.
2049989367a47b015dd85f850cf756b436fb044b5aeaNiranjan Kumar      if (successor_block_info->block != NullBasicBlockId) {
2050989367a47b015dd85f850cf756b436fb044b5aeaNiranjan Kumar        return mir_graph_->GetBasicBlock(successor_block_info->block);
2051989367a47b015dd85f850cf756b436fb044b5aeaNiranjan Kumar      }
2052f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    }
2053f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  }
2054f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler
2055f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  // We do not have anything.
2056f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  return nullptr;
2057f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler}
2058f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler
20598512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe BeylerBasicBlock* BasicBlock::Copy(CompilationUnit* c_unit) {
20608512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  MIRGraph* mir_graph = c_unit->mir_graph.get();
20618512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  return Copy(mir_graph);
20628512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
20633aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
20648512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe BeylerBasicBlock* BasicBlock::Copy(MIRGraph* mir_graph) {
20658512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  BasicBlock* result_bb = mir_graph->CreateNewBB(block_type);
20663aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
20678512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // We don't do a memcpy style copy here because it would lead to a lot of things
20688512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // to clean up. Let us do it by hand instead.
20698512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Copy in taken and fallthrough.
20708512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  result_bb->fall_through = fall_through;
20718512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  result_bb->taken = taken;
20723aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
20738512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Copy successor links if needed.
20748512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  ArenaAllocator* arena = mir_graph->GetArena();
20753aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
20768512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  result_bb->successor_block_list_type = successor_block_list_type;
20778512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (result_bb->successor_block_list_type != kNotUsed) {
2078e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    result_bb->successor_blocks.reserve(successor_blocks.size());
2079e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    for (SuccessorBlockInfo* sbi_old : successor_blocks) {
2080e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      SuccessorBlockInfo* sbi_new = static_cast<SuccessorBlockInfo*>(
2081e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko          arena->Alloc(sizeof(SuccessorBlockInfo), kArenaAllocSuccessor));
20828512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      memcpy(sbi_new, sbi_old, sizeof(SuccessorBlockInfo));
2083e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      result_bb->successor_blocks.push_back(sbi_new);
20843aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    }
20858512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
20863aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
20878512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Copy offset, method.
20888512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  result_bb->start_offset = start_offset;
20893aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
20908512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Now copy instructions.
20918512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  for (MIR* mir = first_mir_insn; mir != 0; mir = mir->next) {
20928512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Get a copy first.
20938512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    MIR* copy = mir->Copy(mir_graph);
20943aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
20958512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Append it.
20968512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    result_bb->AppendMIR(copy);
20973aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  }
20983aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
20998512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  return result_bb;
21003aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler}
21013aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
21023aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe BeylerMIR* MIR::Copy(MIRGraph* mir_graph) {
21033aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  MIR* res = mir_graph->NewMIR();
21043aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  *res = *this;
21053aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
21063aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  // Remove links
21073aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  res->next = nullptr;
21083aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  res->bb = NullBasicBlockId;
21093aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  res->ssa_rep = nullptr;
21103aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
21113aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  return res;
21123aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler}
21133aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
21143aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe BeylerMIR* MIR::Copy(CompilationUnit* c_unit) {
21153aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  return Copy(c_unit->mir_graph.get());
21163aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler}
21173aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
21183aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyleruint32_t SSARepresentation::GetStartUseIndex(Instruction::Code opcode) {
21193aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  // Default result.
21203aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  int res = 0;
21213aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
21223aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  // We are basically setting the iputs to their igets counterparts.
21233aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  switch (opcode) {
21243aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT:
21253aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT_OBJECT:
21263aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT_BOOLEAN:
21273aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT_BYTE:
21283aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT_CHAR:
21293aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT_SHORT:
21303aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT_QUICK:
21313aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT_OBJECT_QUICK:
213237f05ef45e0393de812d51261dc293240c17294dFred Shih    case Instruction::IPUT_BOOLEAN_QUICK:
213337f05ef45e0393de812d51261dc293240c17294dFred Shih    case Instruction::IPUT_BYTE_QUICK:
213437f05ef45e0393de812d51261dc293240c17294dFred Shih    case Instruction::IPUT_CHAR_QUICK:
213537f05ef45e0393de812d51261dc293240c17294dFred Shih    case Instruction::IPUT_SHORT_QUICK:
21363aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::APUT:
21373aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::APUT_OBJECT:
21383aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::APUT_BOOLEAN:
21393aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::APUT_BYTE:
21403aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::APUT_CHAR:
21413aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::APUT_SHORT:
21423aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::SPUT:
21433aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::SPUT_OBJECT:
21443aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::SPUT_BOOLEAN:
21453aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::SPUT_BYTE:
21463aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::SPUT_CHAR:
21473aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::SPUT_SHORT:
21483aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler      // Skip the VR containing what to store.
21493aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler      res = 1;
21503aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler      break;
21513aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT_WIDE:
21523aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT_WIDE_QUICK:
21533aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::APUT_WIDE:
21543aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::SPUT_WIDE:
21553aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler      // Skip the two VRs containing what to store.
21563aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler      res = 2;
21573aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler      break;
21583aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    default:
21593aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler      // Do nothing in the general case.
21603aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler      break;
21613aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  }
21623aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
21633aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  return res;
21643aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler}
21653aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
2166c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler/**
2167c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler * @brief Given a decoded instruction, it checks whether the instruction
2168c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler * sets a constant and if it does, more information is provided about the
2169c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler * constant being set.
2170c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler * @param ptr_value pointer to a 64-bit holder for the constant.
2171c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler * @param wide Updated by function whether a wide constant is being set by bytecode.
2172c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler * @return Returns false if the decoded instruction does not represent a constant bytecode.
2173c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler */
2174c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beylerbool MIR::DecodedInstruction::GetConstant(int64_t* ptr_value, bool* wide) const {
2175c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler  bool sets_const = true;
2176c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler  int64_t value = vB;
2177c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler
2178c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler  DCHECK(ptr_value != nullptr);
2179c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler  DCHECK(wide != nullptr);
2180c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler
2181c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler  switch (opcode) {
2182c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    case Instruction::CONST_4:
2183c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    case Instruction::CONST_16:
2184c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    case Instruction::CONST:
2185c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      *wide = false;
2186c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      value <<= 32;      // In order to get the sign extend.
2187c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      value >>= 32;
2188c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      break;
2189c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    case Instruction::CONST_HIGH16:
2190c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      *wide = false;
2191c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      value <<= 48;      // In order to get the sign extend.
2192c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      value >>= 32;
2193c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      break;
2194c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    case Instruction::CONST_WIDE_16:
2195c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    case Instruction::CONST_WIDE_32:
2196c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      *wide = true;
2197c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      value <<= 32;      // In order to get the sign extend.
2198c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      value >>= 32;
2199c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      break;
2200c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    case Instruction::CONST_WIDE:
2201c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      *wide = true;
2202c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      value = vB_wide;
2203c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      break;
2204c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    case Instruction::CONST_WIDE_HIGH16:
2205c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      *wide = true;
2206c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      value <<= 48;      // In order to get the sign extend.
2207c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      break;
2208c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    default:
2209c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      sets_const = false;
2210c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      break;
2211c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler  }
2212c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler
2213c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler  if (sets_const) {
2214c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    *ptr_value = value;
2215c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler  }
2216c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler
2217c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler  return sets_const;
2218c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler}
22198512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
22208512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::ResetOptimizationFlags(uint16_t reset_flags) {
22218512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Reset flags for all MIRs in bb.
22228512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  for (MIR* mir = first_mir_insn; mir != NULL; mir = mir->next) {
22238512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    mir->optimization_flags &= (~reset_flags);
22248512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
22258512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
22268512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
22278512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::Hide(CompilationUnit* c_unit) {
22288512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // First lets make it a dalvik bytecode block so it doesn't have any special meaning.
22298512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  block_type = kDalvikByteCode;
22308512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
22318512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Mark it as hidden.
22328512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  hidden = true;
22338512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
22348512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Detach it from its MIRs so we don't generate code for them. Also detached MIRs
22358512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // are updated to know that they no longer have a parent.
22368512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  for (MIR* mir = first_mir_insn; mir != nullptr; mir = mir->next) {
22378512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    mir->bb = NullBasicBlockId;
22388512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
22398512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  first_mir_insn = nullptr;
22408512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  last_mir_insn = nullptr;
22418512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
22428512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  MIRGraph* mir_graph = c_unit->mir_graph.get();
2243e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  for (BasicBlockId pred_id : predecessors) {
2244e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    BasicBlock* pred_bb = mir_graph->GetBasicBlock(pred_id);
2245e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    DCHECK(pred_bb != nullptr);
22468512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
22478512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Sadly we have to go through the children by hand here.
22488512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    pred_bb->ReplaceChild(id, NullBasicBlockId);
22498512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
22508512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
22518512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Iterate through children of bb we are hiding.
22528512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  ChildBlockIterator successorChildIter(this, mir_graph);
22538512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
22548512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  for (BasicBlock* childPtr = successorChildIter.Next(); childPtr != 0; childPtr = successorChildIter.Next()) {
2255e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    // Erase this predecessor from child.
2256e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    childPtr->ErasePredecessor(id);
22578512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
2258f588b50986fe34cba26fc3ff3100af384c081dbaJean Christophe Beyler
2259f588b50986fe34cba26fc3ff3100af384c081dbaJean Christophe Beyler  // Remove link to children.
2260f588b50986fe34cba26fc3ff3100af384c081dbaJean Christophe Beyler  taken = NullBasicBlockId;
2261f588b50986fe34cba26fc3ff3100af384c081dbaJean Christophe Beyler  fall_through = NullBasicBlockId;
2262f588b50986fe34cba26fc3ff3100af384c081dbaJean Christophe Beyler  successor_block_list_type = kNotUsed;
22638512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
22648512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
22658512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylerbool BasicBlock::IsSSALiveOut(const CompilationUnit* c_unit, int ssa_reg) {
22668512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // In order to determine if the ssa reg is live out, we scan all the MIRs. We remember
22678512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // the last SSA number of the same dalvik register. At the end, if it is different than ssa_reg,
22688512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // then it is not live out of this BB.
22698512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  int dalvik_reg = c_unit->mir_graph->SRegToVReg(ssa_reg);
22708512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
22718512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  int last_ssa_reg = -1;
22728512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
22738512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Walk through the MIRs backwards.
22748512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  for (MIR* mir = first_mir_insn; mir != nullptr; mir = mir->next) {
22758512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Get ssa rep.
22768512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    SSARepresentation *ssa_rep = mir->ssa_rep;
22778512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
22788512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Go through the defines for this MIR.
22798512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    for (int i = 0; i < ssa_rep->num_defs; i++) {
22808512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      DCHECK(ssa_rep->defs != nullptr);
22818512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
22828512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      // Get the ssa reg.
22838512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      int def_ssa_reg = ssa_rep->defs[i];
22848512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
22858512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      // Get dalvik reg.
22868512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      int def_dalvik_reg = c_unit->mir_graph->SRegToVReg(def_ssa_reg);
22878512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
22888512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      // Compare dalvik regs.
22898512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      if (dalvik_reg == def_dalvik_reg) {
22908512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler        // We found a def of the register that we are being asked about.
22918512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler        // Remember it.
22928512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler        last_ssa_reg = def_ssa_reg;
22938512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      }
22948512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    }
22958512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
22968512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
22978512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (last_ssa_reg == -1) {
22988512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // If we get to this point we couldn't find a define of register user asked about.
22998512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Let's assume the user knows what he's doing so we can be safe and say that if we
23008512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // couldn't find a def, it is live out.
23018512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    return true;
23028512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
23038512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
23048512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // If it is not -1, we found a match, is it ssa_reg?
23058512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  return (ssa_reg == last_ssa_reg);
23068512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
23078512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
23088512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylerbool BasicBlock::ReplaceChild(BasicBlockId old_bb, BasicBlockId new_bb) {
23098512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // We need to check taken, fall_through, and successor_blocks to replace.
23108512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  bool found = false;
23118512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (taken == old_bb) {
23128512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    taken = new_bb;
23138512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    found = true;
23148512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
23158512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
23168512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (fall_through == old_bb) {
23178512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    fall_through = new_bb;
23188512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    found = true;
23198512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
23208512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
23218512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (successor_block_list_type != kNotUsed) {
2322e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    for (SuccessorBlockInfo* successor_block_info : successor_blocks) {
23238512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      if (successor_block_info->block == old_bb) {
23248512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler        successor_block_info->block = new_bb;
23258512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler        found = true;
23268512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      }
23278512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    }
23288512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
23298512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
23308512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  return found;
23318512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
23328512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
2333e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Markovoid BasicBlock::ErasePredecessor(BasicBlockId old_pred) {
2334e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  auto pos = std::find(predecessors.begin(), predecessors.end(), old_pred);
2335e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  DCHECK(pos != predecessors.end());
2336e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  predecessors.erase(pos);
2337e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko}
23388512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
2339e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Markovoid BasicBlock::UpdatePredecessor(BasicBlockId old_pred, BasicBlockId new_pred) {
2340e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  DCHECK_NE(new_pred, NullBasicBlockId);
2341e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  auto pos = std::find(predecessors.begin(), predecessors.end(), old_pred);
2342e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  if (pos != predecessors.end()) {
2343e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    *pos = new_pred;
2344e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  } else {
2345e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    // If not found, add it.
2346e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    predecessors.push_back(new_pred);
23478512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
23488512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
23498512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
23508512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler// Create a new basic block with block_id as num_blocks_ that is
23518512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler// post-incremented.
23528512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe BeylerBasicBlock* MIRGraph::CreateNewBB(BBType block_type) {
23538512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  BasicBlock* res = NewMemBB(block_type, num_blocks_++);
2354e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  block_list_.push_back(res);
23558512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  return res;
23568512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
23578512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
23582469e60e6ff08c2a0b4cd1e209246c5d91027679Jean Christophe Beylervoid MIRGraph::CalculateBasicBlockInformation() {
23592469e60e6ff08c2a0b4cd1e209246c5d91027679Jean Christophe Beyler  PassDriverMEPostOpt driver(cu_);
23602469e60e6ff08c2a0b4cd1e209246c5d91027679Jean Christophe Beyler  driver.Launch();
23612469e60e6ff08c2a0b4cd1e209246c5d91027679Jean Christophe Beyler}
23622469e60e6ff08c2a0b4cd1e209246c5d91027679Jean Christophe Beyler
23632469e60e6ff08c2a0b4cd1e209246c5d91027679Jean Christophe Beylervoid MIRGraph::InitializeBasicBlockData() {
2364e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  num_blocks_ = block_list_.size();
23652469e60e6ff08c2a0b4cd1e209246c5d91027679Jean Christophe Beyler}
23662469e60e6ff08c2a0b4cd1e209246c5d91027679Jean Christophe Beyler
2367fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beylerint MIR::DecodedInstruction::FlagsOf() const {
2368fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler  // Calculate new index.
2369fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler  int idx = static_cast<int>(opcode) - kNumPackedOpcodes;
2370fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler
2371fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler  // Check if it is an extended or not.
2372fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler  if (idx < 0) {
2373fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    return Instruction::FlagsOf(opcode);
2374fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler  }
2375fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler
2376fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler  // For extended, we use a switch.
2377fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler  switch (static_cast<int>(opcode)) {
2378fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPhi:
2379fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2380fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpCopy:
2381fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2382fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpFusedCmplFloat:
2383fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue | Instruction::kBranch;
2384fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpFusedCmpgFloat:
2385fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue | Instruction::kBranch;
2386fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpFusedCmplDouble:
2387fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue | Instruction::kBranch;
2388fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpFusedCmpgDouble:
2389fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue | Instruction::kBranch;
2390fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpFusedCmpLong:
2391fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue | Instruction::kBranch;
2392fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpNop:
2393fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2394fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpNullCheck:
2395fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue | Instruction::kThrow;
2396fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpRangeCheck:
2397fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue | Instruction::kThrow;
2398fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpDivZeroCheck:
2399fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue | Instruction::kThrow;
2400fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpCheck:
2401b7fc629dc562ee9f3df04a112a70b7868664f94dUdayan Banerji      return Instruction::kContinue | Instruction::kThrow;
2402fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpCheckPart2:
2403b7fc629dc562ee9f3df04a112a70b7868664f94dUdayan Banerji      return Instruction::kContinue;
2404fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpSelect:
2405fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2406fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpConstVector:
2407fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2408fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpMoveVector:
2409fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2410fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedMultiply:
2411fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2412fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedAddition:
2413fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2414fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedSubtract:
2415fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2416fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedShiftLeft:
2417fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2418fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedSignedShiftRight:
2419fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2420fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedUnsignedShiftRight:
2421fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2422fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedAnd:
2423fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2424fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedOr:
2425fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2426fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedXor:
2427fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2428fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedAddReduce:
2429fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2430fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedReduce:
2431fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2432fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedSet:
2433fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2434fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpReserveVectorRegisters:
2435fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2436fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpReturnVectorRegisters:
2437fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2438b7fc629dc562ee9f3df04a112a70b7868664f94dUdayan Banerji    case kMirOpMemBarrier:
2439b7fc629dc562ee9f3df04a112a70b7868664f94dUdayan Banerji      return Instruction::kContinue;
2440b7fc629dc562ee9f3df04a112a70b7868664f94dUdayan Banerji    case kMirOpPackedArrayGet:
2441b7fc629dc562ee9f3df04a112a70b7868664f94dUdayan Banerji      return Instruction::kContinue | Instruction::kThrow;
2442b7fc629dc562ee9f3df04a112a70b7868664f94dUdayan Banerji    case kMirOpPackedArrayPut:
2443b7fc629dc562ee9f3df04a112a70b7868664f94dUdayan Banerji      return Instruction::kContinue | Instruction::kThrow;
2444fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    default:
2445fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      LOG(WARNING) << "ExtendedFlagsOf: Unhandled case: " << static_cast<int> (opcode);
2446fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return 0;
2447fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler  }
2448fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler}
24497934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom}  // namespace art
2450