mir_graph.cc revision 41b175aba41c9365a1c53b8a1afbd17129c87c14
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>
21cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe#include <unistd.h>
22f3e2cc4a38389aa75eb8ee3973a535254bf1c8d2Nicolas Geoffray
23e77493c7217efdd1a0ecef521a6845a13da0305bIan Rogers#include "base/bit_vector-inl.h"
240b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "base/logging.h"
256282dc12440a2072dc06a616160027ff21bd895eIan Rogers#include "base/stl_util.h"
260b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "base/stringprintf.h"
27b666f4805c8ae707ea6fd7f6c7f375e0b000dba8Mathieu Chartier#include "base/scoped_arena_containers.h"
280b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "compiler_ir.h"
29311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee#include "dex_file-inl.h"
300b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "dex_flags.h"
3129a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers#include "dex_instruction-inl.h"
320b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "driver/compiler_driver.h"
330b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "driver/dex_compilation_unit.h"
345bdab12d8b48ca4c395d9d2c506ebff0df01b734Mathieu Chartier#include "dex/quick/quick_compiler.h"
35f3e2cc4a38389aa75eb8ee3973a535254bf1c8d2Nicolas Geoffray#include "leb128.h"
362469e60e6ff08c2a0b4cd1e209246c5d91027679Jean Christophe Beyler#include "pass_driver_me_post_opt.h"
3753c913bb71b218714823c8c87a1f92830c336f61Andreas Gampe#include "stack.h"
3841b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko#include "utils.h"
395816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko
40311ca169f4727d46a55bdc8dfa0059719fa72b65buzbeenamespace art {
41311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
42311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee#define MAX_PATTERN_LEN 5
43311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
441fd3346740dfb7f47be9922312b68a4227fada96buzbeeconst char* MIRGraph::extended_mir_op_names_[kMirOpLast - kMirOpFirst] = {
451fd3346740dfb7f47be9922312b68a4227fada96buzbee  "Phi",
461fd3346740dfb7f47be9922312b68a4227fada96buzbee  "Copy",
471fd3346740dfb7f47be9922312b68a4227fada96buzbee  "FusedCmplFloat",
481fd3346740dfb7f47be9922312b68a4227fada96buzbee  "FusedCmpgFloat",
491fd3346740dfb7f47be9922312b68a4227fada96buzbee  "FusedCmplDouble",
501fd3346740dfb7f47be9922312b68a4227fada96buzbee  "FusedCmpgDouble",
511fd3346740dfb7f47be9922312b68a4227fada96buzbee  "FusedCmpLong",
521fd3346740dfb7f47be9922312b68a4227fada96buzbee  "Nop",
531fd3346740dfb7f47be9922312b68a4227fada96buzbee  "OpNullCheck",
541fd3346740dfb7f47be9922312b68a4227fada96buzbee  "OpRangeCheck",
551fd3346740dfb7f47be9922312b68a4227fada96buzbee  "OpDivZeroCheck",
56f80552b7e5f627a5dd07af017b7d65dec010ca48Vladimir Marko  "Check",
571fd3346740dfb7f47be9922312b68a4227fada96buzbee  "Select",
58d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "ConstVector",
59d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "MoveVector",
60d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedMultiply",
61d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedAddition",
62d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedSubtract",
63d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedShiftLeft",
64d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedSignedShiftRight",
65d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedUnsignedShiftRight",
66d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedAnd",
67d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedOr",
68d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedXor",
69d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedAddReduce",
70d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedReduce",
71d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  "PackedSet",
7260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  "ReserveVectorRegisters",
7360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  "ReturnVectorRegisters",
74b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler  "MemBarrier",
75b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A  "PackedArrayGet",
76b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A  "PackedArrayPut",
77a262f7707330dccfb50af6345813083182b61043Ningsheng Jian  "MaddInt",
78a262f7707330dccfb50af6345813083182b61043Ningsheng Jian  "MsubInt",
79a262f7707330dccfb50af6345813083182b61043Ningsheng Jian  "MaddLong",
80a262f7707330dccfb50af6345813083182b61043Ningsheng Jian  "MsubLong",
811fd3346740dfb7f47be9922312b68a4227fada96buzbee};
821fd3346740dfb7f47be9922312b68a4227fada96buzbee
83862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbeeMIRGraph::MIRGraph(CompilationUnit* cu, ArenaAllocator* arena)
842cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    : reg_location_(nullptr),
858081d2b8d7a743729557051d0294e040e61c747aVladimir Marko      block_id_map_(std::less<unsigned int>(), arena->Adapter()),
861fd3346740dfb7f47be9922312b68a4227fada96buzbee      cu_(cu),
87e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      ssa_base_vregs_(arena->Adapter(kArenaAllocSSAToDalvikMap)),
88e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      ssa_subscripts_(arena->Adapter(kArenaAllocSSAToDalvikMap)),
892cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      vreg_to_ssa_map_(nullptr),
902cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      ssa_last_defs_(nullptr),
912cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      is_constant_v_(nullptr),
922cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      constant_values_(nullptr),
93e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      use_counts_(arena->Adapter()),
94e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      raw_use_counts_(arena->Adapter()),
95311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      num_reachable_blocks_(0),
964896d7b6fb75add25f2d6ba84346ac83d8ba9d51Jean Christophe Beyler      max_num_reachable_blocks_(0),
97312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko      dfs_orders_up_to_date_(false),
98ffda4993af78484feb7a4ce5497c1796463c0ba1Vladimir Marko      domination_up_to_date_(false),
99ffda4993af78484feb7a4ce5497c1796463c0ba1Vladimir Marko      mir_ssa_rep_up_to_date_(false),
100ffda4993af78484feb7a4ce5497c1796463c0ba1Vladimir Marko      topological_order_up_to_date_(false),
101e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      dfs_order_(arena->Adapter(kArenaAllocDfsPreOrder)),
102e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      dfs_post_order_(arena->Adapter(kArenaAllocDfsPostOrder)),
103e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      dom_post_order_traversal_(arena->Adapter(kArenaAllocDomPostOrder)),
104e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      topological_order_(arena->Adapter(kArenaAllocTopologicalSortOrder)),
105e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      topological_order_loop_ends_(arena->Adapter(kArenaAllocTopologicalSortOrder)),
106e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      topological_order_indexes_(arena->Adapter(kArenaAllocTopologicalSortOrder)),
107e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      topological_order_loop_head_stack_(arena->Adapter(kArenaAllocTopologicalSortOrder)),
108415ac88a6471792a28cf2b457fe4ba9dc099396eVladimir Marko      max_nested_loops_(0u),
1092cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      i_dom_list_(nullptr),
110bfea9c29e809e04bde4a46591fea64c5a7b922fbVladimir Marko      temp_scoped_alloc_(),
111e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      block_list_(arena->Adapter(kArenaAllocBBList)),
1122cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      try_block_addr_(nullptr),
1132cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      entry_block_(nullptr),
1142cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      exit_block_(nullptr),
1152cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      current_code_item_(nullptr),
1168081d2b8d7a743729557051d0294e040e61c747aVladimir Marko      m_units_(arena->Adapter()),
1178081d2b8d7a743729557051d0294e040e61c747aVladimir Marko      method_stack_(arena->Adapter()),
118311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      current_method_(kInvalidEntry),
119311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      current_offset_(kInvalidEntry),
120311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      def_count_(0),
1212cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      opcode_count_(nullptr),
1221fd3346740dfb7f47be9922312b68a4227fada96buzbee      num_ssa_regs_(0),
1238081d2b8d7a743729557051d0294e040e61c747aVladimir Marko      extended_basic_blocks_(arena->Adapter()),
1241fd3346740dfb7f47be9922312b68a4227fada96buzbee      method_sreg_(0),
125862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee      attributes_(METHOD_IS_LEAF),  // Start with leaf assumption, change on encountering invoke.
1262cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      checkstats_(nullptr),
127b48819db07f9a0992a72173380c24249d7fc648abuzbee      arena_(arena),
128b48819db07f9a0992a72173380c24249d7fc648abuzbee      backward_branches_(0),
129da7a69b3fa7bb22d087567364b7eb5a75824efd8Razvan A Lupusoru      forward_branches_(0),
130da7a69b3fa7bb22d087567364b7eb5a75824efd8Razvan A Lupusoru      num_non_special_compiler_temps_(0),
1318d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru      max_available_special_compiler_temps_(1),  // We only need the method ptr as a special temp for now.
1328d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru      requested_backend_temp_(false),
1338d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru      compiler_temps_committed_(false),
134be0e546730e532ef0987cd4bde2c6f5a1b14dd2aVladimir Marko      punt_to_interpreter_(false),
1353d73ba2ce682edfaf41f29521bd6039c6499a1c5Vladimir Marko      merged_df_flags_(0u),
136e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      ifield_lowering_infos_(arena->Adapter(kArenaAllocLoweringInfo)),
137e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      sfield_lowering_infos_(arena->Adapter(kArenaAllocLoweringInfo)),
138e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      method_lowering_infos_(arena->Adapter(kArenaAllocLoweringInfo)),
1398b858e16563ebf8e522df026a6ab409f1bd9b3deVladimir Marko      suspend_checks_in_loops_(nullptr) {
140f585e549682a98eec12f92033e9634dc162b7df8Vladimir Marko  memset(&temp_, 0, sizeof(temp_));
141e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  use_counts_.reserve(256);
142e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  raw_use_counts_.reserve(256);
143e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  block_list_.reserve(100);
144862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  try_block_addr_ = new (arena_) ArenaBitVector(arena_, 0, true /* expandable */);
1458d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru
1468d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru
1478d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru  if (cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) {
1488d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru    // X86 requires a temp to keep track of the method address.
1498d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru    // TODO For x86_64, addressing can be done with RIP. When that is implemented,
1508d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru    // this needs to be updated to reserve 0 temps for BE.
1518d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru    max_available_non_special_compiler_temps_ = cu_->target64 ? 2 : 1;
1528d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru    reserved_temps_for_backend_ = max_available_non_special_compiler_temps_;
1538d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru  } else {
1548d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru    // Other architectures do not have a known lower bound for non-special temps.
1558d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru    // We allow the update of the max to happen at BE initialization stage and simply set 0 for now.
1568d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru    max_available_non_special_compiler_temps_ = 0;
1578d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru    reserved_temps_for_backend_ = 0;
1588d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru  }
159311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
160311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
1616282dc12440a2072dc06a616160027ff21bd895eIan RogersMIRGraph::~MIRGraph() {
162e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  STLDeleteElements(&block_list_);
1636282dc12440a2072dc06a616160027ff21bd895eIan Rogers  STLDeleteElements(&m_units_);
1646282dc12440a2072dc06a616160027ff21bd895eIan Rogers}
1656282dc12440a2072dc06a616160027ff21bd895eIan Rogers
166311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/*
167311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Parse an instruction, return the length of the instruction
168311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee */
16929a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogersint MIRGraph::ParseInsn(const uint16_t* code_ptr, MIR::DecodedInstruction* decoded_instruction) {
17029a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  const Instruction* inst = Instruction::At(code_ptr);
17129a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  decoded_instruction->opcode = inst->Opcode();
17229a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  decoded_instruction->vA = inst->HasVRegA() ? inst->VRegA() : 0;
17329a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  decoded_instruction->vB = inst->HasVRegB() ? inst->VRegB() : 0;
17429a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  decoded_instruction->vB_wide = inst->HasWideVRegB() ? inst->WideVRegB() : 0;
17529a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  decoded_instruction->vC = inst->HasVRegC() ?  inst->VRegC() : 0;
17629a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  if (inst->HasVarArgs()) {
17729a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers    inst->GetVarArgs(decoded_instruction->arg);
17829a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  }
17929a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  return inst->SizeInCodeUnits();
180311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
181311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
182311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
183311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Split an existing block from the specified code offset into two */
1840d82948094d9a198e01aa95f64012bdedd5b6fc9buzbeeBasicBlock* MIRGraph::SplitBlock(DexOffset code_offset,
1852ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                 BasicBlock* orig_block, BasicBlock** immed_pred_block_p) {
1860d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  DCHECK_GT(code_offset, orig_block->start_offset);
187311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  MIR* insn = orig_block->first_mir_insn;
1882cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  MIR* prev = nullptr;  // Will be set to instruction before split.
189311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  while (insn) {
190311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (insn->offset == code_offset) break;
1910d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    prev = insn;
192311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    insn = insn->next;
193311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
1942cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (insn == nullptr) {
195311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    LOG(FATAL) << "Break split failed";
196311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
19733c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski  // Now insn is at the instruction where we want to split, namely
19833c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski  // insn will be the first instruction of the "bottom" block.
19933c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski  // Similarly, prev will be the last instruction of the "top" block
20033c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski
201e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  BasicBlock* bottom_block = CreateNewBB(kDalvikByteCode);
202311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
203311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  bottom_block->start_offset = code_offset;
204311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  bottom_block->first_mir_insn = insn;
205311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  bottom_block->last_mir_insn = orig_block->last_mir_insn;
206311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
20790223cc2e0bfb5a2b55e9ffed896ef327b9f3d2eJunmo Park  /* If this block was terminated by a return, conditional branch or throw,
20890223cc2e0bfb5a2b55e9ffed896ef327b9f3d2eJunmo Park   * the flag needs to go with the bottom block
20990223cc2e0bfb5a2b55e9ffed896ef327b9f3d2eJunmo Park   */
210311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  bottom_block->terminated_by_return = orig_block->terminated_by_return;
211311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  orig_block->terminated_by_return = false;
212311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
21390223cc2e0bfb5a2b55e9ffed896ef327b9f3d2eJunmo Park  bottom_block->conditional_branch = orig_block->conditional_branch;
21490223cc2e0bfb5a2b55e9ffed896ef327b9f3d2eJunmo Park  orig_block->conditional_branch = false;
21590223cc2e0bfb5a2b55e9ffed896ef327b9f3d2eJunmo Park
21690223cc2e0bfb5a2b55e9ffed896ef327b9f3d2eJunmo Park  bottom_block->explicit_throw = orig_block->explicit_throw;
21790223cc2e0bfb5a2b55e9ffed896ef327b9f3d2eJunmo Park  orig_block->explicit_throw = false;
21890223cc2e0bfb5a2b55e9ffed896ef327b9f3d2eJunmo Park
219311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /* Handle the taken path */
220311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  bottom_block->taken = orig_block->taken;
2210d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  if (bottom_block->taken != NullBasicBlockId) {
2220d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    orig_block->taken = NullBasicBlockId;
2230d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    BasicBlock* bb_taken = GetBasicBlock(bottom_block->taken);
224e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    bb_taken->ErasePredecessor(orig_block->id);
225e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    bb_taken->predecessors.push_back(bottom_block->id);
226311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
227311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
228311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /* Handle the fallthrough path */
229311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  bottom_block->fall_through = orig_block->fall_through;
2300d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  orig_block->fall_through = bottom_block->id;
231e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  bottom_block->predecessors.push_back(orig_block->id);
2320d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  if (bottom_block->fall_through != NullBasicBlockId) {
2330d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    BasicBlock* bb_fall_through = GetBasicBlock(bottom_block->fall_through);
234e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    bb_fall_through->ErasePredecessor(orig_block->id);
235e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    bb_fall_through->predecessors.push_back(bottom_block->id);
236311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
237311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
238311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /* Handle the successor list */
2390d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  if (orig_block->successor_block_list_type != kNotUsed) {
2400d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    bottom_block->successor_block_list_type = orig_block->successor_block_list_type;
241e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    bottom_block->successor_blocks.swap(orig_block->successor_blocks);
2420d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    orig_block->successor_block_list_type = kNotUsed;
243e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    DCHECK(orig_block->successor_blocks.empty());  // Empty after the swap() above.
244e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    for (SuccessorBlockInfo* successor_block_info : bottom_block->successor_blocks) {
2458512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      BasicBlock* bb = GetBasicBlock(successor_block_info->block);
246989367a47b015dd85f850cf756b436fb044b5aeaNiranjan Kumar      if (bb != nullptr) {
247e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko        bb->ErasePredecessor(orig_block->id);
248e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko        bb->predecessors.push_back(bottom_block->id);
249989367a47b015dd85f850cf756b436fb044b5aeaNiranjan Kumar      }
250311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
251311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
252311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
2530d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  orig_block->last_mir_insn = prev;
2543aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  prev->next = nullptr;
255311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
256311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /*
257311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * Update the immediate predecessor block pointer so that outgoing edges
258311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * can be applied to the proper block.
259311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   */
260311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (immed_pred_block_p) {
261311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    DCHECK_EQ(*immed_pred_block_p, orig_block);
262311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    *immed_pred_block_p = bottom_block;
263311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
264b48819db07f9a0992a72173380c24249d7fc648abuzbee
265b48819db07f9a0992a72173380c24249d7fc648abuzbee  // Associate dex instructions in the bottom block with the new container.
2664376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko  DCHECK(insn != nullptr);
2674376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko  DCHECK(insn != orig_block->first_mir_insn);
2684376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko  DCHECK(insn == bottom_block->first_mir_insn);
2694376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko  DCHECK_EQ(insn->offset, bottom_block->start_offset);
27033c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski  // Scan the "bottom" instructions, remapping them to the
27133c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski  // newly created "bottom" block.
2724376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko  MIR* p = insn;
27333c17021c74b4e1911851ca89d634d15ed811d8dMathew Zaleski  p->bb = bottom_block->id;
2744376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko  while (p != bottom_block->last_mir_insn) {
2754376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko    p = p->next;
2764376c87eb45b287fad77a16738e76ba28956ab7dVladimir Marko    DCHECK(p != nullptr);
2773aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    p->bb = bottom_block->id;
278b48819db07f9a0992a72173380c24249d7fc648abuzbee  }
279b48819db07f9a0992a72173380c24249d7fc648abuzbee
280311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  return bottom_block;
281311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
282311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
283311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/*
284311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Given a code offset, find out the block that starts with it. If the offset
285311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * is in the middle of an existing block, split it into two.  If immed_pred_block_p
286311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * is not non-null and is the block being split, update *immed_pred_block_p to
287311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * point to the bottom block so that outgoing edges can be set up properly
288311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * (by the caller)
289311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee * Utilizes a map for fast lookup of the typical cases.
290311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee */
2916a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan RogersBasicBlock* MIRGraph::FindBlock(DexOffset code_offset, bool create,
29272f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                BasicBlock** immed_pred_block_p,
29372f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                ScopedArenaVector<uint16_t>* dex_pc_to_block_map) {
29422c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle  if (UNLIKELY(code_offset >= current_code_item_->insns_size_in_code_units_)) {
29522c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle    // There can be a fall-through out of the method code. We shall record such a block
29622c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle    // here (assuming create==true) and check that it's dead at the end of InlineMethod().
29722c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle    // Though we're only aware of the cases where code_offset is exactly the same as
29822c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle    // insns_size_in_code_units_, treat greater code_offset the same just in case.
29922c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle    code_offset = current_code_item_->insns_size_in_code_units_;
300311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
301b48819db07f9a0992a72173380c24249d7fc648abuzbee
30272f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu  int block_id = (*dex_pc_to_block_map)[code_offset];
303e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  BasicBlock* bb = GetBasicBlock(block_id);
304b48819db07f9a0992a72173380c24249d7fc648abuzbee
3056a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  if ((bb != nullptr) && (bb->start_offset == code_offset)) {
306b48819db07f9a0992a72173380c24249d7fc648abuzbee    // Does this containing block start with the desired instruction?
307bd663de599b16229085759366c56e2ed5a1dc7ecbuzbee    return bb;
308bd663de599b16229085759366c56e2ed5a1dc7ecbuzbee  }
309311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
310b48819db07f9a0992a72173380c24249d7fc648abuzbee  // No direct hit.
311b48819db07f9a0992a72173380c24249d7fc648abuzbee  if (!create) {
3126a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    return nullptr;
313b48819db07f9a0992a72173380c24249d7fc648abuzbee  }
314b48819db07f9a0992a72173380c24249d7fc648abuzbee
3156a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  if (bb != nullptr) {
316b48819db07f9a0992a72173380c24249d7fc648abuzbee    // The target exists somewhere in an existing block.
31772f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu    BasicBlock* bottom_block = SplitBlock(code_offset, bb, bb == *immed_pred_block_p ?  immed_pred_block_p : nullptr);
31872f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu    DCHECK(bottom_block != nullptr);
31972f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu    MIR* p = bottom_block->first_mir_insn;
32072f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu    BasicBlock* orig_block = bb;
32172f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu    DCHECK_EQ((*dex_pc_to_block_map)[p->offset], orig_block->id);
32272f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu    // Scan the "bottom" instructions, remapping them to the
32372f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu    // newly created "bottom" block.
32472f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu    (*dex_pc_to_block_map)[p->offset] = bottom_block->id;
32572f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu    while (p != bottom_block->last_mir_insn) {
32672f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu      p = p->next;
32772f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu      DCHECK(p != nullptr);
32872f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu      int opcode = p->dalvikInsn.opcode;
32972f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu      /*
33072f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu       * Some messiness here to ensure that we only enter real opcodes and only the
33172f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu       * first half of a potentially throwing instruction that has been split into
33272f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu       * CHECK and work portions. Since the 2nd half of a split operation is always
33372f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu       * the first in a BasicBlock, we can't hit it here.
33472f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu       */
33572f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu      if ((opcode == kMirOpCheck) || !MIR::DecodedInstruction::IsPseudoMirOp(opcode)) {
33672f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu        BasicBlockId mapped_id = (*dex_pc_to_block_map)[p->offset];
33772f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu        // At first glance the instructions should all be mapped to orig_block.
33872f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu        // However, multiple instructions may correspond to the same dex, hence an earlier
33972f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu        // instruction may have already moved the mapping for dex to bottom_block.
34072f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu        DCHECK((mapped_id == orig_block->id) || (mapped_id == bottom_block->id));
34172f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu        (*dex_pc_to_block_map)[p->offset] = bottom_block->id;
34272f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu      }
34372f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu    }
34472f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu    return bottom_block;
345311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
346311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
347b48819db07f9a0992a72173380c24249d7fc648abuzbee  // Create a new block.
348e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  bb = CreateNewBB(kDalvikByteCode);
349311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  bb->start_offset = code_offset;
35072f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu  (*dex_pc_to_block_map)[bb->start_offset] = bb->id;
351311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  return bb;
352311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
353311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
354b48819db07f9a0992a72173380c24249d7fc648abuzbee
355311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Identify code range in try blocks and set up the empty catch blocks */
35672f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fuvoid MIRGraph::ProcessTryCatchBlocks(ScopedArenaVector<uint16_t>* dex_pc_to_block_map) {
357311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  int tries_size = current_code_item_->tries_size_;
3580d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  DexOffset offset;
359311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
360311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (tries_size == 0) {
361311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    return;
362311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
363311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
364311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  for (int i = 0; i < tries_size; i++) {
365311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    const DexFile::TryItem* pTry =
366311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        DexFile::GetTryItems(*current_code_item_, i);
3670d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    DexOffset start_offset = pTry->start_addr_;
3680d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    DexOffset end_offset = start_offset + pTry->insn_count_;
369311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    for (offset = start_offset; offset < end_offset; offset++) {
370862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee      try_block_addr_->SetBit(offset);
371311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
372311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
373311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
3748512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Iterate over each of the handlers to enqueue the empty Catch blocks.
37513735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(*current_code_item_, 0);
376311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
377311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  for (uint32_t idx = 0; idx < handlers_size; idx++) {
378311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    CatchHandlerIterator iterator(handlers_ptr);
379311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    for (; iterator.HasNext(); iterator.Next()) {
380311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      uint32_t address = iterator.GetHandlerAddress();
38172f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu      FindBlock(address, true /*create*/, /* immed_pred_block_p */ nullptr, dex_pc_to_block_map);
382311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
383311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    handlers_ptr = iterator.EndDataPointer();
384311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
385311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
386311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
387e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Markobool MIRGraph::IsBadMonitorExitCatch(NarrowDexOffset monitor_exit_offset,
388e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko                                     NarrowDexOffset catch_offset) {
389e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  // Catches for monitor-exit during stack unwinding have the pattern
390e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  //   move-exception (move)* (goto)? monitor-exit throw
391e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  // In the currently generated dex bytecode we see these catching a bytecode range including
392e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  // either its own or an identical monitor-exit, http://b/15745363 . This function checks if
393e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  // it's the case for a given monitor-exit and catch block so that we can ignore it.
394e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  // (We don't want to ignore all monitor-exit catches since one could enclose a synchronized
395e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  // block in a try-block and catch the NPE, Error or Throwable and we should let it through;
396e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  // even though a throwing monitor-exit certainly indicates a bytecode error.)
39709ae022f55ab27edf4802baf7a05e76d7dc823a9Razvan A Lupusoru  const Instruction* monitor_exit = Instruction::At(current_code_item_->insns_ + monitor_exit_offset);
398e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  DCHECK(monitor_exit->Opcode() == Instruction::MONITOR_EXIT);
399e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  int monitor_reg = monitor_exit->VRegA_11x();
40009ae022f55ab27edf4802baf7a05e76d7dc823a9Razvan A Lupusoru  const Instruction* check_insn = Instruction::At(current_code_item_->insns_ + catch_offset);
401e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  DCHECK(check_insn->Opcode() == Instruction::MOVE_EXCEPTION);
402e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  if (check_insn->VRegA_11x() == monitor_reg) {
403e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    // Unexpected move-exception to the same register. Probably not the pattern we're looking for.
404e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    return false;
405e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  }
406e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  check_insn = check_insn->Next();
407e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  while (true) {
408e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    int dest = -1;
409e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    bool wide = false;
410e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    switch (check_insn->Opcode()) {
411e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::MOVE_WIDE:
412e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        wide = true;
413fc787ecd91127b2c8458afd94e5148e2ae51a1f5Ian Rogers        FALLTHROUGH_INTENDED;
414e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::MOVE_OBJECT:
415e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::MOVE:
416e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        dest = check_insn->VRegA_12x();
417e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        break;
418e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko
419e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::MOVE_WIDE_FROM16:
420e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        wide = true;
421fc787ecd91127b2c8458afd94e5148e2ae51a1f5Ian Rogers        FALLTHROUGH_INTENDED;
422e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::MOVE_OBJECT_FROM16:
423e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::MOVE_FROM16:
424e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        dest = check_insn->VRegA_22x();
425e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        break;
426e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko
427e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::MOVE_WIDE_16:
428e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        wide = true;
429fc787ecd91127b2c8458afd94e5148e2ae51a1f5Ian Rogers        FALLTHROUGH_INTENDED;
430e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::MOVE_OBJECT_16:
431e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::MOVE_16:
432e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        dest = check_insn->VRegA_32x();
433e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        break;
434e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko
435e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::GOTO:
436e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::GOTO_16:
437e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      case Instruction::GOTO_32:
438e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        check_insn = check_insn->RelativeAt(check_insn->GetTargetOffset());
439fc787ecd91127b2c8458afd94e5148e2ae51a1f5Ian Rogers        FALLTHROUGH_INTENDED;
440e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      default:
441e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        return check_insn->Opcode() == Instruction::MONITOR_EXIT &&
442e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko            check_insn->VRegA_11x() == monitor_reg;
443e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    }
444e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko
445e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    if (dest == monitor_reg || (wide && dest + 1 == monitor_reg)) {
446e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      return false;
447e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    }
448e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko
449e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    check_insn = check_insn->Next();
450e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  }
451e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko}
452e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko
453311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Process instructions with the kBranch flag */
4540d82948094d9a198e01aa95f64012bdedd5b6fc9buzbeeBasicBlock* MIRGraph::ProcessCanBranch(BasicBlock* cur_block, MIR* insn, DexOffset cur_offset,
4550d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee                                       int width, int flags, const uint16_t* code_ptr,
45672f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                       const uint16_t* code_end,
45772f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                       ScopedArenaVector<uint16_t>* dex_pc_to_block_map) {
4580d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  DexOffset target = cur_offset;
459311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  switch (insn->dalvikInsn.opcode) {
460311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::GOTO:
461311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::GOTO_16:
462311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::GOTO_32:
463311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      target += insn->dalvikInsn.vA;
464311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      break;
465311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_EQ:
466311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_NE:
467311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_LT:
468311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_GE:
469311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_GT:
470311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_LE:
471311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      cur_block->conditional_branch = true;
472311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      target += insn->dalvikInsn.vC;
473311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      break;
474311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_EQZ:
475311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_NEZ:
476311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_LTZ:
477311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_GEZ:
478311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_GTZ:
479311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    case Instruction::IF_LEZ:
480311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      cur_block->conditional_branch = true;
481311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      target += insn->dalvikInsn.vB;
482311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      break;
483311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    default:
484311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      LOG(FATAL) << "Unexpected opcode(" << insn->dalvikInsn.opcode << ") with kBranch set";
485311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
486b48819db07f9a0992a72173380c24249d7fc648abuzbee  CountBranch(target);
4876a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  BasicBlock* taken_block = FindBlock(target, /* create */ true,
48872f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                      /* immed_pred_block_p */ &cur_block,
48972f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                      dex_pc_to_block_map);
49022c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle  DCHECK(taken_block != nullptr);
4910d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  cur_block->taken = taken_block->id;
492e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  taken_block->predecessors.push_back(cur_block->id);
493311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
494311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /* Always terminate the current block for conditional branches */
495311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (flags & Instruction::kContinue) {
4962469e60e6ff08c2a0b4cd1e209246c5d91027679Jean Christophe Beyler    BasicBlock* fallthrough_block = FindBlock(cur_offset +  width,
497311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                             /* create */
498311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                             true,
499311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                                             /* immed_pred_block_p */
50072f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                             &cur_block,
50172f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                             dex_pc_to_block_map);
50222c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle    DCHECK(fallthrough_block != nullptr);
5030d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    cur_block->fall_through = fallthrough_block->id;
504e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    fallthrough_block->predecessors.push_back(cur_block->id);
505311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  } else if (code_ptr < code_end) {
50672f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu    FindBlock(cur_offset + width, /* create */ true, /* immed_pred_block_p */ nullptr, dex_pc_to_block_map);
507311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
508311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  return cur_block;
509311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
510311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
511311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Process instructions with the kSwitch flag */
51217189ac098b2f156713db1821b49db7b2f018bbebuzbeeBasicBlock* MIRGraph::ProcessCanSwitch(BasicBlock* cur_block, MIR* insn, DexOffset cur_offset,
51372f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                       int width, int flags,
51472f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                       ScopedArenaVector<uint16_t>* dex_pc_to_block_map) {
5156a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNUSED(flags);
516311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  const uint16_t* switch_data =
51722c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle      reinterpret_cast<const uint16_t*>(GetCurrentInsns() + cur_offset +
51822c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle          static_cast<int32_t>(insn->dalvikInsn.vB));
519311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  int size;
520311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  const int* keyTable;
521311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  const int* target_table;
522311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  int i;
523311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  int first_key;
524311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
525311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /*
526311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * Packed switch data format:
527311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *  ushort ident = 0x0100   magic value
528311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *  ushort size             number of entries in the table
529311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *  int first_key           first (and lowest) switch case value
530311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *  int targets[size]       branch targets, relative to switch opcode
531311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *
532311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * Total size is (4+size*2) 16-bit code units.
533311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   */
534311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) {
535311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    DCHECK_EQ(static_cast<int>(switch_data[0]),
536311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee              static_cast<int>(Instruction::kPackedSwitchSignature));
537311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    size = switch_data[1];
538311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    first_key = switch_data[2] | (switch_data[3] << 16);
539311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    target_table = reinterpret_cast<const int*>(&switch_data[4]);
5402cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    keyTable = nullptr;        // Make the compiler happy.
541311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /*
542311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * Sparse switch data format:
543311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *  ushort ident = 0x0200   magic value
544311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *  ushort size             number of entries in the table; > 0
545311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *  int keys[size]          keys, sorted low-to-high; 32-bit aligned
546311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *  int targets[size]       branch targets, relative to switch opcode
547311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   *
548311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * Total size is (2+size*4) 16-bit code units.
549311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   */
550311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  } else {
551311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    DCHECK_EQ(static_cast<int>(switch_data[0]),
552311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee              static_cast<int>(Instruction::kSparseSwitchSignature));
553311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    size = switch_data[1];
554311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    keyTable = reinterpret_cast<const int*>(&switch_data[2]);
555311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    target_table = reinterpret_cast<const int*>(&switch_data[2 + size*2]);
5568512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    first_key = 0;   // To make the compiler happy.
557311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
558311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
5590d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  if (cur_block->successor_block_list_type != kNotUsed) {
560311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    LOG(FATAL) << "Successor block list already in use: "
5610d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee               << static_cast<int>(cur_block->successor_block_list_type);
562311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
5630d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  cur_block->successor_block_list_type =
5640d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee      (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?  kPackedSwitch : kSparseSwitch;
565e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  cur_block->successor_blocks.reserve(size);
566311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
567311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  for (i = 0; i < size; i++) {
5686a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    BasicBlock* case_block = FindBlock(cur_offset + target_table[i],  /* create */ true,
56972f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                       /* immed_pred_block_p */ &cur_block,
57072f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                       dex_pc_to_block_map);
57122c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle    DCHECK(case_block != nullptr);
5728512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    SuccessorBlockInfo* successor_block_info =
573f6c4b3ba3825de1dbb3e747a68b809c6cc8eb4dbMathieu Chartier        static_cast<SuccessorBlockInfo*>(arena_->Alloc(sizeof(SuccessorBlockInfo),
57483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko                                                       kArenaAllocSuccessor));
5750d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    successor_block_info->block = case_block->id;
576311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    successor_block_info->key =
577311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
578311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        first_key + i : keyTable[i];
579e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    cur_block->successor_blocks.push_back(successor_block_info);
580e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    case_block->predecessors.push_back(cur_block->id);
581311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
582311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
583311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /* Fall-through case */
5846a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  BasicBlock* fallthrough_block = FindBlock(cur_offset +  width, /* create */ true,
58572f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                            /* immed_pred_block_p */ nullptr,
58672f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                            dex_pc_to_block_map);
58722c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle  DCHECK(fallthrough_block != nullptr);
5880d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  cur_block->fall_through = fallthrough_block->id;
589e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  fallthrough_block->predecessors.push_back(cur_block->id);
59017189ac098b2f156713db1821b49db7b2f018bbebuzbee  return cur_block;
591311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
592311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
593311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Process instructions with the kThrow flag */
5940d82948094d9a198e01aa95f64012bdedd5b6fc9buzbeeBasicBlock* MIRGraph::ProcessCanThrow(BasicBlock* cur_block, MIR* insn, DexOffset cur_offset,
5950d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee                                      int width, int flags, ArenaBitVector* try_block_addr,
59672f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                      const uint16_t* code_ptr, const uint16_t* code_end,
59772f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                      ScopedArenaVector<uint16_t>* dex_pc_to_block_map) {
5986a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNUSED(flags);
599862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  bool in_try_block = try_block_addr->IsBitSet(cur_offset);
60017189ac098b2f156713db1821b49db7b2f018bbebuzbee  bool is_throw = (insn->dalvikInsn.opcode == Instruction::THROW);
601311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
602311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /* In try block */
603311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (in_try_block) {
604311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    CatchHandlerIterator iterator(*current_code_item_, cur_offset);
605311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
6060d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    if (cur_block->successor_block_list_type != kNotUsed) {
607311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      LOG(INFO) << PrettyMethod(cu_->method_idx, *cu_->dex_file);
608311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      LOG(FATAL) << "Successor block list already in use: "
6090d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee                 << static_cast<int>(cur_block->successor_block_list_type);
610311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
611311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
61202c8cc6d1312a2b55533f02f6369dc7c94672f90Brian Carlstrom    for (; iterator.HasNext(); iterator.Next()) {
6136a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers      BasicBlock* catch_block = FindBlock(iterator.GetHandlerAddress(), false /* create */,
61472f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                          nullptr /* immed_pred_block_p */,
61572f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                          dex_pc_to_block_map);
616e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      if (insn->dalvikInsn.opcode == Instruction::MONITOR_EXIT &&
617e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko          IsBadMonitorExitCatch(insn->offset, catch_block->start_offset)) {
618e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        // Don't allow monitor-exit to catch its own exception, http://b/15745363 .
619e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        continue;
620e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      }
621e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      if (cur_block->successor_block_list_type == kNotUsed) {
622e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko        cur_block->successor_block_list_type = kCatch;
623e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko      }
624311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      catch_block->catch_entry = true;
625311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      if (kIsDebugBuild) {
626311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        catches_.insert(catch_block->start_offset);
627311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      }
6288512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      SuccessorBlockInfo* successor_block_info = reinterpret_cast<SuccessorBlockInfo*>
62983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko          (arena_->Alloc(sizeof(SuccessorBlockInfo), kArenaAllocSuccessor));
6300d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee      successor_block_info->block = catch_block->id;
631311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      successor_block_info->key = iterator.GetHandlerTypeIndex();
632e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      cur_block->successor_blocks.push_back(successor_block_info);
633e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      catch_block->predecessors.push_back(cur_block->id);
634311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
635e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko    in_try_block = (cur_block->successor_block_list_type != kNotUsed);
636e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  }
637e767f6ce3997f7634b26e7651bc7b90c060d3965Vladimir Marko  bool build_all_edges =
638e767f6ce3997f7634b26e7651bc7b90c060d3965Vladimir Marko      (cu_->disable_opt & (1 << kSuppressExceptionEdges)) || is_throw || in_try_block;
639e8ae81453e1d6c19d7db2001a1e7b1849f74241cVladimir Marko  if (!in_try_block && build_all_edges) {
640e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    BasicBlock* eh_block = CreateNewBB(kExceptionHandling);
6410d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    cur_block->taken = eh_block->id;
642311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    eh_block->start_offset = cur_offset;
643e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    eh_block->predecessors.push_back(cur_block->id);
644311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
645311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
64617189ac098b2f156713db1821b49db7b2f018bbebuzbee  if (is_throw) {
647311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    cur_block->explicit_throw = true;
6482724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee    if (code_ptr < code_end) {
6498512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      // Force creation of new block following THROW via side-effect.
65072f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu      FindBlock(cur_offset + width, /* create */ true, /* immed_pred_block_p */ nullptr, dex_pc_to_block_map);
651311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
652311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (!in_try_block) {
653311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       // Don't split a THROW that can't rethrow - we're done.
654311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      return cur_block;
655311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
656311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
657311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
65817189ac098b2f156713db1821b49db7b2f018bbebuzbee  if (!build_all_edges) {
65917189ac098b2f156713db1821b49db7b2f018bbebuzbee    /*
66017189ac098b2f156713db1821b49db7b2f018bbebuzbee     * Even though there is an exception edge here, control cannot return to this
66117189ac098b2f156713db1821b49db7b2f018bbebuzbee     * method.  Thus, for the purposes of dataflow analysis and optimization, we can
66217189ac098b2f156713db1821b49db7b2f018bbebuzbee     * ignore the edge.  Doing this reduces compile time, and increases the scope
66317189ac098b2f156713db1821b49db7b2f018bbebuzbee     * of the basic-block level optimization pass.
66417189ac098b2f156713db1821b49db7b2f018bbebuzbee     */
66517189ac098b2f156713db1821b49db7b2f018bbebuzbee    return cur_block;
66617189ac098b2f156713db1821b49db7b2f018bbebuzbee  }
66717189ac098b2f156713db1821b49db7b2f018bbebuzbee
668311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /*
669311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * Split the potentially-throwing instruction into two parts.
670311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * The first half will be a pseudo-op that captures the exception
671311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * edges and terminates the basic block.  It always falls through.
672311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * Then, create a new basic block that begins with the throwing instruction
673311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * (minus exceptions).  Note: this new basic block must NOT be entered into
674311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * the block_map.  If the potentially-throwing instruction is the target of a
675311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * future branch, we need to find the check psuedo half.  The new
676311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * basic block containing the work portion of the instruction should
677311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * only be entered via fallthrough from the block containing the
678311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * pseudo exception edge MIR.  Note also that this new block is
679311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * not automatically terminated after the work portion, and may
680311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   * contain following instructions.
681b48819db07f9a0992a72173380c24249d7fc648abuzbee   *
68272f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu   * Note also that the dex_pc_to_block_map entry for the potentially
683b48819db07f9a0992a72173380c24249d7fc648abuzbee   * throwing instruction will refer to the original basic block.
684311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee   */
685e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  BasicBlock* new_block = CreateNewBB(kDalvikByteCode);
686311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  new_block->start_offset = insn->offset;
6870d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  cur_block->fall_through = new_block->id;
688e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  new_block->predecessors.push_back(cur_block->id);
6893aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  MIR* new_insn = NewMIR();
690311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  *new_insn = *insn;
69135ba7f3a78d38885ec54e61ed060d2771eeceea7buzbee  insn->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpCheck);
6928512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Associate the two halves.
693311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  insn->meta.throw_insn = new_insn;
694cdacac4a8196bdc620185079ec9e886329606f3dJean Christophe Beyler  new_block->AppendMIR(new_insn);
695311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  return new_block;
696311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
697311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
698311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Parse a Dex method and insert it into the MIRGraph at the current insert point. */
699311ca169f4727d46a55bdc8dfa0059719fa72b65buzbeevoid MIRGraph::InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_flags,
70020f85597828194c12be10d3a927999def066555eVladimir Marko                           InvokeType invoke_type ATTRIBUTE_UNUSED, uint16_t class_def_idx,
7012ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                           uint32_t method_idx, jobject class_loader, const DexFile& dex_file) {
702311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  current_code_item_ = code_item;
703311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  method_stack_.push_back(std::make_pair(current_method_, current_offset_));
704311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  current_method_ = m_units_.size();
705311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  current_offset_ = 0;
706311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  // TODO: will need to snapshot stack image and use that as the mir context identification.
707c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko  m_units_.push_back(new (arena_) DexCompilationUnit(
708c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko      cu_, class_loader, Runtime::Current()->GetClassLinker(), dex_file,
709c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko      current_code_item_, class_def_idx, method_idx, access_flags,
710c91df2d6339dd4adf2da582372451df19ce2ff44Vladimir Marko      cu_->compiler_driver->GetVerifiedMethod(&dex_file, method_idx)));
711311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  const uint16_t* code_ptr = current_code_item_->insns_;
712311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  const uint16_t* code_end =
713311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      current_code_item_->insns_ + current_code_item_->insns_size_in_code_units_;
714311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
715311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  // TODO: need to rework expansion of block list & try_block_addr when inlining activated.
716b48819db07f9a0992a72173380c24249d7fc648abuzbee  // TUNING: use better estimate of basic blocks for following resize.
717e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  block_list_.reserve(block_list_.size() + current_code_item_->insns_size_in_code_units_);
71872f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu  // FindBlock lookup cache.
71972f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu  ScopedArenaAllocator allocator(&cu_->arena_stack);
72072f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu  ScopedArenaVector<uint16_t> dex_pc_to_block_map(allocator.Adapter());
72122c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle  dex_pc_to_block_map.resize(current_code_item_->insns_size_in_code_units_ +
72222c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle                             1 /* Fall-through on last insn; dead or punt to interpreter. */);
723bd663de599b16229085759366c56e2ed5a1dc7ecbuzbee
724311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  // TODO: replace with explicit resize routine.  Using automatic extension side effect for now.
725862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  try_block_addr_->SetBit(current_code_item_->insns_size_in_code_units_);
726862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  try_block_addr_->ClearBit(current_code_item_->insns_size_in_code_units_);
727311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
728311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  // If this is the first method, set up default entry and exit blocks.
729311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (current_method_ == 0) {
7302cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    DCHECK(entry_block_ == nullptr);
7312cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    DCHECK(exit_block_ == nullptr);
732ffda4993af78484feb7a4ce5497c1796463c0ba1Vladimir Marko    DCHECK_EQ(GetNumBlocks(), 0U);
7330d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    // Use id 0 to represent a null block.
734e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    BasicBlock* null_block = CreateNewBB(kNullBlock);
7350d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    DCHECK_EQ(null_block->id, NullBasicBlockId);
7360d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    null_block->hidden = true;
737e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    entry_block_ = CreateNewBB(kEntryBlock);
738e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    exit_block_ = CreateNewBB(kExitBlock);
739311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  } else {
740311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    UNIMPLEMENTED(FATAL) << "Nested inlining not implemented.";
741311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    /*
742311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee     * Will need to manage storage for ins & outs, push prevous state and update
743311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee     * insert point.
744311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee     */
745311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
746311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
747311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /* Current block to record parsed instructions */
748e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  BasicBlock* cur_block = CreateNewBB(kDalvikByteCode);
7490d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  DCHECK_EQ(current_offset_, 0U);
750311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  cur_block->start_offset = current_offset_;
7510d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  // TODO: for inlining support, insert at the insert point rather than entry block.
7520d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  entry_block_->fall_through = cur_block->id;
753e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  cur_block->predecessors.push_back(entry_block_->id);
754311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
7553d73ba2ce682edfaf41f29521bd6039c6499a1c5Vladimir Marko  /* Identify code range in try blocks and set up the empty catch blocks */
75672f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu  ProcessTryCatchBlocks(&dex_pc_to_block_map);
757311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
7583d73ba2ce682edfaf41f29521bd6039c6499a1c5Vladimir Marko  uint64_t merged_df_flags = 0u;
7593d73ba2ce682edfaf41f29521bd6039c6499a1c5Vladimir Marko
760311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  /* Parse all instructions and put them into containing basic blocks */
761311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  while (code_ptr < code_end) {
7623aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    MIR *insn = NewMIR();
763311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    insn->offset = current_offset_;
764311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    insn->m_unit_index = current_method_;
765311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    int width = ParseInsn(code_ptr, &insn->dalvikInsn);
766311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    Instruction::Code opcode = insn->dalvikInsn.opcode;
7672cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    if (opcode_count_ != nullptr) {
768311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      opcode_count_[static_cast<int>(opcode)]++;
769311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
770311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
771fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    int flags = insn->dalvikInsn.FlagsOf();
772b1f1d642093418612c0a27ce4203b421bb6eb767buzbee    int verify_flags = Instruction::VerifyFlagsOf(insn->dalvikInsn.opcode);
773311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
774cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler    uint64_t df_flags = GetDataFlowAttributes(insn);
7753d73ba2ce682edfaf41f29521bd6039c6499a1c5Vladimir Marko    merged_df_flags |= df_flags;
776311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
777311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (df_flags & DF_HAS_DEFS) {
778311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      def_count_ += (df_flags & DF_A_WIDE) ? 2 : 1;
779311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
780311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
7811da1e2fceb0030b4b76b43510b1710a9613e0c2ebuzbee    if (df_flags & DF_LVN) {
7821da1e2fceb0030b4b76b43510b1710a9613e0c2ebuzbee      cur_block->use_lvn = true;  // Run local value numbering on this basic block.
7831da1e2fceb0030b4b76b43510b1710a9613e0c2ebuzbee    }
7841da1e2fceb0030b4b76b43510b1710a9613e0c2ebuzbee
7858512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Check for inline data block signatures.
7862724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee    if (opcode == Instruction::NOP) {
7872724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee      // A simple NOP will have a width of 1 at this point, embedded data NOP > 1.
7882724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee      if ((width == 1) && ((current_offset_ & 0x1) == 0x1) && ((code_end - code_ptr) > 1)) {
7892724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee        // Could be an aligning nop.  If an embedded data NOP follows, treat pair as single unit.
7902724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee        uint16_t following_raw_instruction = code_ptr[1];
7912724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee        if ((following_raw_instruction == Instruction::kSparseSwitchSignature) ||
7922724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee            (following_raw_instruction == Instruction::kPackedSwitchSignature) ||
7932724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee            (following_raw_instruction == Instruction::kArrayDataSignature)) {
7942724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee          width += Instruction::At(code_ptr + 1)->SizeInCodeUnits();
7952724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee        }
7962724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee      }
7972724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee      if (width == 1) {
7982724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee        // It is a simple nop - treat normally.
799cdacac4a8196bdc620185079ec9e886329606f3dJean Christophe Beyler        cur_block->AppendMIR(insn);
8002724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee      } else {
8010d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee        DCHECK(cur_block->fall_through == NullBasicBlockId);
8020d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee        DCHECK(cur_block->taken == NullBasicBlockId);
8036489d22a44ea7d135c142ee94925570d0333d5e7buzbee        // Unreachable instruction, mark for no continuation and end basic block.
8042724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee        flags &= ~Instruction::kContinue;
80572f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu        FindBlock(current_offset_ + width, /* create */ true,
80672f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                  /* immed_pred_block_p */ nullptr, &dex_pc_to_block_map);
8072724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee      }
8082724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee    } else {
809cdacac4a8196bdc620185079ec9e886329606f3dJean Christophe Beyler      cur_block->AppendMIR(insn);
8102724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee    }
8112724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee
812b48819db07f9a0992a72173380c24249d7fc648abuzbee    // Associate the starting dex_pc for this opcode with its containing basic block.
81372f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu    dex_pc_to_block_map[insn->offset] = cur_block->id;
814b48819db07f9a0992a72173380c24249d7fc648abuzbee
8152724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee    code_ptr += width;
8162724776ad521eebb1c7f0e4be56d6e6ab4764f86buzbee
817311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (flags & Instruction::kBranch) {
818311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      cur_block = ProcessCanBranch(cur_block, insn, current_offset_,
81972f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                   width, flags, code_ptr, code_end, &dex_pc_to_block_map);
820311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    } else if (flags & Instruction::kReturn) {
821311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      cur_block->terminated_by_return = true;
8220d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee      cur_block->fall_through = exit_block_->id;
823e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      exit_block_->predecessors.push_back(cur_block->id);
824311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      /*
825311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       * Terminate the current block if there are instructions
826311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       * afterwards.
827311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       */
828311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      if (code_ptr < code_end) {
829311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        /*
830311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee         * Create a fallthrough block for real instructions
831311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee         * (incl. NOP).
832311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee         */
83372f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu         FindBlock(current_offset_ + width, /* create */ true,
83472f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                   /* immed_pred_block_p */ nullptr, &dex_pc_to_block_map);
835311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      }
836311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    } else if (flags & Instruction::kThrow) {
837311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      cur_block = ProcessCanThrow(cur_block, insn, current_offset_, width, flags, try_block_addr_,
83872f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                  code_ptr, code_end, &dex_pc_to_block_map);
839311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    } else if (flags & Instruction::kSwitch) {
84072f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu      cur_block = ProcessCanSwitch(cur_block, insn, current_offset_, width,
84172f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                   flags, &dex_pc_to_block_map);
842311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
843688e7c5c9f36573dd4da2edd889470d930b0054bAlexei Zavjalov    if (verify_flags & Instruction::kVerifyVarArgRange ||
844688e7c5c9f36573dd4da2edd889470d930b0054bAlexei Zavjalov        verify_flags & Instruction::kVerifyVarArgRangeNonZero) {
845b1f1d642093418612c0a27ce4203b421bb6eb767buzbee      /*
846b1f1d642093418612c0a27ce4203b421bb6eb767buzbee       * The Quick backend's runtime model includes a gap between a method's
847b1f1d642093418612c0a27ce4203b421bb6eb767buzbee       * argument ("in") vregs and the rest of its vregs.  Handling a range instruction
848b1f1d642093418612c0a27ce4203b421bb6eb767buzbee       * which spans the gap is somewhat complicated, and should not happen
849b1f1d642093418612c0a27ce4203b421bb6eb767buzbee       * in normal usage of dx.  Punt to the interpreter.
850b1f1d642093418612c0a27ce4203b421bb6eb767buzbee       */
851b1f1d642093418612c0a27ce4203b421bb6eb767buzbee      int first_reg_in_range = insn->dalvikInsn.vC;
852b1f1d642093418612c0a27ce4203b421bb6eb767buzbee      int last_reg_in_range = first_reg_in_range + insn->dalvikInsn.vA - 1;
853b1f1d642093418612c0a27ce4203b421bb6eb767buzbee      if (IsInVReg(first_reg_in_range) != IsInVReg(last_reg_in_range)) {
854b1f1d642093418612c0a27ce4203b421bb6eb767buzbee        punt_to_interpreter_ = true;
855b1f1d642093418612c0a27ce4203b421bb6eb767buzbee      }
856b1f1d642093418612c0a27ce4203b421bb6eb767buzbee    }
857311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    current_offset_ += width;
8586a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    BasicBlock* next_block = FindBlock(current_offset_, /* create */ false,
85972f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                       /* immed_pred_block_p */ nullptr,
86072f53af0307b9109a1cfc0671675ce5d45c66d3aChao-ying Fu                                       &dex_pc_to_block_map);
861311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (next_block) {
862311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      /*
863311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       * The next instruction could be the target of a previously parsed
864311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       * forward branch so a block is already created. If the current
865311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       * instruction is not an unconditional branch, connect them through
866311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       * the fall-through link.
867311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee       */
8680d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee      DCHECK(cur_block->fall_through == NullBasicBlockId ||
8690d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee             GetBasicBlock(cur_block->fall_through) == next_block ||
8700d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee             GetBasicBlock(cur_block->fall_through) == exit_block_);
871311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
8720d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee      if ((cur_block->fall_through == NullBasicBlockId) && (flags & Instruction::kContinue)) {
8730d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee        cur_block->fall_through = next_block->id;
874e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko        next_block->predecessors.push_back(cur_block->id);
875311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      }
876311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      cur_block = next_block;
877311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
878311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
8793d73ba2ce682edfaf41f29521bd6039c6499a1c5Vladimir Marko  merged_df_flags_ = merged_df_flags;
8805816ed48bc339c983b40dc493e96b97821ce7966Vladimir Marko
881311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
882311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    DumpCFG("/sdcard/1_post_parse_cfg/", true);
883311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
884311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
885311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  if (cu_->verbose) {
8861fd3346740dfb7f47be9922312b68a4227fada96buzbee    DumpMIRGraph();
887311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
88822c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle
88922c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle  // Check if there's been a fall-through out of the method code.
89022c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle  BasicBlockId out_bb_id = dex_pc_to_block_map[current_code_item_->insns_size_in_code_units_];
89122c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle  if (UNLIKELY(out_bb_id != NullBasicBlockId)) {
89222c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle    // Eagerly calculate DFS order to determine if the block is dead.
89322c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle    DCHECK(!DfsOrdersUpToDate());
89422c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle    ComputeDFSOrders();
89522c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle    BasicBlock* out_bb = GetBasicBlock(out_bb_id);
89622c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle    DCHECK(out_bb != nullptr);
89722c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle    if (out_bb->block_type != kDead) {
89822c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle      LOG(WARNING) << "Live fall-through out of method in " << PrettyMethod(method_idx, dex_file);
89922c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle      SetPuntToInterpreter(true);
90022c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle    }
90122c2d74f4c641feaf22a520d2a0538b31a82239dCalin Juravle  }
902311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
903311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
9042ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MIRGraph::ShowOpcodeStats() {
9052cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  DCHECK(opcode_count_ != nullptr);
906311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  LOG(INFO) << "Opcode Count";
907311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  for (int i = 0; i < kNumPackedOpcodes; i++) {
908311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (opcode_count_[i] != 0) {
909311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      LOG(INFO) << "-C- " << Instruction::Name(static_cast<Instruction::Code>(i))
910311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                << " " << opcode_count_[i];
911311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
912311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
913311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
914311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
915cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyleruint64_t MIRGraph::GetDataFlowAttributes(Instruction::Code opcode) {
916cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler  DCHECK_LT((size_t) opcode, (sizeof(oat_data_flow_attributes_) / sizeof(oat_data_flow_attributes_[0])));
917cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler  return oat_data_flow_attributes_[opcode];
918cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler}
919cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler
920cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyleruint64_t MIRGraph::GetDataFlowAttributes(MIR* mir) {
921cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler  DCHECK(mir != nullptr);
922cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler  Instruction::Code opcode = mir->dalvikInsn.opcode;
923cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler  return GetDataFlowAttributes(opcode);
924cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler}
925cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler
926cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe// The path can easily surpass FS limits because of parameters etc. Use pathconf to get FS
927cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe// restrictions here. Note that a successful invocation will return an actual value. If the path
928cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe// is too long for some reason, the return will be ENAMETOOLONG. Then cut off part of the name.
929cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe//
930cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe// It's possible the path is not valid, or some other errors appear. In that case return false.
931cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampestatic bool CreateDumpFile(std::string& fname, const char* dir_prefix, NarrowDexOffset start_offset,
932cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe                           const char *suffix, int nr, std::string* output) {
933cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe  std::string dir = StringPrintf("./%s", dir_prefix);
934cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe  int64_t max_name_length = pathconf(dir.c_str(), _PC_NAME_MAX);
935cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe  if (max_name_length <= 0) {
936cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe    PLOG(ERROR) << "Could not get file name restrictions for " << dir;
937cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe    return false;
938cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe  }
939cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe
940cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe  std::string name = StringPrintf("%s%x%s_%d.dot", fname.c_str(), start_offset,
941cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe                                  suffix == nullptr ? "" : suffix, nr);
942cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe  std::string fpath;
943cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe  if (static_cast<int64_t>(name.size()) > max_name_length) {
944cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe    std::string suffix_str = StringPrintf("_%d.dot", nr);
945cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe    name = name.substr(0, static_cast<size_t>(max_name_length) - suffix_str.size()) + suffix_str;
946cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe  }
947cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe  // Sanity check.
948cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe  DCHECK_LE(name.size(), static_cast<size_t>(max_name_length));
949cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe
950cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe  *output = StringPrintf("%s%s", dir_prefix, name.c_str());
951cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe  return true;
952cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe}
953cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe
954311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee// TODO: use a configurable base prefix, and adjust callers to supply pass name.
955311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee/* Dump the CFG into a DOT graph */
956d0a515562772d7c637160e8779c4f253ee169c3aJean Christophe Beylervoid MIRGraph::DumpCFG(const char* dir_prefix, bool all_blocks, const char *suffix) {
957311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  FILE* file;
958a8869e60d93ba9eed36a5b53553b7609f58fc05bJean Christophe Beyler  static AtomicInteger cnt(0);
959a8869e60d93ba9eed36a5b53553b7609f58fc05bJean Christophe Beyler
960a8869e60d93ba9eed36a5b53553b7609f58fc05bJean Christophe Beyler  // Increment counter to get a unique file number.
961a8869e60d93ba9eed36a5b53553b7609f58fc05bJean Christophe Beyler  cnt++;
962cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe  int nr = cnt.LoadRelaxed();
963a8869e60d93ba9eed36a5b53553b7609f58fc05bJean Christophe Beyler
964311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  std::string fname(PrettyMethod(cu_->method_idx, *cu_->dex_file));
965311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  ReplaceSpecialChars(fname);
966cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe  std::string fpath;
967cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe  if (!CreateDumpFile(fname, dir_prefix, GetBasicBlock(GetEntryBlock()->fall_through)->start_offset,
968cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe                      suffix, nr, &fpath)) {
969cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe    LOG(ERROR) << "Could not create dump file name for " << fname;
970cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe    return;
971cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe  }
972cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe  file = fopen(fpath.c_str(), "w");
9732cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (file == nullptr) {
974cee97e51ed45401c274cd67bfa6216624a995f6fAndreas Gampe    PLOG(ERROR) << "Could not open " << fpath << " for DumpCFG.";
975311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    return;
976311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
977311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  fprintf(file, "digraph G {\n");
978311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
979311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  fprintf(file, "  rankdir=TB\n");
980311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
981311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  int num_blocks = all_blocks ? GetNumBlocks() : num_reachable_blocks_;
982311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  int idx;
983311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
984311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  for (idx = 0; idx < num_blocks; idx++) {
985e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    int block_idx = all_blocks ? idx : dfs_order_[idx];
9868512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    BasicBlock* bb = GetBasicBlock(block_idx);
9872cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    if (bb == nullptr) continue;
988311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (bb->block_type == kDead) continue;
989a8869e60d93ba9eed36a5b53553b7609f58fc05bJean Christophe Beyler    if (bb->hidden) continue;
990311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (bb->block_type == kEntryBlock) {
991311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  entry_%d [shape=Mdiamond];\n", bb->id);
992311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    } else if (bb->block_type == kExitBlock) {
993311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  exit_%d [shape=Mdiamond];\n", bb->id);
994311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    } else if (bb->block_type == kDalvikByteCode) {
995311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  block%04x_%d [shape=record,label = \"{ \\\n",
996311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee              bb->start_offset, bb->id);
9978512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      const MIR* mir;
998311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        fprintf(file, "    {block id %d\\l}%s\\\n", bb->id,
999311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                bb->first_mir_insn ? " | " : " ");
1000311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        for (mir = bb->first_mir_insn; mir; mir = mir->next) {
1001311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee            int opcode = mir->dalvikInsn.opcode;
1002e0951144d71a4791a5319ec507d84fce373018e0Razvan A Lupusoru            fprintf(file, "    {%04x %s %s %s %s %s %s %s %s %s\\l}%s\\\n", mir->offset,
1003d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell                      mir->ssa_rep ? GetDalvikDisassembly(mir) :
10042ab40eb3c23559205ac7b9b039bd749458e8a761Jean Christophe Beyler                      !MIR::DecodedInstruction::IsPseudoMirOp(opcode) ?
10052ab40eb3c23559205ac7b9b039bd749458e8a761Jean Christophe Beyler                        Instruction::Name(mir->dalvikInsn.opcode) :
1006d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell                        extended_mir_op_names_[opcode - kMirOpFirst],
1007d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell                      (mir->optimization_flags & MIR_IGNORE_RANGE_CHECK) != 0 ? " no_rangecheck" : " ",
1008d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell                      (mir->optimization_flags & MIR_IGNORE_NULL_CHECK) != 0 ? " no_nullcheck" : " ",
100960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji                      (mir->optimization_flags & MIR_IGNORE_SUSPEND_CHECK) != 0 ? " no_suspendcheck" : " ",
1010b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler                      (mir->optimization_flags & MIR_STORE_NON_TEMPORAL) != 0 ? " non_temporal" : " ",
10111500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru                      (mir->optimization_flags & MIR_CALLEE) != 0 ? " inlined" : " ",
101266c6d7bdfdd535e6ecf4461bba3804f1a7794fcdVladimir Marko                      (mir->optimization_flags & MIR_CLASS_IS_INITIALIZED) != 0 ? " cl_inited" : " ",
101366c6d7bdfdd535e6ecf4461bba3804f1a7794fcdVladimir Marko                      (mir->optimization_flags & MIR_CLASS_IS_IN_DEX_CACHE) != 0 ? " cl_in_cache" : " ",
1014e0951144d71a4791a5319ec507d84fce373018e0Razvan A Lupusoru                      (mir->optimization_flags & MIR_IGNORE_DIV_ZERO_CHECK) != 0 ? " no_div_check" : " ",
1015d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell                      mir->next ? " | " : " ");
1016311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        }
1017311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        fprintf(file, "  }\"];\n\n");
1018311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    } else if (bb->block_type == kExceptionHandling) {
1019311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      char block_name[BLOCK_NAME_LEN];
1020311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
1021311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      GetBlockName(bb, block_name);
1022311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  %s [shape=invhouse];\n", block_name);
1023311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
1024311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
1025311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    char block_name1[BLOCK_NAME_LEN], block_name2[BLOCK_NAME_LEN];
1026311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
10270d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    if (bb->taken != NullBasicBlockId) {
1028311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      GetBlockName(bb, block_name1);
10290d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee      GetBlockName(GetBasicBlock(bb->taken), block_name2);
1030311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  %s:s -> %s:n [style=dotted]\n",
1031311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee              block_name1, block_name2);
1032311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
10330d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    if (bb->fall_through != NullBasicBlockId) {
1034311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      GetBlockName(bb, block_name1);
10350d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee      GetBlockName(GetBasicBlock(bb->fall_through), block_name2);
1036311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  %s:s -> %s:n\n", block_name1, block_name2);
1037311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
1038311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
10390d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    if (bb->successor_block_list_type != kNotUsed) {
1040311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  succ%04x_%d [shape=%s,label = \"{ \\\n",
1041311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee              bb->start_offset, bb->id,
10420d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee              (bb->successor_block_list_type == kCatch) ?  "Mrecord" : "record");
1043311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
1044e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      int last_succ_id = static_cast<int>(bb->successor_blocks.size() - 1u);
1045311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      int succ_id = 0;
1046e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      for (SuccessorBlockInfo* successor_block_info : bb->successor_blocks) {
10478512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler        BasicBlock* dest_block = GetBasicBlock(successor_block_info->block);
1048311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        fprintf(file, "    {<f%d> %04x: %04x\\l}%s\\\n",
1049e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko                succ_id,
1050311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                successor_block_info->key,
1051311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee                dest_block->start_offset,
1052e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko                (succ_id != last_succ_id) ? " | " : " ");
1053e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko        ++succ_id;
1054311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      }
1055311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  }\"];\n\n");
1056311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
1057311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      GetBlockName(bb, block_name1);
1058311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  %s:s -> succ%04x_%d:n [style=dashed]\n",
1059311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee              block_name1, bb->start_offset, bb->id);
1060311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
106125bc279080a56546b0f8a33342a853b2778eed0dRazvan A Lupusoru      // Link the successor pseudo-block with all of its potential targets.
106225bc279080a56546b0f8a33342a853b2778eed0dRazvan A Lupusoru      succ_id = 0;
1063e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      for (SuccessorBlockInfo* successor_block_info : bb->successor_blocks) {
106425bc279080a56546b0f8a33342a853b2778eed0dRazvan A Lupusoru        BasicBlock* dest_block = GetBasicBlock(successor_block_info->block);
1065311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
106625bc279080a56546b0f8a33342a853b2778eed0dRazvan A Lupusoru        GetBlockName(dest_block, block_name2);
106725bc279080a56546b0f8a33342a853b2778eed0dRazvan A Lupusoru        fprintf(file, "  succ%04x_%d:f%d:e -> %s:n\n", bb->start_offset,
106825bc279080a56546b0f8a33342a853b2778eed0dRazvan A Lupusoru                bb->id, succ_id++, block_name2);
1069311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      }
1070311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
1071311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    fprintf(file, "\n");
1072311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
1073311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    if (cu_->verbose) {
1074311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      /* Display the dominator tree */
1075311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      GetBlockName(bb, block_name1);
1076311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      fprintf(file, "  cfg%s [label=\"%s\", shape=none];\n",
1077311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee              block_name1, block_name1);
1078311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      if (bb->i_dom) {
10790d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee        GetBlockName(GetBasicBlock(bb->i_dom), block_name2);
1080311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee        fprintf(file, "  cfg%s:s -> cfg%s:n\n\n", block_name2, block_name1);
1081311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee      }
1082311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    }
1083311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  }
1084311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  fprintf(file, "}\n");
1085311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee  fclose(file);
1086311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee}
1087311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee
10883aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler/* Insert an MIR instruction to the end of a basic block. */
1089cdacac4a8196bdc620185079ec9e886329606f3dJean Christophe Beylervoid BasicBlock::AppendMIR(MIR* mir) {
10908512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Insert it after the last MIR.
10918512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  InsertMIRListAfter(last_mir_insn, mir, mir);
10928512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
10938512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
10948512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::AppendMIRList(MIR* first_list_mir, MIR* last_list_mir) {
10958512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Insert it after the last MIR.
10968512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  InsertMIRListAfter(last_mir_insn, first_list_mir, last_list_mir);
10978512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
10988512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
10998512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::AppendMIRList(const std::vector<MIR*>& insns) {
11008512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  for (std::vector<MIR*>::const_iterator it = insns.begin(); it != insns.end(); it++) {
11018512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    MIR* new_mir = *it;
11028512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
11038512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Add a copy of each MIR.
11048512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    InsertMIRListAfter(last_mir_insn, new_mir, new_mir);
11058512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
11068512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
11078512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
11088512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler/* Insert a MIR instruction after the specified MIR. */
11098512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::InsertMIRAfter(MIR* current_mir, MIR* new_mir) {
11108512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  InsertMIRListAfter(current_mir, new_mir, new_mir);
11118512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
11128512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
11138512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::InsertMIRListAfter(MIR* insert_after, MIR* first_list_mir, MIR* last_list_mir) {
11148512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // If no MIR, we are done.
11158512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (first_list_mir == nullptr || last_list_mir == nullptr) {
11168512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    return;
11178512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
11188512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
11198512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // If insert_after is null, assume BB is empty.
11208512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (insert_after == nullptr) {
11218512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    first_mir_insn = first_list_mir;
11228512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    last_mir_insn = last_list_mir;
11238512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    last_list_mir->next = nullptr;
11241fd3346740dfb7f47be9922312b68a4227fada96buzbee  } else {
11258512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    MIR* after_list = insert_after->next;
11268512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    insert_after->next = first_list_mir;
11278512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    last_list_mir->next = after_list;
11288512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    if (after_list == nullptr) {
11298512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      last_mir_insn = last_list_mir;
11308512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    }
11311fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
11323aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
11338512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Set this BB to be the basic block of the MIRs.
11348512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  MIR* last = last_list_mir->next;
11358512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  for (MIR* mir = first_list_mir; mir != last; mir = mir->next) {
11368512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    mir->bb = id;
11378512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
11381fd3346740dfb7f47be9922312b68a4227fada96buzbee}
11391fd3346740dfb7f47be9922312b68a4227fada96buzbee
11403aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler/* Insert an MIR instruction to the head of a basic block. */
1141cdacac4a8196bdc620185079ec9e886329606f3dJean Christophe Beylervoid BasicBlock::PrependMIR(MIR* mir) {
11428512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  InsertMIRListBefore(first_mir_insn, mir, mir);
11438512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
11443aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
11458512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::PrependMIRList(MIR* first_list_mir, MIR* last_list_mir) {
11468512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Insert it before the first MIR.
11478512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  InsertMIRListBefore(first_mir_insn, first_list_mir, last_list_mir);
11481fd3346740dfb7f47be9922312b68a4227fada96buzbee}
11491fd3346740dfb7f47be9922312b68a4227fada96buzbee
11508512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::PrependMIRList(const std::vector<MIR*>& to_add) {
11518512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  for (std::vector<MIR*>::const_iterator it = to_add.begin(); it != to_add.end(); it++) {
11528512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    MIR* mir = *it;
11531fd3346740dfb7f47be9922312b68a4227fada96buzbee
11548512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    InsertMIRListBefore(first_mir_insn, mir, mir);
11551fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
11568512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
11573aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
11588512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler/* Insert a MIR instruction before the specified MIR. */
11598512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::InsertMIRBefore(MIR* current_mir, MIR* new_mir) {
11608512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Insert as a single element list.
11618512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  return InsertMIRListBefore(current_mir, new_mir, new_mir);
11623aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler}
11633aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
11643aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe BeylerMIR* BasicBlock::FindPreviousMIR(MIR* mir) {
11653aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  MIR* current = first_mir_insn;
11663aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
11673aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  while (current != nullptr) {
11683aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    MIR* next = current->next;
11693aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
11703aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    if (next == mir) {
11713aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler      return current;
11723aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    }
11733aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
11743aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    current = next;
11753aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  }
11763aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
11773aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  return nullptr;
11783aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler}
11793aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
11808512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::InsertMIRListBefore(MIR* insert_before, MIR* first_list_mir, MIR* last_list_mir) {
11818512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // If no MIR, we are done.
11828512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (first_list_mir == nullptr || last_list_mir == nullptr) {
11838512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    return;
11848512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
11858512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
11868512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // If insert_before is null, assume BB is empty.
11878512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (insert_before == nullptr) {
11888512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    first_mir_insn = first_list_mir;
11898512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    last_mir_insn = last_list_mir;
11908512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    last_list_mir->next = nullptr;
11918512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  } else {
11928512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    if (first_mir_insn == insert_before) {
11938512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      last_list_mir->next = first_mir_insn;
11948512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      first_mir_insn = first_list_mir;
11958512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    } else {
11968512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      // Find the preceding MIR.
11978512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      MIR* before_list = FindPreviousMIR(insert_before);
11988512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      DCHECK(before_list != nullptr);
11998512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      before_list->next = first_list_mir;
12008512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      last_list_mir->next = insert_before;
12018512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    }
12028512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
12038512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
12048512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Set this BB to be the basic block of the MIRs.
12058512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  for (MIR* mir = first_list_mir; mir != last_list_mir->next; mir = mir->next) {
12068512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    mir->bb = id;
12073aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  }
12088512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
12098512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
12108512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylerbool BasicBlock::RemoveMIR(MIR* mir) {
12118512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Remove as a single element list.
12128512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  return RemoveMIRList(mir, mir);
12138512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
12148512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
12158512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylerbool BasicBlock::RemoveMIRList(MIR* first_list_mir, MIR* last_list_mir) {
12168512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (first_list_mir == nullptr) {
12178512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    return false;
12188512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
12198512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
12208512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Try to find the MIR.
12218512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  MIR* before_list = nullptr;
12228512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  MIR* after_list = nullptr;
12233aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
12248512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // If we are removing from the beginning of the MIR list.
12258512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (first_mir_insn == first_list_mir) {
12268512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    before_list = nullptr;
12278512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  } else {
12288512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    before_list = FindPreviousMIR(first_list_mir);
12298512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    if (before_list == nullptr) {
12308512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      // We did not find the mir.
12318512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      return false;
12328512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    }
12338512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
12348512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
1235a4307aca310aac0ac62dcb5435daa02b1f950558Jean Christophe Beyler  // Remove the BB information and also find the after_list.
1236590c6a4ded1deb378baa253c86070d8eeffdc820Chao-ying Fu  for (MIR* mir = first_list_mir; mir != last_list_mir->next; mir = mir->next) {
12378512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    mir->bb = NullBasicBlockId;
12388512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
12398512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
12408512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  after_list = last_list_mir->next;
12418512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
1242a4307aca310aac0ac62dcb5435daa02b1f950558Jean Christophe Beyler  // If there is nothing before the list, after_list is the first_mir.
12438512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (before_list == nullptr) {
12448512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    first_mir_insn = after_list;
1245a4307aca310aac0ac62dcb5435daa02b1f950558Jean Christophe Beyler  } else {
1246a4307aca310aac0ac62dcb5435daa02b1f950558Jean Christophe Beyler    before_list->next = after_list;
12478512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
12483aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
1249a4307aca310aac0ac62dcb5435daa02b1f950558Jean Christophe Beyler  // If there is nothing after the list, before_list is last_mir.
12508512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (after_list == nullptr) {
12518512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    last_mir_insn = before_list;
12523aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  }
12538512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
12548512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  return true;
12551fd3346740dfb7f47be9922312b68a4227fada96buzbee}
12561fd3346740dfb7f47be9922312b68a4227fada96buzbee
125726e7d454b9924f3673b075b05e4c604ad658a062Vladimir MarkoMIR* BasicBlock::GetFirstNonPhiInsn() {
125826e7d454b9924f3673b075b05e4c604ad658a062Vladimir Marko  MIR* mir = first_mir_insn;
125926e7d454b9924f3673b075b05e4c604ad658a062Vladimir Marko  while (mir != nullptr && static_cast<int>(mir->dalvikInsn.opcode) == kMirOpPhi) {
126026e7d454b9924f3673b075b05e4c604ad658a062Vladimir Marko    mir = mir->next;
126126e7d454b9924f3673b075b05e4c604ad658a062Vladimir Marko  }
126226e7d454b9924f3673b075b05e4c604ad658a062Vladimir Marko  return mir;
126326e7d454b9924f3673b075b05e4c604ad658a062Vladimir Marko}
126426e7d454b9924f3673b075b05e4c604ad658a062Vladimir Marko
1265cdacac4a8196bdc620185079ec9e886329606f3dJean Christophe BeylerMIR* BasicBlock::GetNextUnconditionalMir(MIRGraph* mir_graph, MIR* current) {
12663bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru  MIR* next_mir = nullptr;
12673bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru
12683bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru  if (current != nullptr) {
12693bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru    next_mir = current->next;
12703bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru  }
12713bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru
12723bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru  if (next_mir == nullptr) {
12733bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru    // Only look for next MIR that follows unconditionally.
1274cdacac4a8196bdc620185079ec9e886329606f3dJean Christophe Beyler    if ((taken == NullBasicBlockId) && (fall_through != NullBasicBlockId)) {
1275cdacac4a8196bdc620185079ec9e886329606f3dJean Christophe Beyler      next_mir = mir_graph->GetBasicBlock(fall_through)->first_mir_insn;
12763bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru    }
12773bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru  }
12783bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru
12793bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru  return next_mir;
12803bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru}
12813bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru
12821500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusorustatic void FillTypeSizeString(uint32_t type_size, std::string* decoded_mir) {
12831500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  DCHECK(decoded_mir != nullptr);
12841500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  OpSize type = static_cast<OpSize>(type_size >> 16);
12851500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  uint16_t vect_size = (type_size & 0xFFFF);
12861500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru
12871500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  // Now print the type and vector size.
12881500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  std::stringstream ss;
12891500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  ss << " (type:";
12901500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  ss << type;
12911500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  ss << " vectsize:";
12921500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  ss << vect_size;
12931500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  ss << ")";
12941500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru
12951500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  decoded_mir->append(ss.str());
12961500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru}
12971500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru
12981500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoruvoid MIRGraph::DisassembleExtendedInstr(const MIR* mir, std::string* decoded_mir) {
12991500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  DCHECK(decoded_mir != nullptr);
13001500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  int opcode = mir->dalvikInsn.opcode;
13011500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  SSARepresentation* ssa_rep = mir->ssa_rep;
13021500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  int defs = (ssa_rep != nullptr) ? ssa_rep->num_defs : 0;
13031500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  int uses = (ssa_rep != nullptr) ? ssa_rep->num_uses : 0;
13041500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru
1305f41b92c7a2fcdd411b9edd7070e4729ea18e0ba6Vladimir  if (opcode < kMirOpFirst) {
1306f41b92c7a2fcdd411b9edd7070e4729ea18e0ba6Vladimir    return;  // It is not an extended instruction.
1307f41b92c7a2fcdd411b9edd7070e4729ea18e0ba6Vladimir  }
1308f41b92c7a2fcdd411b9edd7070e4729ea18e0ba6Vladimir
13091500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  decoded_mir->append(extended_mir_op_names_[opcode - kMirOpFirst]);
13101500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru
13111500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  switch (opcode) {
13121500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPhi: {
13131500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      if (defs > 0 && uses > 0) {
13141500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        BasicBlockId* incoming = mir->meta.phi_incoming;
13151500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(StringPrintf(" %s = (%s",
13161500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru                           GetSSANameWithConst(ssa_rep->defs[0], true).c_str(),
13171500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru                           GetSSANameWithConst(ssa_rep->uses[0], true).c_str()));
13181500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(StringPrintf(":%d", incoming[0]));
13191500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        for (int i = 1; i < uses; i++) {
13201500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(StringPrintf(", %s:%d", GetSSANameWithConst(ssa_rep->uses[i], true).c_str(), incoming[i]));
13211500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        }
13221500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(")");
13231500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      }
13241500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13251500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    }
13261500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpCopy:
13271500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      if (ssa_rep != nullptr) {
13281500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(" ");
13291500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[0], false));
13301500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        if (defs > 1) {
13311500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(", ");
13321500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[1], false));
13331500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        }
13341500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(" = ");
13351500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[0], false));
13361500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        if (uses > 1) {
13371500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(", ");
13381500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[1], false));
13391500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        }
13401500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      } else {
13411500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(StringPrintf(" v%d = v%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13421500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      }
13431500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13441500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpFusedCmplFloat:
13451500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpFusedCmpgFloat:
13461500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpFusedCmplDouble:
13471500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpFusedCmpgDouble:
13481500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpFusedCmpLong:
13491500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      if (ssa_rep != nullptr) {
13501500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(" ");
13511500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[0], false));
13521500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        for (int i = 1; i < uses; i++) {
13531500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(", ");
13541500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[i], false));
13551500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        }
13561500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      } else {
13571500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(StringPrintf(" v%d, v%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13581500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      }
13591500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13601500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpMoveVector:
13611500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13621500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
13631500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13641500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedAddition:
13651500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d + vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13661500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
13671500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13681500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedMultiply:
13691500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d * vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13701500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
13711500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13721500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedSubtract:
13731500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d - vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13741500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
13751500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13761500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedAnd:
13771500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d & vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13781500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
13791500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13801500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedOr:
13811500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d \\| vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13821500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
13831500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13841500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedXor:
13851500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d ^ vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13861500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
13871500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13881500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedShiftLeft:
13891500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d \\<\\< %d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13901500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
13911500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13921500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedUnsignedShiftRight:
13931500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d \\>\\>\\> %d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13941500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
13951500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
13961500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedSignedShiftRight:
13971500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = vect%d \\>\\> %d", mir->dalvikInsn.vA, mir->dalvikInsn.vA, mir->dalvikInsn.vB));
13981500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
13991500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
14001500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpConstVector:
14011500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d = %x, %x, %x, %x", mir->dalvikInsn.vA, mir->dalvikInsn.arg[0],
14021500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru                                      mir->dalvikInsn.arg[1], mir->dalvikInsn.arg[2], mir->dalvikInsn.arg[3]));
14031500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
14041500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedSet:
14051500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      if (ssa_rep != nullptr) {
14061500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(StringPrintf(" vect%d = %s", mir->dalvikInsn.vA,
14071500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru              GetSSANameWithConst(ssa_rep->uses[0], false).c_str()));
14081500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        if (uses > 1) {
14091500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(", ");
14101500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[1], false));
14111500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        }
14121500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      } else {
14131500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(StringPrintf(" vect%d = v%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB));
14141500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      }
14151500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
14161500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
14171500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedAddReduce:
14181500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      if (ssa_rep != nullptr) {
14191500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(" ");
14201500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[0], false));
14211500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        if (defs > 1) {
14221500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(", ");
14231500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[1], false));
14241500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        }
14251500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(StringPrintf(" = vect%d + %s", mir->dalvikInsn.vB,
14261500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru            GetSSANameWithConst(ssa_rep->uses[0], false).c_str()));
14271500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        if (uses > 1) {
14281500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(", ");
14291500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[1], false));
14301500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        }
14311500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      } else {
14321500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(StringPrintf("v%d = vect%d + v%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB, mir->dalvikInsn.vA));
14331500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      }
14341500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
14351500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
14361500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpPackedReduce:
14371500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      if (ssa_rep != nullptr) {
14381500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(" ");
14391500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[0], false));
14401500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        if (defs > 1) {
14411500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(", ");
14421500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[1], false));
14431500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        }
1444b72c723bfb21e05cb9b0a7999db805df93fcaee8Razvan A Lupusoru        decoded_mir->append(StringPrintf(" = vect%d (extr_idx:%d)", mir->dalvikInsn.vB, mir->dalvikInsn.arg[0]));
14451500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      } else {
1446b72c723bfb21e05cb9b0a7999db805df93fcaee8Razvan A Lupusoru        decoded_mir->append(StringPrintf(" v%d = vect%d (extr_idx:%d)", mir->dalvikInsn.vA,
1447b72c723bfb21e05cb9b0a7999db805df93fcaee8Razvan A Lupusoru                                         mir->dalvikInsn.vB, mir->dalvikInsn.arg[0]));
14481500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      }
14491500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      FillTypeSizeString(mir->dalvikInsn.vC, decoded_mir);
14501500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
14511500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpReserveVectorRegisters:
14521500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpReturnVectorRegisters:
14531500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(StringPrintf(" vect%d - vect%d", mir->dalvikInsn.vA, mir->dalvikInsn.vB));
14541500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
14551500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    case kMirOpMemBarrier: {
14561500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(" type:");
14571500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      std::stringstream ss;
14581500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      ss << static_cast<MemBarrierKind>(mir->dalvikInsn.vA);
14591500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      decoded_mir->append(ss.str());
14601500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
14611500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    }
1462b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A    case kMirOpPackedArrayGet:
1463b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A    case kMirOpPackedArrayPut:
1464b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A      decoded_mir->append(StringPrintf(" vect%d", mir->dalvikInsn.vA));
1465b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A      if (ssa_rep != nullptr) {
1466b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A        decoded_mir->append(StringPrintf(", %s[%s]",
1467b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A                                        GetSSANameWithConst(ssa_rep->uses[0], false).c_str(),
1468b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A                                        GetSSANameWithConst(ssa_rep->uses[1], false).c_str()));
1469b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A      } else {
1470b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A        decoded_mir->append(StringPrintf(", v%d[v%d]", mir->dalvikInsn.vB, mir->dalvikInsn.vC));
1471b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A      }
1472b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A      FillTypeSizeString(mir->dalvikInsn.arg[0], decoded_mir);
1473b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A      break;
1474a262f7707330dccfb50af6345813083182b61043Ningsheng Jian    case kMirOpMaddInt:
1475a262f7707330dccfb50af6345813083182b61043Ningsheng Jian    case kMirOpMsubInt:
1476a262f7707330dccfb50af6345813083182b61043Ningsheng Jian    case kMirOpMaddLong:
1477a262f7707330dccfb50af6345813083182b61043Ningsheng Jian    case kMirOpMsubLong:
1478a262f7707330dccfb50af6345813083182b61043Ningsheng Jian      if (ssa_rep != nullptr) {
1479a262f7707330dccfb50af6345813083182b61043Ningsheng Jian        decoded_mir->append(" ");
1480a262f7707330dccfb50af6345813083182b61043Ningsheng Jian        decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[0], false));
1481a262f7707330dccfb50af6345813083182b61043Ningsheng Jian        if (defs > 1) {
1482a262f7707330dccfb50af6345813083182b61043Ningsheng Jian          decoded_mir->append(", ");
1483a262f7707330dccfb50af6345813083182b61043Ningsheng Jian          decoded_mir->append(GetSSANameWithConst(ssa_rep->defs[1], false));
1484a262f7707330dccfb50af6345813083182b61043Ningsheng Jian        }
1485a262f7707330dccfb50af6345813083182b61043Ningsheng Jian        for (int i = 0; i < uses; i++) {
1486a262f7707330dccfb50af6345813083182b61043Ningsheng Jian          decoded_mir->append(", ");
1487a262f7707330dccfb50af6345813083182b61043Ningsheng Jian          decoded_mir->append(GetSSANameWithConst(ssa_rep->uses[i], false));
1488a262f7707330dccfb50af6345813083182b61043Ningsheng Jian        }
1489a262f7707330dccfb50af6345813083182b61043Ningsheng Jian      } else {
1490a262f7707330dccfb50af6345813083182b61043Ningsheng Jian        decoded_mir->append(StringPrintf(" v%d, v%d, v%d, v%d",
1491a262f7707330dccfb50af6345813083182b61043Ningsheng Jian                                         mir->dalvikInsn.vA, mir->dalvikInsn.vB,
1492a262f7707330dccfb50af6345813083182b61043Ningsheng Jian                                         mir->dalvikInsn.vC, mir->dalvikInsn.arg[0]));
1493a262f7707330dccfb50af6345813083182b61043Ningsheng Jian      }
1494a262f7707330dccfb50af6345813083182b61043Ningsheng Jian      break;
14951500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    default:
14961500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      break;
14971500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  }
14981500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru}
14991500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru
15002ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromchar* MIRGraph::GetDalvikDisassembly(const MIR* mir) {
150129a2648821ea4d0b5d3aecb9f835822fdfe6faa1Ian Rogers  MIR::DecodedInstruction insn = mir->dalvikInsn;
15021fd3346740dfb7f47be9922312b68a4227fada96buzbee  std::string str;
15031fd3346740dfb7f47be9922312b68a4227fada96buzbee  int flags = 0;
15041fd3346740dfb7f47be9922312b68a4227fada96buzbee  int opcode = insn.opcode;
15051fd3346740dfb7f47be9922312b68a4227fada96buzbee  char* ret;
15061fd3346740dfb7f47be9922312b68a4227fada96buzbee  bool nop = false;
15071fd3346740dfb7f47be9922312b68a4227fada96buzbee  SSARepresentation* ssa_rep = mir->ssa_rep;
15088512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  Instruction::Format dalvik_format = Instruction::k10x;  // Default to no-operand format.
15091fd3346740dfb7f47be9922312b68a4227fada96buzbee
15101500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  // Handle special cases that recover the original dalvik instruction.
1511f80552b7e5f627a5dd07af017b7d65dec010ca48Vladimir Marko  if (opcode == kMirOpCheck) {
15121fd3346740dfb7f47be9922312b68a4227fada96buzbee    str.append(extended_mir_op_names_[opcode - kMirOpFirst]);
15131fd3346740dfb7f47be9922312b68a4227fada96buzbee    str.append(": ");
15148512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Recover the original Dex instruction.
15151fd3346740dfb7f47be9922312b68a4227fada96buzbee    insn = mir->meta.throw_insn->dalvikInsn;
15161fd3346740dfb7f47be9922312b68a4227fada96buzbee    ssa_rep = mir->meta.throw_insn->ssa_rep;
15171fd3346740dfb7f47be9922312b68a4227fada96buzbee    opcode = insn.opcode;
15181fd3346740dfb7f47be9922312b68a4227fada96buzbee  } else if (opcode == kMirOpNop) {
15191fd3346740dfb7f47be9922312b68a4227fada96buzbee    str.append("[");
1520750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru    if (mir->offset < current_code_item_->insns_size_in_code_units_) {
1521750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru      // Recover original opcode.
1522750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru      insn.opcode = Instruction::At(current_code_item_->insns_ + mir->offset)->Opcode();
1523750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru      opcode = insn.opcode;
1524750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru    }
15251fd3346740dfb7f47be9922312b68a4227fada96buzbee    nop = true;
15261fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
15272cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  int defs = (ssa_rep != nullptr) ? ssa_rep->num_defs : 0;
15282cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  int uses = (ssa_rep != nullptr) ? ssa_rep->num_uses : 0;
15291fd3346740dfb7f47be9922312b68a4227fada96buzbee
15302ab40eb3c23559205ac7b9b039bd749458e8a761Jean Christophe Beyler  if (MIR::DecodedInstruction::IsPseudoMirOp(opcode)) {
15311500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    // Note that this does not check the MIR's opcode in all cases. In cases where it
15321500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    // recovered dalvik instruction, it uses opcode of that instead of the extended one.
15331500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    DisassembleExtendedInstr(mir, &str);
15341fd3346740dfb7f47be9922312b68a4227fada96buzbee  } else {
15351fd3346740dfb7f47be9922312b68a4227fada96buzbee    dalvik_format = Instruction::FormatOf(insn.opcode);
1536fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    flags = insn.FlagsOf();
15371fd3346740dfb7f47be9922312b68a4227fada96buzbee    str.append(Instruction::Name(insn.opcode));
15381fd3346740dfb7f47be9922312b68a4227fada96buzbee
15398512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // For invokes-style formats, treat wide regs as a pair of singles.
15401fd3346740dfb7f47be9922312b68a4227fada96buzbee    bool show_singles = ((dalvik_format == Instruction::k35c) ||
15411fd3346740dfb7f47be9922312b68a4227fada96buzbee                         (dalvik_format == Instruction::k3rc));
15421fd3346740dfb7f47be9922312b68a4227fada96buzbee    if (defs != 0) {
15431500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      str.append(" ");
15441500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      str.append(GetSSANameWithConst(ssa_rep->defs[0], false));
15451500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      if (defs > 1) {
15461500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        str.append(", ");
15471500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        str.append(GetSSANameWithConst(ssa_rep->defs[1], false));
15481500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      }
15491fd3346740dfb7f47be9922312b68a4227fada96buzbee      if (uses != 0) {
15501fd3346740dfb7f47be9922312b68a4227fada96buzbee        str.append(", ");
15511fd3346740dfb7f47be9922312b68a4227fada96buzbee      }
15521fd3346740dfb7f47be9922312b68a4227fada96buzbee    }
15531fd3346740dfb7f47be9922312b68a4227fada96buzbee    for (int i = 0; i < uses; i++) {
15541500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      str.append(" ");
15551500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      str.append(GetSSANameWithConst(ssa_rep->uses[i], show_singles));
15562cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      if (!show_singles && (reg_location_ != nullptr) && reg_location_[i].wide) {
15571fd3346740dfb7f47be9922312b68a4227fada96buzbee        // For the listing, skip the high sreg.
15581fd3346740dfb7f47be9922312b68a4227fada96buzbee        i++;
15591fd3346740dfb7f47be9922312b68a4227fada96buzbee      }
15601500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      if (i != (uses - 1)) {
15611fd3346740dfb7f47be9922312b68a4227fada96buzbee        str.append(",");
15621fd3346740dfb7f47be9922312b68a4227fada96buzbee      }
15631fd3346740dfb7f47be9922312b68a4227fada96buzbee    }
15641500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru
15651fd3346740dfb7f47be9922312b68a4227fada96buzbee    switch (dalvik_format) {
15668512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      case Instruction::k11n:  // Add one immediate from vB.
15671fd3346740dfb7f47be9922312b68a4227fada96buzbee      case Instruction::k21s:
15681fd3346740dfb7f47be9922312b68a4227fada96buzbee      case Instruction::k31i:
15691fd3346740dfb7f47be9922312b68a4227fada96buzbee      case Instruction::k21h:
15701500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        str.append(StringPrintf(", #0x%x", insn.vB));
15711fd3346740dfb7f47be9922312b68a4227fada96buzbee        break;
15728512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      case Instruction::k51l:  // Add one wide immediate.
157323b03b5b5fdaa517eda3b8b358752672cf6046b1Ian Rogers        str.append(StringPrintf(", #%" PRId64, insn.vB_wide));
15741fd3346740dfb7f47be9922312b68a4227fada96buzbee        break;
15758512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      case Instruction::k21c:  // One register, one string/type/method index.
15761fd3346740dfb7f47be9922312b68a4227fada96buzbee      case Instruction::k31c:
15771500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        str.append(StringPrintf(", index #0x%x", insn.vB));
15781fd3346740dfb7f47be9922312b68a4227fada96buzbee        break;
15798512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      case Instruction::k22c:  // Two registers, one string/type/method index.
15801500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        str.append(StringPrintf(", index #0x%x", insn.vC));
15811fd3346740dfb7f47be9922312b68a4227fada96buzbee        break;
15828512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      case Instruction::k22s:  // Add one immediate from vC.
15831fd3346740dfb7f47be9922312b68a4227fada96buzbee      case Instruction::k22b:
15841500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        str.append(StringPrintf(", #0x%x", insn.vC));
15851fd3346740dfb7f47be9922312b68a4227fada96buzbee        break;
15861500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      default:
15878512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler        // Nothing left to print.
15881500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru        break;
158902c8cc6d1312a2b55533f02f6369dc7c94672f90Brian Carlstrom    }
15901500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru
15910f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov    if ((flags & Instruction::kBranch) != 0) {
15920f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov      // For branches, decode the instructions to print out the branch targets.
15930f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov      int offset = 0;
15940f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov      switch (dalvik_format) {
15950f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov        case Instruction::k21t:
15960f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov          offset = insn.vB;
15970f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov          break;
15980f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov        case Instruction::k22t:
15990f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov          offset = insn.vC;
16000f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov          break;
16010f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov        case Instruction::k10t:
16020f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov        case Instruction::k20t:
16030f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov        case Instruction::k30t:
16040f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov          offset = insn.vA;
16050f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov          break;
16060f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov        default:
16070f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov          LOG(FATAL) << "Unexpected branch format " << dalvik_format << " from " << insn.opcode;
16081500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru          break;
16090f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov      }
16101500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      str.append(StringPrintf(", 0x%x (%c%x)", mir->offset + offset,
16110f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov                              offset > 0 ? '+' : '-', offset > 0 ? offset : -offset));
16120f3e4989b055bfa0bad3e4fad2f4d1a8b5a09901Serguei Katkov    }
16131500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru
16141500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    if (nop) {
16151500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      str.append("]--optimized away");
16161500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    }
16171fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
16181fd3346740dfb7f47be9922312b68a4227fada96buzbee  int length = str.length() + 1;
1619e4fcc5ba2284c201c022b52d27f7a1201d696324Vladimir Marko  ret = arena_->AllocArray<char>(length, kArenaAllocDFInfo);
16201fd3346740dfb7f47be9922312b68a4227fada96buzbee  strncpy(ret, str.c_str(), length);
16211fd3346740dfb7f47be9922312b68a4227fada96buzbee  return ret;
16221fd3346740dfb7f47be9922312b68a4227fada96buzbee}
16231fd3346740dfb7f47be9922312b68a4227fada96buzbee
16241fd3346740dfb7f47be9922312b68a4227fada96buzbee/* Turn method name into a legal Linux file name */
16252ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MIRGraph::ReplaceSpecialChars(std::string& str) {
16269b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  static const struct { const char before; const char after; } match[] = {
16279b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom    {'/', '-'}, {';', '#'}, {' ', '#'}, {'$', '+'},
16289b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom    {'(', '@'}, {')', '@'}, {'<', '='}, {'>', '='}
16299b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  };
16301fd3346740dfb7f47be9922312b68a4227fada96buzbee  for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) {
16311fd3346740dfb7f47be9922312b68a4227fada96buzbee    std::replace(str.begin(), str.end(), match[i].before, match[i].after);
16321fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
16331fd3346740dfb7f47be9922312b68a4227fada96buzbee}
16341fd3346740dfb7f47be9922312b68a4227fada96buzbee
16352ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromstd::string MIRGraph::GetSSAName(int ssa_reg) {
1636c7399c82c27f85a2df2653e1eb8c0b60f2cfd934Andreas Gampe  // TODO: This value is needed for debugging. Currently, we compute this and then copy to the
1637c7399c82c27f85a2df2653e1eb8c0b60f2cfd934Andreas Gampe  //       arena. We should be smarter and just place straight into the arena, or compute the
163839ebcb800aabedd0ffa6aa4aeac8aa4194c66e61Ian Rogers  //       value more lazily.
16391500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  int vreg = SRegToVReg(ssa_reg);
16401500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  if (vreg >= static_cast<int>(GetFirstTempVR())) {
16411500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    return StringPrintf("t%d_%d", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg));
16421500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  } else {
16431500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    return StringPrintf("v%d_%d", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg));
16441500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru  }
16451fd3346740dfb7f47be9922312b68a4227fada96buzbee}
16461fd3346740dfb7f47be9922312b68a4227fada96buzbee
16471fd3346740dfb7f47be9922312b68a4227fada96buzbee// Similar to GetSSAName, but if ssa name represents an immediate show that as well.
16482ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromstd::string MIRGraph::GetSSANameWithConst(int ssa_reg, bool singles_only) {
16492cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (reg_location_ == nullptr) {
16508512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Pre-SSA - just use the standard name.
16511fd3346740dfb7f47be9922312b68a4227fada96buzbee    return GetSSAName(ssa_reg);
16521fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
16531fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (IsConst(reg_location_[ssa_reg])) {
16549944b3b792103cb72df1953b5502ced9bf128305Mark Mendell    if (!singles_only && reg_location_[ssa_reg].wide &&
16559944b3b792103cb72df1953b5502ced9bf128305Mark Mendell        !reg_location_[ssa_reg].high_word) {
165623b03b5b5fdaa517eda3b8b358752672cf6046b1Ian Rogers      return StringPrintf("v%d_%d#0x%" PRIx64, SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg),
16571fd3346740dfb7f47be9922312b68a4227fada96buzbee                          ConstantValueWide(reg_location_[ssa_reg]));
16581fd3346740dfb7f47be9922312b68a4227fada96buzbee    } else {
1659b1eba213afaf7fa6445de863ddc9680ab99762eaBrian Carlstrom      return StringPrintf("v%d_%d#0x%x", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg),
16601fd3346740dfb7f47be9922312b68a4227fada96buzbee                          ConstantValue(reg_location_[ssa_reg]));
16611fd3346740dfb7f47be9922312b68a4227fada96buzbee    }
16621fd3346740dfb7f47be9922312b68a4227fada96buzbee  } else {
16631500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    int vreg = SRegToVReg(ssa_reg);
16641500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    if (vreg >= static_cast<int>(GetFirstTempVR())) {
16651500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      return StringPrintf("t%d_%d", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg));
16661500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    } else {
16671500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru      return StringPrintf("v%d_%d", SRegToVReg(ssa_reg), GetSSASubscript(ssa_reg));
16681500e6fe209223f920cfbe6857dc4e2f0e0fc9caRazvan A Lupusoru    }
16691fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
16701fd3346740dfb7f47be9922312b68a4227fada96buzbee}
16711fd3346740dfb7f47be9922312b68a4227fada96buzbee
16722ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MIRGraph::GetBlockName(BasicBlock* bb, char* name) {
16731fd3346740dfb7f47be9922312b68a4227fada96buzbee  switch (bb->block_type) {
16741fd3346740dfb7f47be9922312b68a4227fada96buzbee    case kEntryBlock:
16751fd3346740dfb7f47be9922312b68a4227fada96buzbee      snprintf(name, BLOCK_NAME_LEN, "entry_%d", bb->id);
16761fd3346740dfb7f47be9922312b68a4227fada96buzbee      break;
16771fd3346740dfb7f47be9922312b68a4227fada96buzbee    case kExitBlock:
16781fd3346740dfb7f47be9922312b68a4227fada96buzbee      snprintf(name, BLOCK_NAME_LEN, "exit_%d", bb->id);
16791fd3346740dfb7f47be9922312b68a4227fada96buzbee      break;
16801fd3346740dfb7f47be9922312b68a4227fada96buzbee    case kDalvikByteCode:
16811fd3346740dfb7f47be9922312b68a4227fada96buzbee      snprintf(name, BLOCK_NAME_LEN, "block%04x_%d", bb->start_offset, bb->id);
16821fd3346740dfb7f47be9922312b68a4227fada96buzbee      break;
16831fd3346740dfb7f47be9922312b68a4227fada96buzbee    case kExceptionHandling:
16841fd3346740dfb7f47be9922312b68a4227fada96buzbee      snprintf(name, BLOCK_NAME_LEN, "exception%04x_%d", bb->start_offset,
16851fd3346740dfb7f47be9922312b68a4227fada96buzbee               bb->id);
16861fd3346740dfb7f47be9922312b68a4227fada96buzbee      break;
16871fd3346740dfb7f47be9922312b68a4227fada96buzbee    default:
16881fd3346740dfb7f47be9922312b68a4227fada96buzbee      snprintf(name, BLOCK_NAME_LEN, "_%d", bb->id);
16891fd3346740dfb7f47be9922312b68a4227fada96buzbee      break;
16901fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
16911fd3346740dfb7f47be9922312b68a4227fada96buzbee}
16921fd3346740dfb7f47be9922312b68a4227fada96buzbee
1693717a3e447c6f7a922cf9c3efe522747a187a045dSerguei Katkovconst char* MIRGraph::GetShortyFromMethodReference(const MethodReference& target_method) {
1694717a3e447c6f7a922cf9c3efe522747a187a045dSerguei Katkov  const DexFile::MethodId& method_id =
1695717a3e447c6f7a922cf9c3efe522747a187a045dSerguei Katkov      target_method.dex_file->GetMethodId(target_method.dex_method_index);
1696717a3e447c6f7a922cf9c3efe522747a187a045dSerguei Katkov  return target_method.dex_file->GetShorty(method_id.proto_idx_);
1697717a3e447c6f7a922cf9c3efe522747a187a045dSerguei Katkov}
1698717a3e447c6f7a922cf9c3efe522747a187a045dSerguei Katkov
16991fd3346740dfb7f47be9922312b68a4227fada96buzbee/* Debug Utility - dump a compilation unit */
17002ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid MIRGraph::DumpMIRGraph() {
17011fd3346740dfb7f47be9922312b68a4227fada96buzbee  const char* block_type_names[] = {
170217189ac098b2f156713db1821b49db7b2f018bbebuzbee    "Null Block",
17031fd3346740dfb7f47be9922312b68a4227fada96buzbee    "Entry Block",
17041fd3346740dfb7f47be9922312b68a4227fada96buzbee    "Code Block",
17051fd3346740dfb7f47be9922312b68a4227fada96buzbee    "Exit Block",
17061fd3346740dfb7f47be9922312b68a4227fada96buzbee    "Exception Handling",
17071fd3346740dfb7f47be9922312b68a4227fada96buzbee    "Catch Block"
17081fd3346740dfb7f47be9922312b68a4227fada96buzbee  };
17091fd3346740dfb7f47be9922312b68a4227fada96buzbee
17101fd3346740dfb7f47be9922312b68a4227fada96buzbee  LOG(INFO) << "Compiling " << PrettyMethod(cu_->method_idx, *cu_->dex_file);
17118d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru  LOG(INFO) << GetInsns(0) << " insns";
17121fd3346740dfb7f47be9922312b68a4227fada96buzbee  LOG(INFO) << GetNumBlocks() << " blocks in total";
17131fd3346740dfb7f47be9922312b68a4227fada96buzbee
1714e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  for (BasicBlock* bb : block_list_) {
17151fd3346740dfb7f47be9922312b68a4227fada96buzbee    LOG(INFO) << StringPrintf("Block %d (%s) (insn %04x - %04x%s)",
17161fd3346740dfb7f47be9922312b68a4227fada96buzbee        bb->id,
17171fd3346740dfb7f47be9922312b68a4227fada96buzbee        block_type_names[bb->block_type],
17181fd3346740dfb7f47be9922312b68a4227fada96buzbee        bb->start_offset,
17191fd3346740dfb7f47be9922312b68a4227fada96buzbee        bb->last_mir_insn ? bb->last_mir_insn->offset : bb->start_offset,
17201fd3346740dfb7f47be9922312b68a4227fada96buzbee        bb->last_mir_insn ? "" : " empty");
17210d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    if (bb->taken != NullBasicBlockId) {
17220d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee      LOG(INFO) << "  Taken branch: block " << bb->taken
17230d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee                << "(0x" << std::hex << GetBasicBlock(bb->taken)->start_offset << ")";
17241fd3346740dfb7f47be9922312b68a4227fada96buzbee    }
17250d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee    if (bb->fall_through != NullBasicBlockId) {
17260d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee      LOG(INFO) << "  Fallthrough : block " << bb->fall_through
17270d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee                << " (0x" << std::hex << GetBasicBlock(bb->fall_through)->start_offset << ")";
17281fd3346740dfb7f47be9922312b68a4227fada96buzbee    }
17291fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
17301fd3346740dfb7f47be9922312b68a4227fada96buzbee}
17311fd3346740dfb7f47be9922312b68a4227fada96buzbee
17321fd3346740dfb7f47be9922312b68a4227fada96buzbee/*
17331fd3346740dfb7f47be9922312b68a4227fada96buzbee * Build an array of location records for the incoming arguments.
17341fd3346740dfb7f47be9922312b68a4227fada96buzbee * Note: one location record per word of arguments, with dummy
17351fd3346740dfb7f47be9922312b68a4227fada96buzbee * high-word loc for wide arguments.  Also pull up any following
17361fd3346740dfb7f47be9922312b68a4227fada96buzbee * MOVE_RESULT and incorporate it into the invoke.
17371fd3346740dfb7f47be9922312b68a4227fada96buzbee */
1738e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu ChartierCallInfo* MIRGraph::NewMemCallInfo(BasicBlock* bb, MIR* mir, InvokeType type, bool is_range) {
1739f6c4b3ba3825de1dbb3e747a68b809c6cc8eb4dbMathieu Chartier  CallInfo* info = static_cast<CallInfo*>(arena_->Alloc(sizeof(CallInfo),
174083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko                                                        kArenaAllocMisc));
17411fd3346740dfb7f47be9922312b68a4227fada96buzbee  MIR* move_result_mir = FindMoveResult(bb, mir);
17422cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (move_result_mir == nullptr) {
17431fd3346740dfb7f47be9922312b68a4227fada96buzbee    info->result.location = kLocInvalid;
17441fd3346740dfb7f47be9922312b68a4227fada96buzbee  } else {
17451fd3346740dfb7f47be9922312b68a4227fada96buzbee    info->result = GetRawDest(move_result_mir);
17461fd3346740dfb7f47be9922312b68a4227fada96buzbee    move_result_mir->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
17471fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
17481fd3346740dfb7f47be9922312b68a4227fada96buzbee  info->num_arg_words = mir->ssa_rep->num_uses;
1749e4fcc5ba2284c201c022b52d27f7a1201d696324Vladimir Marko  info->args = (info->num_arg_words == 0) ? nullptr :
1750e4fcc5ba2284c201c022b52d27f7a1201d696324Vladimir Marko      arena_->AllocArray<RegLocation>(info->num_arg_words, kArenaAllocMisc);
17516ce3eba0f2e6e505ed408cdc40d213c8a512238dVladimir Marko  for (size_t i = 0; i < info->num_arg_words; i++) {
17521fd3346740dfb7f47be9922312b68a4227fada96buzbee    info->args[i] = GetRawSrc(mir, i);
17531fd3346740dfb7f47be9922312b68a4227fada96buzbee  }
17541fd3346740dfb7f47be9922312b68a4227fada96buzbee  info->opt_flags = mir->optimization_flags;
17551fd3346740dfb7f47be9922312b68a4227fada96buzbee  info->type = type;
17561fd3346740dfb7f47be9922312b68a4227fada96buzbee  info->is_range = is_range;
1757e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  if (IsInstructionQuickInvoke(mir->dalvikInsn.opcode)) {
1758e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier    const auto& method_info = GetMethodLoweringInfo(mir);
1759e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier    info->method_ref = method_info.GetTargetMethod();
1760e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  } else {
1761e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier    info->method_ref = MethodReference(GetCurrentDexCompilationUnit()->GetDexFile(),
1762e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier                                       mir->dalvikInsn.vB);
1763e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  }
17641fd3346740dfb7f47be9922312b68a4227fada96buzbee  info->index = mir->dalvikInsn.vB;
17651fd3346740dfb7f47be9922312b68a4227fada96buzbee  info->offset = mir->offset;
1766f096aad9203d7c50b2f9cbe1c1215a50c265a059Vladimir Marko  info->mir = mir;
17671fd3346740dfb7f47be9922312b68a4227fada96buzbee  return info;
17681fd3346740dfb7f47be9922312b68a4227fada96buzbee}
17691fd3346740dfb7f47be9922312b68a4227fada96buzbee
17703aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler// Allocate a new MIR.
17713aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe BeylerMIR* MIRGraph::NewMIR() {
17723aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  MIR* mir = new (arena_) MIR();
17733aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  return mir;
17743aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler}
17753aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
1776862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee// Allocate a new basic block.
17772ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromBasicBlock* MIRGraph::NewMemBB(BBType block_type, int block_id) {
1778e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  BasicBlock* bb = new (arena_) BasicBlock(block_id, block_type, arena_);
17798512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
1780862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  // TUNING: better estimate of the exit block predecessors?
1781e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  bb->predecessors.reserve((block_type == kExitBlock) ? 2048 : 2);
1782862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  block_id_map_.Put(block_id, block_id);
1783862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  return bb;
1784862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee}
17851fd3346740dfb7f47be9922312b68a4227fada96buzbee
17864e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beylervoid MIRGraph::InitializeConstantPropagation() {
17874e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler  is_constant_v_ = new (arena_) ArenaBitVector(arena_, GetNumSSARegs(), false);
1788e4fcc5ba2284c201c022b52d27f7a1201d696324Vladimir Marko  constant_values_ = arena_->AllocArray<int>(GetNumSSARegs(), kArenaAllocDFInfo);
17894e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler}
17904e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
17914e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beylervoid MIRGraph::InitializeMethodUses() {
17928512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // The gate starts by initializing the use counts.
17934e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler  int num_ssa_regs = GetNumSSARegs();
1794e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  use_counts_.clear();
1795e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  use_counts_.reserve(num_ssa_regs + 32);
1796e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  use_counts_.resize(num_ssa_regs, 0u);
1797e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  raw_use_counts_.clear();
1798e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  raw_use_counts_.reserve(num_ssa_regs + 32);
1799e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  raw_use_counts_.resize(num_ssa_regs, 0u);
18004e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler}
18014e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
1802a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Markovoid MIRGraph::SSATransformationStart() {
1803a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko  DCHECK(temp_scoped_alloc_.get() == nullptr);
1804a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko  temp_scoped_alloc_.reset(ScopedArenaAllocator::Create(&cu_->arena_stack));
1805f585e549682a98eec12f92033e9634dc162b7df8Vladimir Marko  temp_.ssa.num_vregs = GetNumOfCodeAndTempVRs();
1806f585e549682a98eec12f92033e9634dc162b7df8Vladimir Marko  temp_.ssa.work_live_vregs = new (temp_scoped_alloc_.get()) ArenaBitVector(
1807f585e549682a98eec12f92033e9634dc162b7df8Vladimir Marko      temp_scoped_alloc_.get(), temp_.ssa.num_vregs, false, kBitMapRegisterV);
18084e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler}
18094e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
1810a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Markovoid MIRGraph::SSATransformationEnd() {
1811a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko  // Verify the dataflow information after the pass.
1812a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko  if (cu_->enable_debug & (1 << kDebugVerifyDataflow)) {
1813a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko    VerifyDataflow();
1814a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko  }
1815a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko
1816f585e549682a98eec12f92033e9634dc162b7df8Vladimir Marko  temp_.ssa.num_vregs = 0u;
1817f585e549682a98eec12f92033e9634dc162b7df8Vladimir Marko  temp_.ssa.work_live_vregs = nullptr;
18186a8946ba3d170fee0ff06de42209be4b14e6aff3Vladimir Marko  DCHECK(temp_.ssa.def_block_matrix == nullptr);
18196a8946ba3d170fee0ff06de42209be4b14e6aff3Vladimir Marko  temp_.ssa.phi_node_blocks = nullptr;
1820a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko  DCHECK(temp_scoped_alloc_.get() != nullptr);
1821a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko  temp_scoped_alloc_.reset();
1822c029c98cc056bc247b69160f413ee7ce9a93d8c3Johnny Qiu
1823c029c98cc056bc247b69160f413ee7ce9a93d8c3Johnny Qiu  // Update the maximum number of reachable blocks.
1824c029c98cc056bc247b69160f413ee7ce9a93d8c3Johnny Qiu  max_num_reachable_blocks_ = num_reachable_blocks_;
1825ffda4993af78484feb7a4ce5497c1796463c0ba1Vladimir Marko
1826ffda4993af78484feb7a4ce5497c1796463c0ba1Vladimir Marko  // Mark MIR SSA representations as up to date.
1827ffda4993af78484feb7a4ce5497c1796463c0ba1Vladimir Marko  mir_ssa_rep_up_to_date_ = true;
1828a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko}
1829a5b8fde2d2bc3167078694fad417fddfe442a6fdVladimir Marko
1830750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusorusize_t MIRGraph::GetNumDalvikInsns() const {
1831750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  size_t cumulative_size = 0u;
1832750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  bool counted_current_item = false;
1833750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  const uint8_t size_for_null_code_item = 2u;
1834750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru
1835750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  for (auto it : m_units_) {
1836750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru    const DexFile::CodeItem* code_item = it->GetCodeItem();
1837750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru    // Even if the code item is null, we still count non-zero value so that
1838750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru    // each m_unit is counted as having impact.
1839750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru    cumulative_size += (code_item == nullptr ?
1840750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru        size_for_null_code_item : code_item->insns_size_in_code_units_);
1841750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru    if (code_item == current_code_item_) {
1842750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru      counted_current_item = true;
1843750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru    }
1844750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  }
1845750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru
1846750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  // If the current code item was not counted yet, count it now.
1847750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  // This can happen for example in unit tests where some fields like m_units_
1848750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  // are not initialized.
1849750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  if (counted_current_item == false) {
1850750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru    cumulative_size += (current_code_item_ == nullptr ?
1851750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru        size_for_null_code_item : current_code_item_->insns_size_in_code_units_);
1852750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  }
1853750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru
1854750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru  return cumulative_size;
1855750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru}
1856750359753444498d509a756fa9a042e9f3c432dfRazvan A Lupusoru
185755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Markostatic BasicBlock* SelectTopologicalSortOrderFallBack(
185855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    MIRGraph* mir_graph, const ArenaBitVector* current_loop,
185955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    const ScopedArenaVector<size_t>* visited_cnt_values, ScopedArenaAllocator* allocator,
186055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    ScopedArenaVector<BasicBlockId>* tmp_stack) {
186155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // No true loop head has been found but there may be true loop heads after the mess we need
186255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // to resolve. To avoid taking one of those, pick the candidate with the highest number of
186355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // reachable unvisited nodes. That candidate will surely be a part of a loop.
186455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  BasicBlock* fall_back = nullptr;
186555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  size_t fall_back_num_reachable = 0u;
186655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // Reuse the same bit vector for each candidate to mark reachable unvisited blocks.
186755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  ArenaBitVector candidate_reachable(allocator, mir_graph->GetNumBlocks(), false, kBitMapMisc);
186855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  AllNodesIterator iter(mir_graph);
186955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  for (BasicBlock* candidate = iter.Next(); candidate != nullptr; candidate = iter.Next()) {
187055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    if (candidate->hidden ||                            // Hidden, or
187155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        candidate->visited ||                           // already processed, or
187255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        (*visited_cnt_values)[candidate->id] == 0u ||   // no processed predecessors, or
187355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        (current_loop != nullptr &&                     // outside current loop.
187455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko         !current_loop->IsBitSet(candidate->id))) {
187555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      continue;
187655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    }
187755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    DCHECK(tmp_stack->empty());
187855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    tmp_stack->push_back(candidate->id);
187955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    candidate_reachable.ClearAllBits();
188055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    size_t num_reachable = 0u;
188155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    while (!tmp_stack->empty()) {
188255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      BasicBlockId current_id = tmp_stack->back();
188355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      tmp_stack->pop_back();
188455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      BasicBlock* current_bb = mir_graph->GetBasicBlock(current_id);
188555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      DCHECK(current_bb != nullptr);
188655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      ChildBlockIterator child_iter(current_bb, mir_graph);
188755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      BasicBlock* child_bb = child_iter.Next();
188855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      for ( ; child_bb != nullptr; child_bb = child_iter.Next()) {
188955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        DCHECK(!child_bb->hidden);
189055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        if (child_bb->visited ||                            // Already processed, or
189155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            (current_loop != nullptr &&                     // outside current loop.
189255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko             !current_loop->IsBitSet(child_bb->id))) {
189355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          continue;
189455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        }
189555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        if (!candidate_reachable.IsBitSet(child_bb->id)) {
189655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          candidate_reachable.SetBit(child_bb->id);
189755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          tmp_stack->push_back(child_bb->id);
189855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          num_reachable += 1u;
189955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        }
190055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      }
190155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    }
190255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    if (fall_back_num_reachable < num_reachable) {
190355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      fall_back_num_reachable = num_reachable;
190455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      fall_back = candidate;
190555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    }
190655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  }
190755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  return fall_back;
190855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko}
190944e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
191055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko// Compute from which unvisited blocks is bb_id reachable through unvisited blocks.
191155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Markostatic void ComputeUnvisitedReachableFrom(MIRGraph* mir_graph, BasicBlockId bb_id,
191255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko                                          ArenaBitVector* reachable,
191355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko                                          ScopedArenaVector<BasicBlockId>* tmp_stack) {
191455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // NOTE: Loop heads indicated by the "visited" flag.
191555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  DCHECK(tmp_stack->empty());
191655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  reachable->ClearAllBits();
191755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  tmp_stack->push_back(bb_id);
191855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  while (!tmp_stack->empty()) {
191955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    BasicBlockId current_id = tmp_stack->back();
192055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    tmp_stack->pop_back();
192155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    BasicBlock* current_bb = mir_graph->GetBasicBlock(current_id);
192255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    DCHECK(current_bb != nullptr);
1923e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    for (BasicBlockId pred_id : current_bb->predecessors) {
1924e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      BasicBlock* pred_bb = mir_graph->GetBasicBlock(pred_id);
1925e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      DCHECK(pred_bb != nullptr);
192655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      if (!pred_bb->visited && !reachable->IsBitSet(pred_bb->id)) {
192755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        reachable->SetBit(pred_bb->id);
192855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        tmp_stack->push_back(pred_bb->id);
192955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      }
193055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    }
193144e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler  }
193255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko}
193344e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
193455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Markovoid MIRGraph::ComputeTopologicalSortOrder() {
1935622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko  ScopedArenaAllocator allocator(&cu_->arena_stack);
193655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  unsigned int num_blocks = GetNumBlocks();
193755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko
1938622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko  ScopedArenaQueue<BasicBlock*> q(allocator.Adapter());
193955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  ScopedArenaVector<size_t> visited_cnt_values(num_blocks, 0u, allocator.Adapter());
194055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  ScopedArenaVector<BasicBlockId> loop_head_stack(allocator.Adapter());
194155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  size_t max_nested_loops = 0u;
194255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  ArenaBitVector loop_exit_blocks(&allocator, num_blocks, false, kBitMapMisc);
194355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  loop_exit_blocks.ClearAllBits();
1944622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko
194555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // Count the number of blocks to process and add the entry block(s).
194655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  unsigned int num_blocks_to_process = 0u;
1947e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  for (BasicBlock* bb : block_list_) {
194844e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler    if (bb->hidden == true) {
194944e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler      continue;
195044e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler    }
195144e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
195255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    num_blocks_to_process += 1u;
1953622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko
1954e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    if (bb->predecessors.size() == 0u) {
195555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      // Add entry block to the queue.
195644e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler      q.push(bb);
195744e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler    }
195844e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler  }
195944e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
1960e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  // Clear the topological order arrays.
1961e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  topological_order_.clear();
1962e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  topological_order_.reserve(num_blocks);
1963e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  topological_order_loop_ends_.clear();
1964e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  topological_order_loop_ends_.resize(num_blocks, 0u);
1965e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  topological_order_indexes_.clear();
1966e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  topological_order_indexes_.resize(num_blocks, static_cast<uint16_t>(-1));
196755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko
196855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // Mark all blocks as unvisited.
196955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  ClearAllVisitedFlags();
197055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko
197155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // For loop heads, keep track from which blocks they are reachable not going through other
197255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // loop heads. Other loop heads are excluded to detect the heads of nested loops. The children
197355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // in this set go into the loop body, the other children are jumping over the loop.
197455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  ScopedArenaVector<ArenaBitVector*> loop_head_reachable_from(allocator.Adapter());
197555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  loop_head_reachable_from.resize(num_blocks, nullptr);
197655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // Reuse the same temp stack whenever calculating a loop_head_reachable_from[loop_head_id].
197755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  ScopedArenaVector<BasicBlockId> tmp_stack(allocator.Adapter());
197855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko
197955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  while (num_blocks_to_process != 0u) {
1980622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    BasicBlock* bb = nullptr;
1981622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    if (!q.empty()) {
198255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      num_blocks_to_process -= 1u;
1983622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko      // Get top.
1984622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko      bb = q.front();
1985622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko      q.pop();
198655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      if (bb->visited) {
198755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        // Loop head: it was already processed, mark end and copy exit blocks to the queue.
198855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        DCHECK(q.empty()) << PrettyMethod(cu_->method_idx, *cu_->dex_file);
1989e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko        uint16_t idx = static_cast<uint16_t>(topological_order_.size());
1990e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko        topological_order_loop_ends_[topological_order_indexes_[bb->id]] = idx;
199155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        DCHECK_EQ(loop_head_stack.back(), bb->id);
199255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        loop_head_stack.pop_back();
199355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        ArenaBitVector* reachable =
199455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            loop_head_stack.empty() ? nullptr : loop_head_reachable_from[loop_head_stack.back()];
199555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        for (BasicBlockId candidate_id : loop_exit_blocks.Indexes()) {
199655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          if (reachable == nullptr || reachable->IsBitSet(candidate_id)) {
199755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            q.push(GetBasicBlock(candidate_id));
199855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            // NOTE: The BitVectorSet::IndexIterator will not check the pointed-to bit again,
199955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            // so clearing the bit has no effect on the iterator.
200055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            loop_exit_blocks.ClearBit(candidate_id);
200155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          }
200255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        }
200355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        continue;
200455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      }
2005622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    } else {
200655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      // Find the new loop head.
200755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      AllNodesIterator iter(this);
200855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      while (true) {
200955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        BasicBlock* candidate = iter.Next();
201055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        if (candidate == nullptr) {
201155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          // We did not find a true loop head, fall back to a reachable block in any loop.
201255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          ArenaBitVector* current_loop =
201355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko              loop_head_stack.empty() ? nullptr : loop_head_reachable_from[loop_head_stack.back()];
201455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          bb = SelectTopologicalSortOrderFallBack(this, current_loop, &visited_cnt_values,
201555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko                                                  &allocator, &tmp_stack);
201655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          DCHECK(bb != nullptr) << PrettyMethod(cu_->method_idx, *cu_->dex_file);
201755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          if (kIsDebugBuild && cu_->dex_file != nullptr) {
201855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            LOG(INFO) << "Topological sort order: Using fall-back in "
201955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko                << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " BB #" << bb->id
202055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko                << " @0x" << std::hex << bb->start_offset
202155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko                << ", num_blocks = " << std::dec << num_blocks;
202255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          }
202355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          break;
202455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        }
202555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        if (candidate->hidden ||                            // Hidden, or
202655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            candidate->visited ||                           // already processed, or
202755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            visited_cnt_values[candidate->id] == 0u ||      // no processed predecessors, or
202855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            (!loop_head_stack.empty() &&                    // outside current loop.
202955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko             !loop_head_reachable_from[loop_head_stack.back()]->IsBitSet(candidate->id))) {
2030622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko          continue;
2031622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko        }
203255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko
2033e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko        for (BasicBlockId pred_id : candidate->predecessors) {
2034e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko          BasicBlock* pred_bb = GetBasicBlock(pred_id);
2035e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko          DCHECK(pred_bb != nullptr);
203655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          if (pred_bb != candidate && !pred_bb->visited &&
203755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko              !pred_bb->dominators->IsBitSet(candidate->id)) {
2038e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko            candidate = nullptr;  // Set candidate to null to indicate failure.
2039e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko            break;
2040622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko          }
2041622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko        }
2042e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko        if (candidate != nullptr) {
204355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          bb = candidate;
204455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          break;
204555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        }
2046622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko      }
204755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      // Compute blocks from which the loop head is reachable and process those blocks first.
204855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      ArenaBitVector* reachable =
204955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          new (&allocator) ArenaBitVector(&allocator, num_blocks, false, kBitMapMisc);
205055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      loop_head_reachable_from[bb->id] = reachable;
205155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      ComputeUnvisitedReachableFrom(this, bb->id, reachable, &tmp_stack);
205255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      // Now mark as loop head. (Even if it's only a fall back when we don't find a true loop.)
205355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      loop_head_stack.push_back(bb->id);
205455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      max_nested_loops = std::max(max_nested_loops, loop_head_stack.size());
2055622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    }
205644e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
205744e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler    DCHECK_EQ(bb->hidden, false);
2058622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    DCHECK_EQ(bb->visited, false);
2059622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    bb->visited = true;
20608b858e16563ebf8e522df026a6ab409f1bd9b3deVladimir Marko    bb->nesting_depth = loop_head_stack.size();
206144e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
2062622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    // Now add the basic block.
2063e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    uint16_t idx = static_cast<uint16_t>(topological_order_.size());
2064e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    topological_order_indexes_[bb->id] = idx;
2065e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    topological_order_.push_back(bb->id);
206644e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
206755fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko    // Update visited_cnt_values for children.
2068622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    ChildBlockIterator succIter(bb, this);
2069622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    BasicBlock* successor = succIter.Next();
2070622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko    for ( ; successor != nullptr; successor = succIter.Next()) {
207155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      if (successor->hidden) {
2072622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko        continue;
2073622bdbe6c295b08d06dfaa8d896b9ca152aa899cVladimir Marko      }
207444e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
207555fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      // One more predecessor was visited.
207655fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko      visited_cnt_values[successor->id] += 1u;
2077e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      if (visited_cnt_values[successor->id] == successor->predecessors.size()) {
207855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        if (loop_head_stack.empty() ||
207955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko            loop_head_reachable_from[loop_head_stack.back()]->IsBitSet(successor->id)) {
208055fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          q.push(successor);
208155fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        } else {
208255fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          DCHECK(!loop_exit_blocks.IsBitSet(successor->id));
208355fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko          loop_exit_blocks.SetBit(successor->id);
208455fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko        }
208544e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler      }
208644e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler    }
208744e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler  }
208855fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko
208955fff044d3a4f7196098e25bab1dad106d9b54a2Vladimir Marko  // Prepare the loop head stack for iteration.
2090e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  topological_order_loop_head_stack_.clear();
2091e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  topological_order_loop_head_stack_.reserve(max_nested_loops);
2092415ac88a6471792a28cf2b457fe4ba9dc099396eVladimir Marko  max_nested_loops_ = max_nested_loops;
2093ffda4993af78484feb7a4ce5497c1796463c0ba1Vladimir Marko  topological_order_up_to_date_ = true;
209444e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler}
209544e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
209644e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beylerbool BasicBlock::IsExceptionBlock() const {
209744e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler  if (block_type == kExceptionHandling) {
209844e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler    return true;
209944e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler  }
210044e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler  return false;
210144e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler}
210244e5bdec17d0528b90cc0773be2beb76dcafdc5bJean Christophe Beyler
2103f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe BeylerChildBlockIterator::ChildBlockIterator(BasicBlock* bb, MIRGraph* mir_graph)
2104f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    : basic_block_(bb), mir_graph_(mir_graph), visited_fallthrough_(false),
2105f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler      visited_taken_(false), have_successors_(false) {
2106f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  // Check if we actually do have successors.
2107f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  if (basic_block_ != 0 && basic_block_->successor_block_list_type != kNotUsed) {
2108f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    have_successors_ = true;
2109e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    successor_iter_ = basic_block_->successor_blocks.cbegin();
2110f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  }
2111f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler}
2112f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler
2113f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe BeylerBasicBlock* ChildBlockIterator::Next() {
2114f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  // We check if we have a basic block. If we don't we cannot get next child.
2115f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  if (basic_block_ == nullptr) {
2116f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    return nullptr;
2117f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  }
2118f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler
2119f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  // If we haven't visited fallthrough, return that.
2120f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  if (visited_fallthrough_ == false) {
2121f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    visited_fallthrough_ = true;
2122f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler
2123f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    BasicBlock* result = mir_graph_->GetBasicBlock(basic_block_->fall_through);
2124f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    if (result != nullptr) {
2125f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler      return result;
2126f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    }
2127f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  }
2128f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler
2129f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  // If we haven't visited taken, return that.
2130f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  if (visited_taken_ == false) {
2131f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    visited_taken_ = true;
2132f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler
2133f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    BasicBlock* result = mir_graph_->GetBasicBlock(basic_block_->taken);
2134f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    if (result != nullptr) {
2135f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler      return result;
2136f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    }
2137f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  }
2138f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler
2139f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  // We visited both taken and fallthrough. Now check if we have successors we need to visit.
2140f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  if (have_successors_ == true) {
2141f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    // Get information about next successor block.
2142e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    auto end = basic_block_->successor_blocks.cend();
2143e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    while (successor_iter_ != end) {
2144e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      SuccessorBlockInfo* successor_block_info = *successor_iter_;
2145e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      ++successor_iter_;
2146989367a47b015dd85f850cf756b436fb044b5aeaNiranjan Kumar      // If block was replaced by zero block, take next one.
2147989367a47b015dd85f850cf756b436fb044b5aeaNiranjan Kumar      if (successor_block_info->block != NullBasicBlockId) {
2148989367a47b015dd85f850cf756b436fb044b5aeaNiranjan Kumar        return mir_graph_->GetBasicBlock(successor_block_info->block);
2149989367a47b015dd85f850cf756b436fb044b5aeaNiranjan Kumar      }
2150f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler    }
2151f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  }
2152f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler
2153f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  // We do not have anything.
2154f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler  return nullptr;
2155f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler}
2156f8c762b8cbd4a223c697d7e7bdb976fb39224cb8Jean Christophe Beyler
21578512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe BeylerBasicBlock* BasicBlock::Copy(CompilationUnit* c_unit) {
21588512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  MIRGraph* mir_graph = c_unit->mir_graph.get();
21598512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  return Copy(mir_graph);
21608512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
21613aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
21628512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe BeylerBasicBlock* BasicBlock::Copy(MIRGraph* mir_graph) {
21638512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  BasicBlock* result_bb = mir_graph->CreateNewBB(block_type);
21643aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
21658512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // We don't do a memcpy style copy here because it would lead to a lot of things
21668512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // to clean up. Let us do it by hand instead.
21678512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Copy in taken and fallthrough.
21688512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  result_bb->fall_through = fall_through;
21698512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  result_bb->taken = taken;
21703aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
21718512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Copy successor links if needed.
21728512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  ArenaAllocator* arena = mir_graph->GetArena();
21733aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
21748512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  result_bb->successor_block_list_type = successor_block_list_type;
21758512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (result_bb->successor_block_list_type != kNotUsed) {
2176e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    result_bb->successor_blocks.reserve(successor_blocks.size());
2177e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    for (SuccessorBlockInfo* sbi_old : successor_blocks) {
2178e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      SuccessorBlockInfo* sbi_new = static_cast<SuccessorBlockInfo*>(
2179e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko          arena->Alloc(sizeof(SuccessorBlockInfo), kArenaAllocSuccessor));
21808512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      memcpy(sbi_new, sbi_old, sizeof(SuccessorBlockInfo));
2181e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko      result_bb->successor_blocks.push_back(sbi_new);
21823aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    }
21838512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
21843aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
21858512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Copy offset, method.
21868512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  result_bb->start_offset = start_offset;
21873aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
21888512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Now copy instructions.
21898512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  for (MIR* mir = first_mir_insn; mir != 0; mir = mir->next) {
21908512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Get a copy first.
21918512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    MIR* copy = mir->Copy(mir_graph);
21923aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
21938512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Append it.
21948512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    result_bb->AppendMIR(copy);
21953aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  }
21963aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
21978512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  return result_bb;
21983aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler}
21993aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
22003aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe BeylerMIR* MIR::Copy(MIRGraph* mir_graph) {
22013aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  MIR* res = mir_graph->NewMIR();
22023aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  *res = *this;
22033aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
22043aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  // Remove links
22053aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  res->next = nullptr;
22063aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  res->bb = NullBasicBlockId;
22073aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  res->ssa_rep = nullptr;
22083aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
22093aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  return res;
22103aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler}
22113aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
22123aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe BeylerMIR* MIR::Copy(CompilationUnit* c_unit) {
22133aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  return Copy(c_unit->mir_graph.get());
22143aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler}
22153aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
22163aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyleruint32_t SSARepresentation::GetStartUseIndex(Instruction::Code opcode) {
22173aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  // Default result.
22183aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  int res = 0;
22193aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
22203aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  // We are basically setting the iputs to their igets counterparts.
22213aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  switch (opcode) {
22223aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT:
22233aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT_OBJECT:
22243aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT_BOOLEAN:
22253aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT_BYTE:
22263aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT_CHAR:
22273aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT_SHORT:
22283aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT_QUICK:
22293aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT_OBJECT_QUICK:
223037f05ef45e0393de812d51261dc293240c17294dFred Shih    case Instruction::IPUT_BOOLEAN_QUICK:
223137f05ef45e0393de812d51261dc293240c17294dFred Shih    case Instruction::IPUT_BYTE_QUICK:
223237f05ef45e0393de812d51261dc293240c17294dFred Shih    case Instruction::IPUT_CHAR_QUICK:
223337f05ef45e0393de812d51261dc293240c17294dFred Shih    case Instruction::IPUT_SHORT_QUICK:
22343aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::APUT:
22353aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::APUT_OBJECT:
22363aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::APUT_BOOLEAN:
22373aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::APUT_BYTE:
22383aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::APUT_CHAR:
22393aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::APUT_SHORT:
22403aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::SPUT:
22413aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::SPUT_OBJECT:
22423aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::SPUT_BOOLEAN:
22433aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::SPUT_BYTE:
22443aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::SPUT_CHAR:
22453aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::SPUT_SHORT:
22463aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler      // Skip the VR containing what to store.
22473aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler      res = 1;
22483aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler      break;
22493aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT_WIDE:
22503aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::IPUT_WIDE_QUICK:
22513aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::APUT_WIDE:
22523aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    case Instruction::SPUT_WIDE:
22533aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler      // Skip the two VRs containing what to store.
22543aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler      res = 2;
22553aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler      break;
22563aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler    default:
22573aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler      // Do nothing in the general case.
22583aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler      break;
22593aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  }
22603aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
22613aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler  return res;
22623aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler}
22633aa57730e2aec451bb836918d936c6862598d8d6Jean Christophe Beyler
2264c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler/**
2265c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler * @brief Given a decoded instruction, it checks whether the instruction
2266c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler * sets a constant and if it does, more information is provided about the
2267c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler * constant being set.
2268c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler * @param ptr_value pointer to a 64-bit holder for the constant.
2269c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler * @param wide Updated by function whether a wide constant is being set by bytecode.
2270c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler * @return Returns false if the decoded instruction does not represent a constant bytecode.
2271c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler */
2272c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beylerbool MIR::DecodedInstruction::GetConstant(int64_t* ptr_value, bool* wide) const {
2273c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler  bool sets_const = true;
2274c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler  int64_t value = vB;
2275c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler
2276c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler  DCHECK(ptr_value != nullptr);
2277c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler  DCHECK(wide != nullptr);
2278c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler
2279c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler  switch (opcode) {
2280c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    case Instruction::CONST_4:
2281c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    case Instruction::CONST_16:
2282c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    case Instruction::CONST:
2283c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      *wide = false;
2284c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      value <<= 32;      // In order to get the sign extend.
2285c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      value >>= 32;
2286c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      break;
2287c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    case Instruction::CONST_HIGH16:
2288c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      *wide = false;
2289c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      value <<= 48;      // In order to get the sign extend.
2290c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      value >>= 32;
2291c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      break;
2292c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    case Instruction::CONST_WIDE_16:
2293c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    case Instruction::CONST_WIDE_32:
2294c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      *wide = true;
2295c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      value <<= 32;      // In order to get the sign extend.
2296c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      value >>= 32;
2297c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      break;
2298c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    case Instruction::CONST_WIDE:
2299c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      *wide = true;
2300c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      value = vB_wide;
2301c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      break;
2302c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    case Instruction::CONST_WIDE_HIGH16:
2303c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      *wide = true;
2304c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      value <<= 48;      // In order to get the sign extend.
2305c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      break;
2306c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    default:
2307c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      sets_const = false;
2308c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler      break;
2309c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler  }
2310c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler
2311c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler  if (sets_const) {
2312c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler    *ptr_value = value;
2313c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler  }
2314c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler
2315c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler  return sets_const;
2316c3db20b7e6f847339d6ecbd89846c173a7ccc967Jean Christophe Beyler}
23178512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
23188512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylervoid BasicBlock::ResetOptimizationFlags(uint16_t reset_flags) {
23198512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Reset flags for all MIRs in bb.
23202cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  for (MIR* mir = first_mir_insn; mir != nullptr; mir = mir->next) {
23218512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    mir->optimization_flags &= (~reset_flags);
23228512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
23238512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
23248512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
2325cb873d8fd06b7dde4b69c5987b4eaf541d345a50Vladimir Markovoid BasicBlock::Kill(MIRGraph* mir_graph) {
2326e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  for (BasicBlockId pred_id : predecessors) {
2327e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    BasicBlock* pred_bb = mir_graph->GetBasicBlock(pred_id);
2328e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    DCHECK(pred_bb != nullptr);
23298512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
23308512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Sadly we have to go through the children by hand here.
23318512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    pred_bb->ReplaceChild(id, NullBasicBlockId);
23328512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
2333cb873d8fd06b7dde4b69c5987b4eaf541d345a50Vladimir Marko  predecessors.clear();
23348512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
2335312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  // Mark as dead and hidden.
2336312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  block_type = kDead;
2337312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  hidden = true;
2338312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko
2339312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  // Detach it from its MIRs so we don't generate code for them. Also detached MIRs
2340312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  // are updated to know that they no longer have a parent.
2341312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  for (MIR* mir = first_mir_insn; mir != nullptr; mir = mir->next) {
2342312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko    mir->bb = NullBasicBlockId;
2343312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  }
2344312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  first_mir_insn = nullptr;
2345312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  last_mir_insn = nullptr;
2346312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko
2347312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  data_flow_info = nullptr;
2348312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko
2349312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  // Erase this bb from all children's predecessors and kill unreachable children.
2350312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  ChildBlockIterator iter(this, mir_graph);
2351312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  for (BasicBlock* succ_bb = iter.Next(); succ_bb != nullptr; succ_bb = iter.Next()) {
2352312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko    succ_bb->ErasePredecessor(id);
2353312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  }
2354312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko
2355312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  // Remove links to children.
2356312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  fall_through = NullBasicBlockId;
2357312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  taken = NullBasicBlockId;
2358312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  successor_block_list_type = kNotUsed;
2359312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko
2360312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  if (kIsDebugBuild) {
2361312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko    if (catch_entry) {
2362312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko      DCHECK_EQ(mir_graph->catches_.count(start_offset), 1u);
2363312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko      mir_graph->catches_.erase(start_offset);
2364312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko    }
2365312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  }
2366312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko}
2367312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko
23688512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylerbool BasicBlock::IsSSALiveOut(const CompilationUnit* c_unit, int ssa_reg) {
23698512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // In order to determine if the ssa reg is live out, we scan all the MIRs. We remember
23708512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // the last SSA number of the same dalvik register. At the end, if it is different than ssa_reg,
23718512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // then it is not live out of this BB.
23728512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  int dalvik_reg = c_unit->mir_graph->SRegToVReg(ssa_reg);
23738512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
23748512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  int last_ssa_reg = -1;
23758512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
23768512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // Walk through the MIRs backwards.
23778512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  for (MIR* mir = first_mir_insn; mir != nullptr; mir = mir->next) {
23788512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Get ssa rep.
23798512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    SSARepresentation *ssa_rep = mir->ssa_rep;
23808512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
23818512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Go through the defines for this MIR.
23828512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    for (int i = 0; i < ssa_rep->num_defs; i++) {
23838512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      DCHECK(ssa_rep->defs != nullptr);
23848512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
23858512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      // Get the ssa reg.
23868512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      int def_ssa_reg = ssa_rep->defs[i];
23878512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
23888512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      // Get dalvik reg.
23898512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      int def_dalvik_reg = c_unit->mir_graph->SRegToVReg(def_ssa_reg);
23908512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
23918512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      // Compare dalvik regs.
23928512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      if (dalvik_reg == def_dalvik_reg) {
23938512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler        // We found a def of the register that we are being asked about.
23948512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler        // Remember it.
23958512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler        last_ssa_reg = def_ssa_reg;
23968512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      }
23978512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    }
23988512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
23998512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
24008512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (last_ssa_reg == -1) {
24018512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // If we get to this point we couldn't find a define of register user asked about.
24028512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // Let's assume the user knows what he's doing so we can be safe and say that if we
24038512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    // couldn't find a def, it is live out.
24048512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    return true;
24058512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
24068512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
24078512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // If it is not -1, we found a match, is it ssa_reg?
24088512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  return (ssa_reg == last_ssa_reg);
24098512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
24108512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
24118512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beylerbool BasicBlock::ReplaceChild(BasicBlockId old_bb, BasicBlockId new_bb) {
24128512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  // We need to check taken, fall_through, and successor_blocks to replace.
24138512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  bool found = false;
24148512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (taken == old_bb) {
24158512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    taken = new_bb;
24168512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    found = true;
24178512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
24188512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
24198512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (fall_through == old_bb) {
24208512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    fall_through = new_bb;
24218512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    found = true;
24228512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
24238512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
24248512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  if (successor_block_list_type != kNotUsed) {
2425e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko    for (SuccessorBlockInfo* successor_block_info : successor_blocks) {
24268512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      if (successor_block_info->block == old_bb) {
24278512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler        successor_block_info->block = new_bb;
24288512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler        found = true;
24298512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler      }
24308512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler    }
24318512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
24328512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
24338512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  return found;
24348512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
24358512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
2436e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Markovoid BasicBlock::ErasePredecessor(BasicBlockId old_pred) {
2437e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  auto pos = std::find(predecessors.begin(), predecessors.end(), old_pred);
2438e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  DCHECK(pos != predecessors.end());
2439312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  // It's faster to move the back() to *pos than erase(pos).
2440312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  *pos = predecessors.back();
2441312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  predecessors.pop_back();
2442312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  size_t idx = std::distance(predecessors.begin(), pos);
2443312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  for (MIR* mir = first_mir_insn; mir != nullptr; mir = mir->next) {
2444312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko    if (static_cast<int>(mir->dalvikInsn.opcode) != kMirOpPhi) {
2445312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko      break;
2446312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko    }
2447312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko    DCHECK_EQ(mir->ssa_rep->num_uses - 1u, predecessors.size());
2448312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko    DCHECK_EQ(mir->meta.phi_incoming[idx], old_pred);
2449312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko    mir->meta.phi_incoming[idx] = mir->meta.phi_incoming[predecessors.size()];
2450312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko    mir->ssa_rep->uses[idx] = mir->ssa_rep->uses[predecessors.size()];
2451312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko    mir->ssa_rep->num_uses = predecessors.size();
2452312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  }
2453e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko}
24548512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
2455e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Markovoid BasicBlock::UpdatePredecessor(BasicBlockId old_pred, BasicBlockId new_pred) {
2456e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  DCHECK_NE(new_pred, NullBasicBlockId);
2457e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  auto pos = std::find(predecessors.begin(), predecessors.end(), old_pred);
2458312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  DCHECK(pos != predecessors.end());
2459312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  *pos = new_pred;
2460312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  size_t idx = std::distance(predecessors.begin(), pos);
2461312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko  for (MIR* mir = first_mir_insn; mir != nullptr; mir = mir->next) {
2462312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko    if (static_cast<int>(mir->dalvikInsn.opcode) != kMirOpPhi) {
2463312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko      break;
2464312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko    }
2465312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko    DCHECK_EQ(mir->meta.phi_incoming[idx], old_pred);
2466312eb25273dc0e2f8880d80f00c5b0998febaf7bVladimir Marko    mir->meta.phi_incoming[idx] = new_pred;
24678512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  }
24688512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
24698512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
24708512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler// Create a new basic block with block_id as num_blocks_ that is
24718512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler// post-incremented.
24728512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe BeylerBasicBlock* MIRGraph::CreateNewBB(BBType block_type) {
2473ffda4993af78484feb7a4ce5497c1796463c0ba1Vladimir Marko  BasicBlockId id = static_cast<BasicBlockId>(block_list_.size());
2474ffda4993af78484feb7a4ce5497c1796463c0ba1Vladimir Marko  BasicBlock* res = NewMemBB(block_type, id);
2475e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko  block_list_.push_back(res);
24768512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler  return res;
24778512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler}
24788512758d1208d3c32bf67db9c925b8fc6e077fd7Jean Christophe Beyler
2479216eaa2927f424821a03d7c4c6bf701fdb48e865Nicolas Geoffrayvoid MIRGraph::CalculateBasicBlockInformation(const PassManager* const post_opt_pass_manager) {
24805bdab12d8b48ca4c395d9d2c506ebff0df01b734Mathieu Chartier  /* Create the pass driver and launch it */
2481216eaa2927f424821a03d7c4c6bf701fdb48e865Nicolas Geoffray  PassDriverMEPostOpt driver(post_opt_pass_manager, cu_);
24822469e60e6ff08c2a0b4cd1e209246c5d91027679Jean Christophe Beyler  driver.Launch();
24832469e60e6ff08c2a0b4cd1e209246c5d91027679Jean Christophe Beyler}
24842469e60e6ff08c2a0b4cd1e209246c5d91027679Jean Christophe Beyler
2485fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beylerint MIR::DecodedInstruction::FlagsOf() const {
2486fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler  // Calculate new index.
2487fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler  int idx = static_cast<int>(opcode) - kNumPackedOpcodes;
2488fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler
2489fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler  // Check if it is an extended or not.
2490fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler  if (idx < 0) {
2491fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    return Instruction::FlagsOf(opcode);
2492fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler  }
2493fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler
2494fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler  // For extended, we use a switch.
2495fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler  switch (static_cast<int>(opcode)) {
2496fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPhi:
2497fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2498fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpCopy:
2499fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2500fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpFusedCmplFloat:
2501fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue | Instruction::kBranch;
2502fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpFusedCmpgFloat:
2503fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue | Instruction::kBranch;
2504fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpFusedCmplDouble:
2505fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue | Instruction::kBranch;
2506fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpFusedCmpgDouble:
2507fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue | Instruction::kBranch;
2508fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpFusedCmpLong:
2509fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue | Instruction::kBranch;
2510fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpNop:
2511fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2512fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpNullCheck:
2513fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue | Instruction::kThrow;
2514fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpRangeCheck:
2515fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue | Instruction::kThrow;
2516fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpDivZeroCheck:
2517fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue | Instruction::kThrow;
2518fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpCheck:
2519b7fc629dc562ee9f3df04a112a70b7868664f94dUdayan Banerji      return Instruction::kContinue | Instruction::kThrow;
2520fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpSelect:
2521fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2522fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpConstVector:
2523fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2524fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpMoveVector:
2525fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2526fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedMultiply:
2527fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2528fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedAddition:
2529fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2530fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedSubtract:
2531fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2532fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedShiftLeft:
2533fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2534fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedSignedShiftRight:
2535fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2536fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedUnsignedShiftRight:
2537fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2538fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedAnd:
2539fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2540fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedOr:
2541fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2542fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedXor:
2543fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2544fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedAddReduce:
2545fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2546fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedReduce:
2547fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2548fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpPackedSet:
2549fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2550fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpReserveVectorRegisters:
2551fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2552fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    case kMirOpReturnVectorRegisters:
2553fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return Instruction::kContinue;
2554b7fc629dc562ee9f3df04a112a70b7868664f94dUdayan Banerji    case kMirOpMemBarrier:
2555b7fc629dc562ee9f3df04a112a70b7868664f94dUdayan Banerji      return Instruction::kContinue;
2556b7fc629dc562ee9f3df04a112a70b7868664f94dUdayan Banerji    case kMirOpPackedArrayGet:
2557b7fc629dc562ee9f3df04a112a70b7868664f94dUdayan Banerji      return Instruction::kContinue | Instruction::kThrow;
2558b7fc629dc562ee9f3df04a112a70b7868664f94dUdayan Banerji    case kMirOpPackedArrayPut:
2559b7fc629dc562ee9f3df04a112a70b7868664f94dUdayan Banerji      return Instruction::kContinue | Instruction::kThrow;
2560a262f7707330dccfb50af6345813083182b61043Ningsheng Jian    case kMirOpMaddInt:
2561a262f7707330dccfb50af6345813083182b61043Ningsheng Jian    case kMirOpMsubInt:
2562a262f7707330dccfb50af6345813083182b61043Ningsheng Jian    case kMirOpMaddLong:
2563a262f7707330dccfb50af6345813083182b61043Ningsheng Jian    case kMirOpMsubLong:
2564a262f7707330dccfb50af6345813083182b61043Ningsheng Jian      return Instruction::kContinue;
2565fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler    default:
2566fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      LOG(WARNING) << "ExtendedFlagsOf: Unhandled case: " << static_cast<int> (opcode);
2567fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler      return 0;
2568fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler  }
2569fb0ea2df9a52e5db18e1aa85da282938bbd92f2eJean Christophe Beyler}
25700b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe
25710b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampeconst uint16_t* MIRGraph::GetInsns(int m_unit_index) const {
25720b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe  return m_units_[m_unit_index]->GetCodeItem()->insns_;
25730b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe}
25740b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe
25757a01dc2107d4255b445c32867d15d45fcebb3acdVladimir Markovoid MIRGraph::SetPuntToInterpreter(bool val) {
25767a01dc2107d4255b445c32867d15d45fcebb3acdVladimir Marko  punt_to_interpreter_ = val;
25777a01dc2107d4255b445c32867d15d45fcebb3acdVladimir Marko  if (val) {
25787a01dc2107d4255b445c32867d15d45fcebb3acdVladimir Marko    // Disable all subsequent optimizations. They may not be safe to run. (For example,
25797a01dc2107d4255b445c32867d15d45fcebb3acdVladimir Marko    // LVN/GVN assumes there are no conflicts found by the type inference pass.)
25807a01dc2107d4255b445c32867d15d45fcebb3acdVladimir Marko    cu_->disable_opt = ~static_cast<decltype(cu_->disable_opt)>(0);
25817a01dc2107d4255b445c32867d15d45fcebb3acdVladimir Marko  }
25827a01dc2107d4255b445c32867d15d45fcebb3acdVladimir Marko}
25837a01dc2107d4255b445c32867d15d45fcebb3acdVladimir Marko
25847934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom}  // namespace art
2585