Home | History | Annotate | Download | only in dex
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "dataflow_iterator-inl.h"
     18 #include "dex/mir_field_info.h"
     19 #include "global_value_numbering.h"
     20 #include "gvn_dead_code_elimination.h"
     21 #include "local_value_numbering.h"
     22 #include "gtest/gtest.h"
     23 
     24 namespace art {
     25 
     26 class GvnDeadCodeEliminationTest : public testing::Test {
     27  protected:
     28   static constexpr uint16_t kNoValue = GlobalValueNumbering::kNoValue;
     29 
     30   struct IFieldDef {
     31     uint16_t field_idx;
     32     uintptr_t declaring_dex_file;
     33     uint16_t declaring_field_idx;
     34     bool is_volatile;
     35     DexMemAccessType type;
     36   };
     37 
     38   struct SFieldDef {
     39     uint16_t field_idx;
     40     uintptr_t declaring_dex_file;
     41     uint16_t declaring_field_idx;
     42     bool is_volatile;
     43     DexMemAccessType type;
     44   };
     45 
     46   struct BBDef {
     47     static constexpr size_t kMaxSuccessors = 4;
     48     static constexpr size_t kMaxPredecessors = 4;
     49 
     50     BBType type;
     51     size_t num_successors;
     52     BasicBlockId successors[kMaxPredecessors];
     53     size_t num_predecessors;
     54     BasicBlockId predecessors[kMaxPredecessors];
     55   };
     56 
     57   struct MIRDef {
     58     static constexpr size_t kMaxSsaDefs = 2;
     59     static constexpr size_t kMaxSsaUses = 4;
     60 
     61     BasicBlockId bbid;
     62     Instruction::Code opcode;
     63     int64_t value;
     64     uint32_t field_info;
     65     size_t num_uses;
     66     int32_t uses[kMaxSsaUses];
     67     size_t num_defs;
     68     int32_t defs[kMaxSsaDefs];
     69   };
     70 
     71 #define DEF_SUCC0() \
     72     0u, { }
     73 #define DEF_SUCC1(s1) \
     74     1u, { s1 }
     75 #define DEF_SUCC2(s1, s2) \
     76     2u, { s1, s2 }
     77 #define DEF_SUCC3(s1, s2, s3) \
     78     3u, { s1, s2, s3 }
     79 #define DEF_SUCC4(s1, s2, s3, s4) \
     80     4u, { s1, s2, s3, s4 }
     81 #define DEF_PRED0() \
     82     0u, { }
     83 #define DEF_PRED1(p1) \
     84     1u, { p1 }
     85 #define DEF_PRED2(p1, p2) \
     86     2u, { p1, p2 }
     87 #define DEF_PRED3(p1, p2, p3) \
     88     3u, { p1, p2, p3 }
     89 #define DEF_PRED4(p1, p2, p3, p4) \
     90     4u, { p1, p2, p3, p4 }
     91 #define DEF_BB(type, succ, pred) \
     92     { type, succ, pred }
     93 
     94 #define DEF_CONST(bb, opcode, reg, value) \
     95     { bb, opcode, value, 0u, 0, { }, 1, { reg } }
     96 #define DEF_CONST_WIDE(bb, opcode, reg, value) \
     97     { bb, opcode, value, 0u, 0, { }, 2, { reg, reg + 1 } }
     98 #define DEF_CONST_STRING(bb, opcode, reg, index) \
     99     { bb, opcode, index, 0u, 0, { }, 1, { reg } }
    100 #define DEF_IGET(bb, opcode, reg, obj, field_info) \
    101     { bb, opcode, 0u, field_info, 1, { obj }, 1, { reg } }
    102 #define DEF_IGET_WIDE(bb, opcode, reg, obj, field_info) \
    103     { bb, opcode, 0u, field_info, 1, { obj }, 2, { reg, reg + 1 } }
    104 #define DEF_IPUT(bb, opcode, reg, obj, field_info) \
    105     { bb, opcode, 0u, field_info, 2, { reg, obj }, 0, { } }
    106 #define DEF_IPUT_WIDE(bb, opcode, reg, obj, field_info) \
    107     { bb, opcode, 0u, field_info, 3, { reg, reg + 1, obj }, 0, { } }
    108 #define DEF_SGET(bb, opcode, reg, field_info) \
    109     { bb, opcode, 0u, field_info, 0, { }, 1, { reg } }
    110 #define DEF_SGET_WIDE(bb, opcode, reg, field_info) \
    111     { bb, opcode, 0u, field_info, 0, { }, 2, { reg, reg + 1 } }
    112 #define DEF_SPUT(bb, opcode, reg, field_info) \
    113     { bb, opcode, 0u, field_info, 1, { reg }, 0, { } }
    114 #define DEF_SPUT_WIDE(bb, opcode, reg, field_info) \
    115     { bb, opcode, 0u, field_info, 2, { reg, reg + 1 }, 0, { } }
    116 #define DEF_AGET(bb, opcode, reg, obj, idx) \
    117     { bb, opcode, 0u, 0u, 2, { obj, idx }, 1, { reg } }
    118 #define DEF_AGET_WIDE(bb, opcode, reg, obj, idx) \
    119     { bb, opcode, 0u, 0u, 2, { obj, idx }, 2, { reg, reg + 1 } }
    120 #define DEF_APUT(bb, opcode, reg, obj, idx) \
    121     { bb, opcode, 0u, 0u, 3, { reg, obj, idx }, 0, { } }
    122 #define DEF_APUT_WIDE(bb, opcode, reg, obj, idx) \
    123     { bb, opcode, 0u, 0u, 4, { reg, reg + 1, obj, idx }, 0, { } }
    124 #define DEF_INVOKE1(bb, opcode, reg) \
    125     { bb, opcode, 0u, 0u, 1, { reg }, 0, { } }
    126 #define DEF_UNIQUE_REF(bb, opcode, reg) \
    127     { bb, opcode, 0u, 0u, 0, { }, 1, { reg } }  // CONST_CLASS, CONST_STRING, NEW_ARRAY, ...
    128 #define DEF_IFZ(bb, opcode, reg) \
    129     { bb, opcode, 0u, 0u, 1, { reg }, 0, { } }
    130 #define DEF_MOVE(bb, opcode, reg, src) \
    131     { bb, opcode, 0u, 0u, 1, { src }, 1, { reg } }
    132 #define DEF_MOVE_WIDE(bb, opcode, reg, src) \
    133     { bb, opcode, 0u, 0u, 2, { src, src + 1 }, 2, { reg, reg + 1 } }
    134 #define DEF_PHI2(bb, reg, src1, src2) \
    135     { bb, static_cast<Instruction::Code>(kMirOpPhi), 0, 0u, 2u, { src1, src2 }, 1, { reg } }
    136 #define DEF_UNOP(bb, opcode, result, src1) \
    137     { bb, opcode, 0u, 0u, 1, { src1 }, 1, { result } }
    138 #define DEF_BINOP(bb, opcode, result, src1, src2) \
    139     { bb, opcode, 0u, 0u, 2, { src1, src2 }, 1, { result } }
    140 #define DEF_BINOP_WIDE(bb, opcode, result, src1, src2) \
    141     { bb, opcode, 0u, 0u, 4, { src1, src1 + 1, src2, src2 + 1 }, 2, { result, result + 1 } }
    142 
    143   void DoPrepareIFields(const IFieldDef* defs, size_t count) {
    144     cu_.mir_graph->ifield_lowering_infos_.clear();
    145     cu_.mir_graph->ifield_lowering_infos_.reserve(count);
    146     for (size_t i = 0u; i != count; ++i) {
    147       const IFieldDef* def = &defs[i];
    148       MirIFieldLoweringInfo field_info(def->field_idx, def->type, false);
    149       if (def->declaring_dex_file != 0u) {
    150         field_info.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file);
    151         field_info.declaring_field_idx_ = def->declaring_field_idx;
    152         field_info.flags_ =
    153             MirIFieldLoweringInfo::kFlagFastGet | MirIFieldLoweringInfo::kFlagFastPut |
    154             (field_info.flags_ & ~(def->is_volatile ? 0u : MirIFieldLoweringInfo::kFlagIsVolatile));
    155       }
    156       cu_.mir_graph->ifield_lowering_infos_.push_back(field_info);
    157     }
    158   }
    159 
    160   template <size_t count>
    161   void PrepareIFields(const IFieldDef (&defs)[count]) {
    162     DoPrepareIFields(defs, count);
    163   }
    164 
    165   void DoPrepareSFields(const SFieldDef* defs, size_t count) {
    166     cu_.mir_graph->sfield_lowering_infos_.clear();
    167     cu_.mir_graph->sfield_lowering_infos_.reserve(count);
    168     for (size_t i = 0u; i != count; ++i) {
    169       const SFieldDef* def = &defs[i];
    170       MirSFieldLoweringInfo field_info(def->field_idx, def->type);
    171       // Mark even unresolved fields as initialized.
    172       field_info.flags_ |= MirSFieldLoweringInfo::kFlagClassIsInitialized;
    173       // NOTE: MirSFieldLoweringInfo::kFlagClassIsInDexCache isn't used by GVN.
    174       if (def->declaring_dex_file != 0u) {
    175         field_info.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file);
    176         field_info.declaring_field_idx_ = def->declaring_field_idx;
    177         field_info.flags_ =
    178             MirSFieldLoweringInfo::kFlagFastGet | MirSFieldLoweringInfo::kFlagFastPut |
    179             (field_info.flags_ & ~(def->is_volatile ? 0u : MirSFieldLoweringInfo::kFlagIsVolatile));
    180       }
    181       cu_.mir_graph->sfield_lowering_infos_.push_back(field_info);
    182     }
    183   }
    184 
    185   template <size_t count>
    186   void PrepareSFields(const SFieldDef (&defs)[count]) {
    187     DoPrepareSFields(defs, count);
    188   }
    189 
    190   void DoPrepareBasicBlocks(const BBDef* defs, size_t count) {
    191     cu_.mir_graph->block_id_map_.clear();
    192     cu_.mir_graph->block_list_.clear();
    193     ASSERT_LT(3u, count);  // null, entry, exit and at least one bytecode block.
    194     ASSERT_EQ(kNullBlock, defs[0].type);
    195     ASSERT_EQ(kEntryBlock, defs[1].type);
    196     ASSERT_EQ(kExitBlock, defs[2].type);
    197     for (size_t i = 0u; i != count; ++i) {
    198       const BBDef* def = &defs[i];
    199       BasicBlock* bb = cu_.mir_graph->CreateNewBB(def->type);
    200       if (def->num_successors <= 2) {
    201         bb->successor_block_list_type = kNotUsed;
    202         bb->fall_through = (def->num_successors >= 1) ? def->successors[0] : 0u;
    203         bb->taken = (def->num_successors >= 2) ? def->successors[1] : 0u;
    204       } else {
    205         bb->successor_block_list_type = kPackedSwitch;
    206         bb->fall_through = 0u;
    207         bb->taken = 0u;
    208         bb->successor_blocks.reserve(def->num_successors);
    209         for (size_t j = 0u; j != def->num_successors; ++j) {
    210           SuccessorBlockInfo* successor_block_info =
    211               static_cast<SuccessorBlockInfo*>(cu_.arena.Alloc(sizeof(SuccessorBlockInfo),
    212                                                                kArenaAllocSuccessor));
    213           successor_block_info->block = j;
    214           successor_block_info->key = 0u;  // Not used by class init check elimination.
    215           bb->successor_blocks.push_back(successor_block_info);
    216         }
    217       }
    218       bb->predecessors.assign(def->predecessors, def->predecessors + def->num_predecessors);
    219       if (def->type == kDalvikByteCode || def->type == kEntryBlock || def->type == kExitBlock) {
    220         bb->data_flow_info = static_cast<BasicBlockDataFlow*>(
    221             cu_.arena.Alloc(sizeof(BasicBlockDataFlow), kArenaAllocDFInfo));
    222         bb->data_flow_info->live_in_v = live_in_v_;
    223         bb->data_flow_info->vreg_to_ssa_map_exit = nullptr;
    224       }
    225     }
    226     ASSERT_EQ(count, cu_.mir_graph->block_list_.size());
    227     cu_.mir_graph->entry_block_ = cu_.mir_graph->block_list_[1];
    228     ASSERT_EQ(kEntryBlock, cu_.mir_graph->entry_block_->block_type);
    229     cu_.mir_graph->exit_block_ = cu_.mir_graph->block_list_[2];
    230     ASSERT_EQ(kExitBlock, cu_.mir_graph->exit_block_->block_type);
    231   }
    232 
    233   template <size_t count>
    234   void PrepareBasicBlocks(const BBDef (&defs)[count]) {
    235     DoPrepareBasicBlocks(defs, count);
    236   }
    237 
    238   int SRegToVReg(int32_t s_reg, bool wide) {
    239     int v_reg = cu_.mir_graph->SRegToVReg(s_reg);
    240     CHECK_LT(static_cast<size_t>(v_reg), num_vregs_);
    241     if (wide) {
    242       CHECK_LT(static_cast<size_t>(v_reg + 1), num_vregs_);
    243     }
    244     return v_reg;
    245   }
    246 
    247   int SRegToVReg(int32_t* uses, size_t* use, bool wide) {
    248     int v_reg = SRegToVReg(uses[*use], wide);
    249     if (wide) {
    250       CHECK_EQ(uses[*use] + 1, uses[*use + 1]);
    251       *use += 2u;
    252     } else {
    253       *use += 1u;
    254     }
    255     return v_reg;
    256   }
    257 
    258   void DoPrepareMIRs(const MIRDef* defs, size_t count) {
    259     mir_count_ = count;
    260     mirs_ = reinterpret_cast<MIR*>(cu_.arena.Alloc(sizeof(MIR) * count, kArenaAllocMIR));
    261     ssa_reps_.resize(count);
    262     for (size_t i = 0u; i != count; ++i) {
    263       const MIRDef* def = &defs[i];
    264       MIR* mir = &mirs_[i];
    265       ASSERT_LT(def->bbid, cu_.mir_graph->block_list_.size());
    266       BasicBlock* bb = cu_.mir_graph->block_list_[def->bbid];
    267       bb->AppendMIR(mir);
    268       mir->dalvikInsn.opcode = def->opcode;
    269       mir->dalvikInsn.vB = static_cast<int32_t>(def->value);
    270       mir->dalvikInsn.vB_wide = def->value;
    271       if (IsInstructionIGetOrIPut(def->opcode)) {
    272         ASSERT_LT(def->field_info, cu_.mir_graph->ifield_lowering_infos_.size());
    273         mir->meta.ifield_lowering_info = def->field_info;
    274         ASSERT_EQ(cu_.mir_graph->ifield_lowering_infos_[def->field_info].MemAccessType(),
    275                   IGetOrIPutMemAccessType(def->opcode));
    276       } else if (IsInstructionSGetOrSPut(def->opcode)) {
    277         ASSERT_LT(def->field_info, cu_.mir_graph->sfield_lowering_infos_.size());
    278         mir->meta.sfield_lowering_info = def->field_info;
    279         ASSERT_EQ(cu_.mir_graph->sfield_lowering_infos_[def->field_info].MemAccessType(),
    280                   SGetOrSPutMemAccessType(def->opcode));
    281       } else if (def->opcode == static_cast<Instruction::Code>(kMirOpPhi)) {
    282         mir->meta.phi_incoming =
    283             allocator_->AllocArray<BasicBlockId>(def->num_uses, kArenaAllocDFInfo);
    284         ASSERT_EQ(def->num_uses, bb->predecessors.size());
    285         std::copy(bb->predecessors.begin(), bb->predecessors.end(), mir->meta.phi_incoming);
    286       }
    287       mir->ssa_rep = &ssa_reps_[i];
    288       cu_.mir_graph->AllocateSSAUseData(mir, def->num_uses);
    289       std::copy_n(def->uses, def->num_uses, mir->ssa_rep->uses);
    290       // Keep mir->ssa_rep->fp_use[.] zero-initialized (false). Not used by DCE, only copied.
    291       cu_.mir_graph->AllocateSSADefData(mir, def->num_defs);
    292       std::copy_n(def->defs, def->num_defs, mir->ssa_rep->defs);
    293       // Keep mir->ssa_rep->fp_def[.] zero-initialized (false). Not used by DCE, only copied.
    294       mir->dalvikInsn.opcode = def->opcode;
    295       mir->offset = i;  // LVN uses offset only for debug output
    296       mir->optimization_flags = 0u;
    297       uint64_t df_attrs = MIRGraph::GetDataFlowAttributes(mir);
    298       if ((df_attrs & DF_DA) != 0) {
    299         CHECK_NE(def->num_defs, 0u);
    300         mir->dalvikInsn.vA = SRegToVReg(def->defs[0], (df_attrs & DF_A_WIDE) != 0);
    301         bb->data_flow_info->vreg_to_ssa_map_exit[mir->dalvikInsn.vA] = def->defs[0];
    302         if ((df_attrs & DF_A_WIDE) != 0) {
    303           CHECK_EQ(def->defs[0] + 1, def->defs[1]);
    304           bb->data_flow_info->vreg_to_ssa_map_exit[mir->dalvikInsn.vA + 1u] = def->defs[0] + 1;
    305         }
    306       }
    307       if ((df_attrs & (DF_UA | DF_UB | DF_UC)) != 0) {
    308         size_t use = 0;
    309         if ((df_attrs & DF_UA) != 0) {
    310           mir->dalvikInsn.vA = SRegToVReg(mir->ssa_rep->uses, &use, (df_attrs & DF_A_WIDE) != 0);
    311         }
    312         if ((df_attrs & DF_UB) != 0) {
    313           mir->dalvikInsn.vB = SRegToVReg(mir->ssa_rep->uses, &use, (df_attrs & DF_B_WIDE) != 0);
    314         }
    315         if ((df_attrs & DF_UC) != 0) {
    316           mir->dalvikInsn.vC = SRegToVReg(mir->ssa_rep->uses, &use, (df_attrs & DF_C_WIDE) != 0);
    317         }
    318         DCHECK_EQ(def->num_uses, use);
    319       }
    320     }
    321     DexFile::CodeItem* code_item = static_cast<DexFile::CodeItem*>(
    322         cu_.arena.Alloc(sizeof(DexFile::CodeItem), kArenaAllocMisc));
    323     code_item->insns_size_in_code_units_ = 2u * count;
    324     code_item->registers_size_ = kMaxVRegs;
    325     cu_.mir_graph->current_code_item_ = code_item;
    326   }
    327 
    328   template <size_t count>
    329   void PrepareMIRs(const MIRDef (&defs)[count]) {
    330     DoPrepareMIRs(defs, count);
    331   }
    332 
    333   template <size_t count>
    334   void PrepareSRegToVRegMap(const int (&map)[count]) {
    335     cu_.mir_graph->ssa_base_vregs_.assign(map, map + count);
    336     num_vregs_ = *std::max_element(map, map + count) + 1u;
    337     AllNodesIterator iterator(cu_.mir_graph.get());
    338     for (BasicBlock* bb = iterator.Next(); bb != nullptr; bb = iterator.Next()) {
    339       if (bb->data_flow_info != nullptr) {
    340         bb->data_flow_info->vreg_to_ssa_map_exit = static_cast<int32_t*>(
    341             cu_.arena.Alloc(sizeof(int32_t) * num_vregs_, kArenaAllocDFInfo));
    342         std::fill_n(bb->data_flow_info->vreg_to_ssa_map_exit, num_vregs_, INVALID_SREG);
    343       }
    344     }
    345   }
    346 
    347   void PerformGVN() {
    348     cu_.mir_graph->SSATransformationStart();
    349     cu_.mir_graph->ComputeDFSOrders();
    350     cu_.mir_graph->ComputeDominators();
    351     cu_.mir_graph->ComputeTopologicalSortOrder();
    352     cu_.mir_graph->SSATransformationEnd();
    353     cu_.mir_graph->temp_.gvn.ifield_ids =  GlobalValueNumbering::PrepareGvnFieldIds(
    354         allocator_.get(), cu_.mir_graph->ifield_lowering_infos_);
    355     cu_.mir_graph->temp_.gvn.sfield_ids =  GlobalValueNumbering::PrepareGvnFieldIds(
    356         allocator_.get(), cu_.mir_graph->sfield_lowering_infos_);
    357     ASSERT_TRUE(gvn_ == nullptr);
    358     gvn_.reset(new (allocator_.get()) GlobalValueNumbering(&cu_, allocator_.get(),
    359                                                            GlobalValueNumbering::kModeGvn));
    360     value_names_.resize(mir_count_, 0xffffu);
    361     LoopRepeatingTopologicalSortIterator iterator(cu_.mir_graph.get());
    362     bool change = false;
    363     for (BasicBlock* bb = iterator.Next(change); bb != nullptr; bb = iterator.Next(change)) {
    364       LocalValueNumbering* lvn = gvn_->PrepareBasicBlock(bb);
    365       if (lvn != nullptr) {
    366         for (MIR* mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) {
    367           value_names_[mir - mirs_] = lvn->GetValueNumber(mir);
    368         }
    369       }
    370       change = (lvn != nullptr) && gvn_->FinishBasicBlock(bb);
    371       ASSERT_TRUE(gvn_->Good());
    372     }
    373   }
    374 
    375   void PerformGVNCodeModifications() {
    376     ASSERT_TRUE(gvn_ != nullptr);
    377     ASSERT_TRUE(gvn_->Good());
    378     gvn_->StartPostProcessing();
    379     TopologicalSortIterator iterator(cu_.mir_graph.get());
    380     for (BasicBlock* bb = iterator.Next(); bb != nullptr; bb = iterator.Next()) {
    381       LocalValueNumbering* lvn = gvn_->PrepareBasicBlock(bb);
    382       if (lvn != nullptr) {
    383         for (MIR* mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) {
    384           uint16_t value_name = lvn->GetValueNumber(mir);
    385           ASSERT_EQ(value_name, value_names_[mir - mirs_]);
    386         }
    387       }
    388       bool change = (lvn != nullptr) && gvn_->FinishBasicBlock(bb);
    389       ASSERT_FALSE(change);
    390       ASSERT_TRUE(gvn_->Good());
    391     }
    392   }
    393 
    394   void FillVregToSsaRegExitMaps() {
    395     // Fill in vreg_to_ssa_map_exit for each BB.
    396     PreOrderDfsIterator iterator(cu_.mir_graph.get());
    397     for (BasicBlock* bb = iterator.Next(); bb != nullptr; bb = iterator.Next()) {
    398       if (bb->block_type == kDalvikByteCode) {
    399         CHECK(!bb->predecessors.empty());
    400         BasicBlock* pred_bb = cu_.mir_graph->GetBasicBlock(bb->predecessors[0]);
    401         for (size_t v_reg = 0; v_reg != num_vregs_; ++v_reg) {
    402           if (bb->data_flow_info->vreg_to_ssa_map_exit[v_reg] == INVALID_SREG) {
    403             bb->data_flow_info->vreg_to_ssa_map_exit[v_reg] =
    404                 pred_bb->data_flow_info->vreg_to_ssa_map_exit[v_reg];
    405           }
    406         }
    407       }
    408     }
    409   }
    410 
    411   template <size_t count>
    412   void MarkAsWideSRegs(const int32_t (&sregs)[count]) {
    413     for (int32_t sreg : sregs) {
    414       cu_.mir_graph->reg_location_[sreg].wide = true;
    415       cu_.mir_graph->reg_location_[sreg + 1].wide = true;
    416       cu_.mir_graph->reg_location_[sreg + 1].high_word = true;
    417     }
    418   }
    419 
    420   void PerformDCE() {
    421     FillVregToSsaRegExitMaps();
    422     cu_.mir_graph->GetNumOfCodeAndTempVRs();
    423     dce_.reset(new (allocator_.get()) GvnDeadCodeElimination(gvn_.get(), allocator_.get()));
    424     PreOrderDfsIterator iterator(cu_.mir_graph.get());
    425     for (BasicBlock* bb = iterator.Next(); bb != nullptr; bb = iterator.Next()) {
    426       if (bb->block_type == kDalvikByteCode) {
    427         dce_->Apply(bb);
    428       }
    429     }
    430   }
    431 
    432   void PerformGVN_DCE() {
    433     PerformGVN();
    434     PerformGVNCodeModifications();  // Eliminate null/range checks.
    435     PerformDCE();
    436   }
    437 
    438   template <size_t count>
    439   void ExpectValueNamesNE(const size_t (&indexes)[count]) {
    440     for (size_t i1 = 0; i1 != count; ++i1) {
    441       size_t idx1 = indexes[i1];
    442       for (size_t i2 = i1 + 1; i2 != count; ++i2) {
    443         size_t idx2 = indexes[i2];
    444         EXPECT_NE(value_names_[idx1], value_names_[idx2]) << idx1 << " " << idx2;
    445       }
    446     }
    447   }
    448 
    449   template <size_t count>
    450   void ExpectNoNullCheck(const size_t (&indexes)[count]) {
    451     for (size_t i = 0; i != count; ++i) {
    452       size_t idx = indexes[i];
    453       EXPECT_EQ(MIR_IGNORE_NULL_CHECK, mirs_[idx].optimization_flags & MIR_IGNORE_NULL_CHECK)
    454           << idx;
    455     }
    456     size_t num_no_null_ck = 0u;
    457     for (size_t i = 0; i != mir_count_; ++i) {
    458       if ((mirs_[i].optimization_flags & MIR_IGNORE_NULL_CHECK) != 0) {
    459         ++num_no_null_ck;
    460       }
    461     }
    462     EXPECT_EQ(count, num_no_null_ck);
    463   }
    464 
    465   GvnDeadCodeEliminationTest()
    466       : pool_(),
    467         cu_(&pool_, kRuntimeISA, nullptr, nullptr),
    468         num_vregs_(0u),
    469         mir_count_(0u),
    470         mirs_(nullptr),
    471         ssa_reps_(),
    472         allocator_(),
    473         gvn_(),
    474         dce_(),
    475         value_names_(),
    476         live_in_v_(new (&cu_.arena) ArenaBitVector(&cu_.arena, kMaxSsaRegs, false, kBitMapMisc)) {
    477     cu_.mir_graph.reset(new MIRGraph(&cu_, &cu_.arena));
    478     cu_.access_flags = kAccStatic;  // Don't let "this" interfere with this test.
    479     allocator_.reset(ScopedArenaAllocator::Create(&cu_.arena_stack));
    480     // By default, the zero-initialized reg_location_[.] with ref == false tells LVN that
    481     // 0 constants are integral, not references, and the values are all narrow.
    482     // Nothing else is used by LVN/GVN. Tests can override the default values as needed.
    483     cu_.mir_graph->reg_location_ = static_cast<RegLocation*>(cu_.arena.Alloc(
    484         kMaxSsaRegs * sizeof(cu_.mir_graph->reg_location_[0]), kArenaAllocRegAlloc));
    485     cu_.mir_graph->num_ssa_regs_ = kMaxSsaRegs;
    486     // Bind all possible sregs to live vregs for test purposes.
    487     live_in_v_->SetInitialBits(kMaxSsaRegs);
    488     cu_.mir_graph->ssa_base_vregs_.reserve(kMaxSsaRegs);
    489     cu_.mir_graph->ssa_subscripts_.reserve(kMaxSsaRegs);
    490     for (unsigned int i = 0; i < kMaxSsaRegs; i++) {
    491       cu_.mir_graph->ssa_base_vregs_.push_back(i);
    492       cu_.mir_graph->ssa_subscripts_.push_back(0);
    493     }
    494     // Set shorty for a void-returning method without arguments.
    495     cu_.shorty = "V";
    496   }
    497 
    498   static constexpr size_t kMaxSsaRegs = 16384u;
    499   static constexpr size_t kMaxVRegs = 256u;
    500 
    501   ArenaPool pool_;
    502   CompilationUnit cu_;
    503   size_t num_vregs_;
    504   size_t mir_count_;
    505   MIR* mirs_;
    506   std::vector<SSARepresentation> ssa_reps_;
    507   std::unique_ptr<ScopedArenaAllocator> allocator_;
    508   std::unique_ptr<GlobalValueNumbering> gvn_;
    509   std::unique_ptr<GvnDeadCodeElimination> dce_;
    510   std::vector<uint16_t> value_names_;
    511   ArenaBitVector* live_in_v_;
    512 };
    513 
    514 constexpr uint16_t GvnDeadCodeEliminationTest::kNoValue;
    515 
    516 class GvnDeadCodeEliminationTestSimple : public GvnDeadCodeEliminationTest {
    517  public:
    518   GvnDeadCodeEliminationTestSimple();
    519 
    520  private:
    521   static const BBDef kSimpleBbs[];
    522 };
    523 
    524 const GvnDeadCodeEliminationTest::BBDef GvnDeadCodeEliminationTestSimple::kSimpleBbs[] = {
    525     DEF_BB(kNullBlock, DEF_SUCC0(), DEF_PRED0()),
    526     DEF_BB(kEntryBlock, DEF_SUCC1(3), DEF_PRED0()),
    527     DEF_BB(kExitBlock, DEF_SUCC0(), DEF_PRED1(3)),
    528     DEF_BB(kDalvikByteCode, DEF_SUCC1(2), DEF_PRED1(1)),
    529 };
    530 
    531 GvnDeadCodeEliminationTestSimple::GvnDeadCodeEliminationTestSimple()
    532     : GvnDeadCodeEliminationTest() {
    533   PrepareBasicBlocks(kSimpleBbs);
    534 }
    535 
    536 class GvnDeadCodeEliminationTestDiamond : public GvnDeadCodeEliminationTest {
    537  public:
    538   GvnDeadCodeEliminationTestDiamond();
    539 
    540  private:
    541   static const BBDef kDiamondBbs[];
    542 };
    543 
    544 const GvnDeadCodeEliminationTest::BBDef GvnDeadCodeEliminationTestDiamond::kDiamondBbs[] = {
    545     DEF_BB(kNullBlock, DEF_SUCC0(), DEF_PRED0()),
    546     DEF_BB(kEntryBlock, DEF_SUCC1(3), DEF_PRED0()),
    547     DEF_BB(kExitBlock, DEF_SUCC0(), DEF_PRED1(6)),
    548     DEF_BB(kDalvikByteCode, DEF_SUCC2(4, 5), DEF_PRED1(1)),  // Block #3, top of the diamond.
    549     DEF_BB(kDalvikByteCode, DEF_SUCC1(6), DEF_PRED1(3)),     // Block #4, left side.
    550     DEF_BB(kDalvikByteCode, DEF_SUCC1(6), DEF_PRED1(3)),     // Block #5, right side.
    551     DEF_BB(kDalvikByteCode, DEF_SUCC1(2), DEF_PRED2(4, 5)),  // Block #6, bottom.
    552 };
    553 
    554 GvnDeadCodeEliminationTestDiamond::GvnDeadCodeEliminationTestDiamond()
    555     : GvnDeadCodeEliminationTest() {
    556   PrepareBasicBlocks(kDiamondBbs);
    557 }
    558 
    559 class GvnDeadCodeEliminationTestLoop : public GvnDeadCodeEliminationTest {
    560  public:
    561   GvnDeadCodeEliminationTestLoop();
    562 
    563  private:
    564   static const BBDef kLoopBbs[];
    565 };
    566 
    567 const GvnDeadCodeEliminationTest::BBDef GvnDeadCodeEliminationTestLoop::kLoopBbs[] = {
    568     DEF_BB(kNullBlock, DEF_SUCC0(), DEF_PRED0()),
    569     DEF_BB(kEntryBlock, DEF_SUCC1(3), DEF_PRED0()),
    570     DEF_BB(kExitBlock, DEF_SUCC0(), DEF_PRED1(5)),
    571     DEF_BB(kDalvikByteCode, DEF_SUCC1(4), DEF_PRED1(1)),
    572     DEF_BB(kDalvikByteCode, DEF_SUCC2(5, 4), DEF_PRED2(3, 4)),  // "taken" loops to self.
    573     DEF_BB(kDalvikByteCode, DEF_SUCC1(2), DEF_PRED1(4)),
    574 };
    575 
    576 GvnDeadCodeEliminationTestLoop::GvnDeadCodeEliminationTestLoop()
    577     : GvnDeadCodeEliminationTest() {
    578   PrepareBasicBlocks(kLoopBbs);
    579 }
    580 
    581 TEST_F(GvnDeadCodeEliminationTestSimple, Rename1) {
    582   static const IFieldDef ifields[] = {
    583       { 0u, 1u, 0u, false, kDexMemAccessWord },
    584       { 1u, 1u, 1u, false, kDexMemAccessWord },
    585   };
    586   static const MIRDef mirs[] = {
    587       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
    588       DEF_IGET(3, Instruction::IGET, 1u, 0u, 0u),
    589       DEF_MOVE(3, Instruction::MOVE_OBJECT, 2u, 0u),
    590       DEF_IGET(3, Instruction::IGET, 3u, 2u, 1u),
    591   };
    592 
    593   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 2 };
    594   PrepareSRegToVRegMap(sreg_to_vreg_map);
    595 
    596   PrepareIFields(ifields);
    597   PrepareMIRs(mirs);
    598   PerformGVN_DCE();
    599 
    600   ASSERT_EQ(arraysize(mirs), value_names_.size());
    601   static const size_t diff_indexes[] = { 0, 1, 3 };
    602   ExpectValueNamesNE(diff_indexes);
    603   EXPECT_EQ(value_names_[0], value_names_[2]);
    604 
    605   const size_t no_null_ck_indexes[] = { 1, 3 };
    606   ExpectNoNullCheck(no_null_ck_indexes);
    607 
    608   static const bool eliminated[] = {
    609       false, false, true, false
    610   };
    611   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
    612   for (size_t i = 0; i != arraysize(eliminated); ++i) {
    613     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
    614     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
    615   }
    616   // Check that the IGET uses the s_reg 0, v_reg 0, defined by mirs_[0].
    617   ASSERT_EQ(1, mirs_[3].ssa_rep->num_uses);
    618   EXPECT_EQ(0, mirs_[3].ssa_rep->uses[0]);
    619   EXPECT_EQ(0u, mirs_[3].dalvikInsn.vB);
    620 }
    621 
    622 TEST_F(GvnDeadCodeEliminationTestSimple, Rename2) {
    623   static const IFieldDef ifields[] = {
    624       { 0u, 1u, 0u, false, kDexMemAccessWord },
    625       { 1u, 1u, 1u, false, kDexMemAccessWord },
    626   };
    627   static const MIRDef mirs[] = {
    628       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
    629       DEF_IGET(3, Instruction::IGET, 1u, 0u, 0u),
    630       DEF_MOVE(3, Instruction::MOVE_OBJECT, 2u, 0u),
    631       DEF_IGET(3, Instruction::IGET, 3u, 2u, 1u),
    632       DEF_CONST(3, Instruction::CONST, 4u, 1000),
    633   };
    634 
    635   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 3, 2 };
    636   PrepareSRegToVRegMap(sreg_to_vreg_map);
    637 
    638   PrepareIFields(ifields);
    639   PrepareMIRs(mirs);
    640   PerformGVN_DCE();
    641 
    642   ASSERT_EQ(arraysize(mirs), value_names_.size());
    643   static const size_t diff_indexes[] = { 0, 1, 3, 4 };
    644   ExpectValueNamesNE(diff_indexes);
    645   EXPECT_EQ(value_names_[0], value_names_[2]);
    646 
    647   const size_t no_null_ck_indexes[] = { 1, 3 };
    648   ExpectNoNullCheck(no_null_ck_indexes);
    649 
    650   static const bool eliminated[] = {
    651       false, false, true, false, false
    652   };
    653   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
    654   for (size_t i = 0; i != arraysize(eliminated); ++i) {
    655     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
    656     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
    657   }
    658   // Check that the IGET uses the s_reg 0, v_reg 0, defined by mirs_[0].
    659   ASSERT_EQ(1, mirs_[3].ssa_rep->num_uses);
    660   EXPECT_EQ(0, mirs_[3].ssa_rep->uses[0]);
    661   EXPECT_EQ(0u, mirs_[3].dalvikInsn.vB);
    662 }
    663 
    664 TEST_F(GvnDeadCodeEliminationTestSimple, Rename3) {
    665   static const IFieldDef ifields[] = {
    666       { 0u, 1u, 0u, false, kDexMemAccessWord },
    667       { 1u, 1u, 1u, false, kDexMemAccessWord },
    668   };
    669   static const MIRDef mirs[] = {
    670       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
    671       DEF_IGET(3, Instruction::IGET, 1u, 0u, 0u),
    672       DEF_MOVE(3, Instruction::MOVE_OBJECT, 2u, 0u),
    673       DEF_IGET(3, Instruction::IGET, 3u, 2u, 1u),
    674   };
    675 
    676   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 0 };
    677   PrepareSRegToVRegMap(sreg_to_vreg_map);
    678 
    679   PrepareIFields(ifields);
    680   PrepareMIRs(mirs);
    681   PerformGVN_DCE();
    682 
    683   ASSERT_EQ(arraysize(mirs), value_names_.size());
    684   static const size_t diff_indexes[] = { 0, 1, 3 };
    685   ExpectValueNamesNE(diff_indexes);
    686   EXPECT_EQ(value_names_[0], value_names_[2]);
    687 
    688   const size_t no_null_ck_indexes[] = { 1, 3 };
    689   ExpectNoNullCheck(no_null_ck_indexes);
    690 
    691   static const bool eliminated[] = {
    692       false, false, true, false
    693   };
    694   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
    695   for (size_t i = 0; i != arraysize(eliminated); ++i) {
    696     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
    697     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
    698   }
    699   // Check that the NEW_INSTANCE defines the s_reg 2, v_reg 2, originally defined by the move.
    700   ASSERT_EQ(1, mirs_[0].ssa_rep->num_defs);
    701   EXPECT_EQ(2, mirs_[0].ssa_rep->defs[0]);
    702   EXPECT_EQ(2u, mirs_[0].dalvikInsn.vA);
    703   // Check that the first IGET is using the s_reg 2, v_reg 2.
    704   ASSERT_EQ(1, mirs_[1].ssa_rep->num_uses);
    705   EXPECT_EQ(2, mirs_[1].ssa_rep->uses[0]);
    706   EXPECT_EQ(2u, mirs_[1].dalvikInsn.vB);
    707 }
    708 
    709 TEST_F(GvnDeadCodeEliminationTestSimple, Rename4) {
    710   static const MIRDef mirs[] = {
    711       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
    712       DEF_MOVE(3, Instruction::MOVE_OBJECT, 1u, 0u),
    713       DEF_MOVE(3, Instruction::MOVE_OBJECT, 2u, 1u),
    714       DEF_CONST_WIDE(3, Instruction::CONST_WIDE, 3u, 1000u),
    715   };
    716 
    717   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 0, 1 /* high word */ };
    718   PrepareSRegToVRegMap(sreg_to_vreg_map);
    719 
    720   PrepareMIRs(mirs);
    721   static const int32_t wide_sregs[] = { 3 };
    722   MarkAsWideSRegs(wide_sregs);
    723   PerformGVN_DCE();
    724 
    725   ASSERT_EQ(arraysize(mirs), value_names_.size());
    726   static const size_t diff_indexes[] = { 0, 3 };
    727   ExpectValueNamesNE(diff_indexes);
    728   EXPECT_EQ(value_names_[0], value_names_[1]);
    729   EXPECT_EQ(value_names_[0], value_names_[2]);
    730 
    731   static const bool eliminated[] = {
    732       false, true, true, false
    733   };
    734   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
    735   for (size_t i = 0; i != arraysize(eliminated); ++i) {
    736     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
    737     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
    738   }
    739   // Check that the NEW_INSTANCE defines the s_reg 2, v_reg 2, originally defined by the move 2u.
    740   ASSERT_EQ(1, mirs_[0].ssa_rep->num_defs);
    741   EXPECT_EQ(2, mirs_[0].ssa_rep->defs[0]);
    742   EXPECT_EQ(2u, mirs_[0].dalvikInsn.vA);
    743 }
    744 
    745 TEST_F(GvnDeadCodeEliminationTestSimple, Rename5) {
    746   static const IFieldDef ifields[] = {
    747       { 0u, 1u, 0u, false, kDexMemAccessWord },
    748   };
    749   static const MIRDef mirs[] = {
    750       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
    751       DEF_IGET(3, Instruction::IGET, 1u, 0u, 0u),
    752       DEF_UNOP(3, Instruction::INT_TO_FLOAT, 2u, 1u),
    753       DEF_MOVE(3, Instruction::MOVE_OBJECT, 3u, 0u),
    754       DEF_MOVE(3, Instruction::MOVE_OBJECT, 4u, 3u),
    755       DEF_CONST_WIDE(3, Instruction::CONST_WIDE, 5u, 1000u),
    756   };
    757 
    758   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 1, 3, 0, 1 /* high word */ };
    759   PrepareSRegToVRegMap(sreg_to_vreg_map);
    760 
    761   PrepareIFields(ifields);
    762   PrepareMIRs(mirs);
    763   static const int32_t wide_sregs[] = { 5 };
    764   MarkAsWideSRegs(wide_sregs);
    765   PerformGVN_DCE();
    766 
    767   ASSERT_EQ(arraysize(mirs), value_names_.size());
    768   static const size_t diff_indexes[] = { 0, 1, 2, 5 };
    769   ExpectValueNamesNE(diff_indexes);
    770   EXPECT_EQ(value_names_[0], value_names_[3]);
    771   EXPECT_EQ(value_names_[0], value_names_[4]);
    772 
    773   static const bool eliminated[] = {
    774       false, false, false, true, true, false
    775   };
    776   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
    777   for (size_t i = 0; i != arraysize(eliminated); ++i) {
    778     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
    779     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
    780   }
    781   // Check that the NEW_INSTANCE defines the s_reg 4, v_reg 3, originally defined by the move 4u.
    782   ASSERT_EQ(1, mirs_[0].ssa_rep->num_defs);
    783   EXPECT_EQ(4, mirs_[0].ssa_rep->defs[0]);
    784   EXPECT_EQ(3u, mirs_[0].dalvikInsn.vA);
    785 }
    786 
    787 TEST_F(GvnDeadCodeEliminationTestSimple, Rename6) {
    788   static const MIRDef mirs[] = {
    789       DEF_CONST_WIDE(3, Instruction::CONST_WIDE, 0u, 1000u),
    790       DEF_MOVE_WIDE(3, Instruction::MOVE_WIDE, 2u, 0u),
    791   };
    792 
    793   static const int32_t sreg_to_vreg_map[] = { 0, 1 /* high word */, 1, 2 /* high word */ };
    794   PrepareSRegToVRegMap(sreg_to_vreg_map);
    795 
    796   PrepareMIRs(mirs);
    797   static const int32_t wide_sregs[] = { 0, 2 };
    798   MarkAsWideSRegs(wide_sregs);
    799   PerformGVN_DCE();
    800 
    801   ASSERT_EQ(arraysize(mirs), value_names_.size());
    802   EXPECT_EQ(value_names_[0], value_names_[1]);
    803 
    804   static const bool eliminated[] = {
    805       false, true
    806   };
    807   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
    808   for (size_t i = 0; i != arraysize(eliminated); ++i) {
    809     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
    810     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
    811   }
    812   // Check that the CONST_WIDE defines the s_reg 2, v_reg 1, originally defined by the move 2u.
    813   ASSERT_EQ(2, mirs_[0].ssa_rep->num_defs);
    814   EXPECT_EQ(2, mirs_[0].ssa_rep->defs[0]);
    815   EXPECT_EQ(3, mirs_[0].ssa_rep->defs[1]);
    816   EXPECT_EQ(1u, mirs_[0].dalvikInsn.vA);
    817 }
    818 
    819 TEST_F(GvnDeadCodeEliminationTestSimple, Rename7) {
    820   static const MIRDef mirs[] = {
    821       DEF_CONST(3, Instruction::CONST, 0u, 1000u),
    822       DEF_MOVE(3, Instruction::MOVE, 1u, 0u),
    823       DEF_BINOP(3, Instruction::ADD_INT, 2u, 0u, 1u),
    824   };
    825 
    826   static const int32_t sreg_to_vreg_map[] = { 0, 1, 0 };
    827   PrepareSRegToVRegMap(sreg_to_vreg_map);
    828 
    829   PrepareMIRs(mirs);
    830   PerformGVN_DCE();
    831 
    832   ASSERT_EQ(arraysize(mirs), value_names_.size());
    833   EXPECT_NE(value_names_[0], value_names_[2]);
    834   EXPECT_EQ(value_names_[0], value_names_[1]);
    835 
    836   static const bool eliminated[] = {
    837       false, true, false
    838   };
    839   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
    840   for (size_t i = 0; i != arraysize(eliminated); ++i) {
    841     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
    842     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
    843   }
    844   // Check that the CONST defines the s_reg 1, v_reg 1, originally defined by the move 1u.
    845   ASSERT_EQ(1, mirs_[0].ssa_rep->num_defs);
    846   EXPECT_EQ(1, mirs_[0].ssa_rep->defs[0]);
    847   EXPECT_EQ(1u, mirs_[0].dalvikInsn.vA);
    848   // Check that the ADD_INT inputs are both s_reg1, vreg 1.
    849   ASSERT_EQ(2, mirs_[2].ssa_rep->num_uses);
    850   EXPECT_EQ(1, mirs_[2].ssa_rep->uses[0]);
    851   EXPECT_EQ(1, mirs_[2].ssa_rep->uses[1]);
    852   EXPECT_EQ(1u, mirs_[2].dalvikInsn.vB);
    853   EXPECT_EQ(1u, mirs_[2].dalvikInsn.vC);
    854 }
    855 
    856 TEST_F(GvnDeadCodeEliminationTestSimple, Rename8) {
    857   static const MIRDef mirs[] = {
    858       DEF_CONST(3, Instruction::CONST, 0u, 1000u),
    859       DEF_MOVE(3, Instruction::MOVE, 1u, 0u),
    860       DEF_BINOP(3, Instruction::ADD_INT_2ADDR, 2u, 0u, 1u),
    861   };
    862 
    863   static const int32_t sreg_to_vreg_map[] = { 0, 1, 0 };
    864   PrepareSRegToVRegMap(sreg_to_vreg_map);
    865 
    866   PrepareMIRs(mirs);
    867   PerformGVN_DCE();
    868 
    869   ASSERT_EQ(arraysize(mirs), value_names_.size());
    870   EXPECT_NE(value_names_[0], value_names_[2]);
    871   EXPECT_EQ(value_names_[0], value_names_[1]);
    872 
    873   static const bool eliminated[] = {
    874       false, true, false
    875   };
    876   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
    877   for (size_t i = 0; i != arraysize(eliminated); ++i) {
    878     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
    879     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
    880   }
    881   // Check that the CONST defines the s_reg 1, v_reg 1, originally defined by the move 1u.
    882   ASSERT_EQ(1, mirs_[0].ssa_rep->num_defs);
    883   EXPECT_EQ(1, mirs_[0].ssa_rep->defs[0]);
    884   EXPECT_EQ(1u, mirs_[0].dalvikInsn.vA);
    885   // Check that the ADD_INT_2ADDR was replaced by ADD_INT and inputs are both s_reg 1, vreg 1.
    886   EXPECT_EQ(Instruction::ADD_INT, mirs_[2].dalvikInsn.opcode);
    887   ASSERT_EQ(2, mirs_[2].ssa_rep->num_uses);
    888   EXPECT_EQ(1, mirs_[2].ssa_rep->uses[0]);
    889   EXPECT_EQ(1, mirs_[2].ssa_rep->uses[1]);
    890   EXPECT_EQ(1u, mirs_[2].dalvikInsn.vB);
    891   EXPECT_EQ(1u, mirs_[2].dalvikInsn.vC);
    892 }
    893 
    894 TEST_F(GvnDeadCodeEliminationTestSimple, Rename9) {
    895   static const MIRDef mirs[] = {
    896       DEF_CONST(3, Instruction::CONST, 0u, 1000u),
    897       DEF_BINOP(3, Instruction::ADD_INT_2ADDR, 1u, 0u, 0u),
    898       DEF_MOVE(3, Instruction::MOVE, 2u, 1u),
    899       DEF_CONST(3, Instruction::CONST, 3u, 3000u),
    900   };
    901 
    902   static const int32_t sreg_to_vreg_map[] = { 0, 0, 1, 0 };
    903   PrepareSRegToVRegMap(sreg_to_vreg_map);
    904 
    905   PrepareMIRs(mirs);
    906   PerformGVN_DCE();
    907 
    908   ASSERT_EQ(arraysize(mirs), value_names_.size());
    909   static const size_t diff_indexes[] = { 0, 1, 3 };
    910   ExpectValueNamesNE(diff_indexes);
    911   EXPECT_EQ(value_names_[1], value_names_[2]);
    912 
    913   static const bool eliminated[] = {
    914       false, false, true, false
    915   };
    916   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
    917   for (size_t i = 0; i != arraysize(eliminated); ++i) {
    918     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
    919     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
    920   }
    921   // Check that the ADD_INT_2ADDR was replaced by ADD_INT and output is in s_reg 2, vreg 1.
    922   EXPECT_EQ(Instruction::ADD_INT, mirs_[1].dalvikInsn.opcode);
    923   ASSERT_EQ(2, mirs_[1].ssa_rep->num_uses);
    924   EXPECT_EQ(0, mirs_[1].ssa_rep->uses[0]);
    925   EXPECT_EQ(0, mirs_[1].ssa_rep->uses[1]);
    926   EXPECT_EQ(0u, mirs_[1].dalvikInsn.vB);
    927   EXPECT_EQ(0u, mirs_[1].dalvikInsn.vC);
    928   ASSERT_EQ(1, mirs_[1].ssa_rep->num_defs);
    929   EXPECT_EQ(2, mirs_[1].ssa_rep->defs[0]);
    930   EXPECT_EQ(1u, mirs_[1].dalvikInsn.vA);
    931 }
    932 
    933 TEST_F(GvnDeadCodeEliminationTestSimple, NoRename1) {
    934   static const IFieldDef ifields[] = {
    935       { 0u, 1u, 0u, false, kDexMemAccessWord },
    936       { 1u, 1u, 1u, false, kDexMemAccessWord },
    937   };
    938   static const MIRDef mirs[] = {
    939       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
    940       DEF_IGET(3, Instruction::IGET, 1u, 0u, 0u),
    941       DEF_UNOP(3, Instruction::INT_TO_FLOAT, 2u, 1u),
    942       DEF_MOVE(3, Instruction::MOVE_OBJECT, 3u, 0u),
    943       DEF_CONST(3, Instruction::CONST, 4u, 1000),
    944       DEF_IGET(3, Instruction::IGET, 5u, 3u, 1u),
    945   };
    946 
    947   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 1, 0, 1 };
    948   PrepareSRegToVRegMap(sreg_to_vreg_map);
    949 
    950   PrepareIFields(ifields);
    951   PrepareMIRs(mirs);
    952   PerformGVN_DCE();
    953 
    954   ASSERT_EQ(arraysize(mirs), value_names_.size());
    955   static const size_t diff_indexes[] = { 0, 1, 2, 4, 5 };
    956   ExpectValueNamesNE(diff_indexes);
    957   EXPECT_EQ(value_names_[0], value_names_[3]);
    958 
    959   const size_t no_null_ck_indexes[] = { 1, 5 };
    960   ExpectNoNullCheck(no_null_ck_indexes);
    961 
    962   static const bool eliminated[] = {
    963       false, false, false, false, false, false
    964   };
    965   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
    966   for (size_t i = 0; i != arraysize(eliminated); ++i) {
    967     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
    968     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
    969   }
    970 }
    971 
    972 TEST_F(GvnDeadCodeEliminationTestSimple, NoRename2) {
    973   static const IFieldDef ifields[] = {
    974       { 0u, 1u, 0u, false, kDexMemAccessWord },
    975       { 1u, 1u, 1u, false, kDexMemAccessWord },
    976   };
    977   static const MIRDef mirs[] = {
    978       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
    979       DEF_IGET(3, Instruction::IGET, 1u, 0u, 0u),
    980       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 2u),
    981       DEF_MOVE(3, Instruction::MOVE_OBJECT, 3u, 0u),
    982       DEF_CONST(3, Instruction::CONST, 4u, 1000),
    983       DEF_IGET(3, Instruction::IGET, 5u, 3u, 1u),
    984       DEF_CONST(3, Instruction::CONST, 6u, 2000),
    985   };
    986 
    987   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 2, 0, 3, 2 };
    988   PrepareSRegToVRegMap(sreg_to_vreg_map);
    989 
    990   PrepareIFields(ifields);
    991   PrepareMIRs(mirs);
    992   PerformGVN_DCE();
    993 
    994   ASSERT_EQ(arraysize(mirs), value_names_.size());
    995   static const size_t diff_indexes[] = { 0, 1, 2, 4, 5, 6 };
    996   ExpectValueNamesNE(diff_indexes);
    997   EXPECT_EQ(value_names_[0], value_names_[3]);
    998 
    999   const size_t no_null_ck_indexes[] = { 1, 5 };
   1000   ExpectNoNullCheck(no_null_ck_indexes);
   1001 
   1002   static const bool eliminated[] = {
   1003       false, false, false, false, false, false, false
   1004   };
   1005   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1006   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1007     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1008     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1009   }
   1010 }
   1011 
   1012 TEST_F(GvnDeadCodeEliminationTestSimple, NoRename3) {
   1013   static const IFieldDef ifields[] = {
   1014       { 0u, 1u, 0u, false, kDexMemAccessWord },
   1015       { 1u, 1u, 1u, false, kDexMemAccessWord },
   1016       { 2u, 1u, 2u, false, kDexMemAccessWord },
   1017   };
   1018   static const MIRDef mirs[] = {
   1019       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
   1020       DEF_IGET(3, Instruction::IGET, 1u, 0u, 0u),
   1021       DEF_IGET(3, Instruction::IGET, 2u, 0u, 2u),
   1022       DEF_BINOP(3, Instruction::ADD_INT, 3u, 1u, 2u),
   1023       DEF_MOVE(3, Instruction::MOVE_OBJECT, 4u, 0u),
   1024       DEF_IGET(3, Instruction::IGET, 5u, 4u, 1u),
   1025   };
   1026 
   1027   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 3, 2, 0 };
   1028   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1029 
   1030   PrepareIFields(ifields);
   1031   PrepareMIRs(mirs);
   1032   PerformGVN_DCE();
   1033 
   1034   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1035   static const size_t diff_indexes[] = { 0, 1, 2, 3, 5 };
   1036   ExpectValueNamesNE(diff_indexes);
   1037   EXPECT_EQ(value_names_[0], value_names_[4]);
   1038 
   1039   const size_t no_null_ck_indexes[] = { 1, 2, 5 };
   1040   ExpectNoNullCheck(no_null_ck_indexes);
   1041 
   1042   static const bool eliminated[] = {
   1043       false, false, false, false, false, false
   1044   };
   1045   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1046   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1047     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1048     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1049   }
   1050 }
   1051 
   1052 TEST_F(GvnDeadCodeEliminationTestSimple, NoRename4) {
   1053   static const MIRDef mirs[] = {
   1054       DEF_CONST(3, Instruction::CONST, 0u, 1000u),
   1055       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 1u),
   1056       DEF_CONST(3, Instruction::CONST, 2u, 100u),
   1057       DEF_CONST(3, Instruction::CONST, 3u, 200u),
   1058       DEF_BINOP(3, Instruction::OR_INT_2ADDR, 4u, 2u, 3u),   // 3. Find definition of the move src.
   1059       DEF_MOVE(3, Instruction::MOVE, 5u, 0u),                // 4. Uses move dest vreg.
   1060       DEF_MOVE(3, Instruction::MOVE, 6u, 4u),                // 2. Find overwritten move src.
   1061       DEF_CONST(3, Instruction::CONST, 7u, 2000u),           // 1. Overwrites 4u, look for moves.
   1062   };
   1063 
   1064   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 3, 2, 4, 0, 2 };
   1065   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1066 
   1067   PrepareMIRs(mirs);
   1068   PerformGVN_DCE();
   1069 
   1070   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1071   static const size_t diff_indexes[] = { 0, 1, 2, 3, 4, 7 };
   1072   ExpectValueNamesNE(diff_indexes);
   1073   EXPECT_EQ(value_names_[0], value_names_[5]);
   1074   EXPECT_EQ(value_names_[4], value_names_[6]);
   1075 
   1076   static const bool eliminated[] = {
   1077       false, false, false, false, false, false, false, false
   1078   };
   1079   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1080   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1081     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1082     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1083   }
   1084 }
   1085 
   1086 TEST_F(GvnDeadCodeEliminationTestSimple, Simple1) {
   1087   static const IFieldDef ifields[] = {
   1088       { 0u, 1u, 0u, false, kDexMemAccessObject },
   1089       { 1u, 1u, 1u, false, kDexMemAccessObject },
   1090       { 2u, 1u, 2u, false, kDexMemAccessWord },
   1091   };
   1092   static const MIRDef mirs[] = {
   1093       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
   1094       DEF_IGET(3, Instruction::IGET_OBJECT, 1u, 0u, 0u),
   1095       DEF_IGET(3, Instruction::IGET_OBJECT, 2u, 1u, 1u),
   1096       DEF_IGET(3, Instruction::IGET, 3u, 2u, 2u),
   1097       DEF_IGET(3, Instruction::IGET_OBJECT, 4u, 0u, 0u),
   1098       DEF_IGET(3, Instruction::IGET_OBJECT, 5u, 4u, 1u),
   1099   };
   1100 
   1101   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 3, 1, 2 };
   1102   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1103 
   1104   PrepareIFields(ifields);
   1105   PrepareMIRs(mirs);
   1106   PerformGVN_DCE();
   1107 
   1108   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1109   EXPECT_NE(value_names_[0], value_names_[1]);
   1110   EXPECT_NE(value_names_[0], value_names_[2]);
   1111   EXPECT_NE(value_names_[0], value_names_[3]);
   1112   EXPECT_NE(value_names_[1], value_names_[2]);
   1113   EXPECT_NE(value_names_[1], value_names_[3]);
   1114   EXPECT_NE(value_names_[2], value_names_[3]);
   1115   EXPECT_EQ(value_names_[1], value_names_[4]);
   1116   EXPECT_EQ(value_names_[2], value_names_[5]);
   1117 
   1118   EXPECT_EQ(MIR_IGNORE_NULL_CHECK, mirs_[4].optimization_flags & MIR_IGNORE_NULL_CHECK);
   1119   EXPECT_EQ(MIR_IGNORE_NULL_CHECK, mirs_[5].optimization_flags & MIR_IGNORE_NULL_CHECK);
   1120 
   1121   static const bool eliminated[] = {
   1122       false, false, false, false, true, true
   1123   };
   1124   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1125   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1126     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1127     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1128   }
   1129   // Check that the sregs have been renamed correctly.
   1130   ASSERT_EQ(1, mirs_[1].ssa_rep->num_defs);
   1131   EXPECT_EQ(4, mirs_[1].ssa_rep->defs[0]);
   1132   ASSERT_EQ(1, mirs_[1].ssa_rep->num_uses);
   1133   EXPECT_EQ(0, mirs_[1].ssa_rep->uses[0]);
   1134   ASSERT_EQ(1, mirs_[2].ssa_rep->num_defs);
   1135   EXPECT_EQ(5, mirs_[2].ssa_rep->defs[0]);
   1136   ASSERT_EQ(1, mirs_[2].ssa_rep->num_uses);
   1137   EXPECT_EQ(4, mirs_[2].ssa_rep->uses[0]);
   1138   ASSERT_EQ(1, mirs_[3].ssa_rep->num_defs);
   1139   EXPECT_EQ(3, mirs_[3].ssa_rep->defs[0]);
   1140   ASSERT_EQ(1, mirs_[3].ssa_rep->num_uses);
   1141   EXPECT_EQ(5, mirs_[3].ssa_rep->uses[0]);
   1142 }
   1143 
   1144 TEST_F(GvnDeadCodeEliminationTestSimple, Simple2) {
   1145   static const IFieldDef ifields[] = {
   1146       { 0u, 1u, 0u, false, kDexMemAccessWord },
   1147   };
   1148   static const MIRDef mirs[] = {
   1149       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
   1150       DEF_CONST(3, Instruction::CONST, 1u, 1000),
   1151       DEF_IGET(3, Instruction::IGET, 2u, 0u, 0u),
   1152       DEF_BINOP(3, Instruction::ADD_INT_2ADDR, 3u, 2u, 1u),
   1153       DEF_UNOP(3, Instruction::INT_TO_FLOAT, 4u, 3u),
   1154       DEF_IGET(3, Instruction::IGET, 5u, 0u, 0u),
   1155       DEF_BINOP(3, Instruction::ADD_INT_2ADDR, 6u, 5u, 1u),
   1156   };
   1157 
   1158   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 2, 3, 2, 2 };
   1159   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1160 
   1161   PrepareIFields(ifields);
   1162   PrepareMIRs(mirs);
   1163   PerformGVN_DCE();
   1164 
   1165   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1166   static const size_t diff_indexes[] = { 0, 1, 2, 3 };
   1167   ExpectValueNamesNE(diff_indexes);
   1168   EXPECT_EQ(value_names_[2], value_names_[5]);
   1169   EXPECT_EQ(value_names_[3], value_names_[6]);
   1170 
   1171   const size_t no_null_ck_indexes[] = { 2, 5 };
   1172   ExpectNoNullCheck(no_null_ck_indexes);
   1173 
   1174   static const bool eliminated[] = {
   1175       false, false, false, false, false, true, true
   1176   };
   1177   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1178   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1179     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1180     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1181   }
   1182   // Check that the sregs have been renamed correctly.
   1183   ASSERT_EQ(1, mirs_[3].ssa_rep->num_defs);
   1184   EXPECT_EQ(6, mirs_[3].ssa_rep->defs[0]);
   1185   ASSERT_EQ(2, mirs_[3].ssa_rep->num_uses);
   1186   EXPECT_EQ(2, mirs_[3].ssa_rep->uses[0]);
   1187   EXPECT_EQ(1, mirs_[3].ssa_rep->uses[1]);
   1188   ASSERT_EQ(1, mirs_[4].ssa_rep->num_defs);
   1189   EXPECT_EQ(4, mirs_[4].ssa_rep->defs[0]);
   1190   ASSERT_EQ(1, mirs_[4].ssa_rep->num_uses);
   1191   EXPECT_EQ(6, mirs_[4].ssa_rep->uses[0]);
   1192 }
   1193 
   1194 TEST_F(GvnDeadCodeEliminationTestSimple, Simple3) {
   1195   static const IFieldDef ifields[] = {
   1196       { 0u, 1u, 0u, false, kDexMemAccessWord },
   1197   };
   1198   static const MIRDef mirs[] = {
   1199       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
   1200       DEF_CONST(3, Instruction::CONST, 1u, 1000),
   1201       DEF_CONST(3, Instruction::CONST, 2u, 2000),
   1202       DEF_CONST(3, Instruction::CONST, 3u, 3000),
   1203       DEF_IGET(3, Instruction::IGET, 4u, 0u, 0u),
   1204       DEF_BINOP(3, Instruction::ADD_INT, 5u, 4u, 1u),
   1205       DEF_BINOP(3, Instruction::MUL_INT, 6u, 5u, 2u),
   1206       DEF_BINOP(3, Instruction::SUB_INT, 7u, 6u, 3u),
   1207       DEF_UNOP(3, Instruction::INT_TO_FLOAT, 8u, 7u),
   1208       DEF_IGET(3, Instruction::IGET, 9u, 0u, 0u),
   1209       DEF_BINOP(3, Instruction::ADD_INT, 10u, 9u, 1u),
   1210       DEF_BINOP(3, Instruction::MUL_INT, 11u, 10u, 2u),  // Simple elimination of ADD+MUL
   1211       DEF_BINOP(3, Instruction::SUB_INT, 12u, 11u, 3u),  // allows simple elimination of IGET+SUB.
   1212   };
   1213 
   1214   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 3, 4, 5, 5, 4, 6, 4, 5, 5, 4 };
   1215   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1216 
   1217   PrepareIFields(ifields);
   1218   PrepareMIRs(mirs);
   1219   PerformGVN_DCE();
   1220 
   1221   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1222   static const size_t diff_indexes[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
   1223   ExpectValueNamesNE(diff_indexes);
   1224   EXPECT_EQ(value_names_[4], value_names_[9]);
   1225   EXPECT_EQ(value_names_[5], value_names_[10]);
   1226   EXPECT_EQ(value_names_[6], value_names_[11]);
   1227   EXPECT_EQ(value_names_[7], value_names_[12]);
   1228 
   1229   const size_t no_null_ck_indexes[] = { 4, 9 };
   1230   ExpectNoNullCheck(no_null_ck_indexes);
   1231 
   1232   static const bool eliminated[] = {
   1233       false, false, false, false, false, false, false, false, false, true, true, true, true
   1234   };
   1235   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1236   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1237     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1238     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1239   }
   1240   // Check that the sregs have been renamed correctly.
   1241   ASSERT_EQ(1, mirs_[6].ssa_rep->num_defs);
   1242   EXPECT_EQ(11, mirs_[6].ssa_rep->defs[0]);  // 6 -> 11
   1243   ASSERT_EQ(2, mirs_[6].ssa_rep->num_uses);
   1244   EXPECT_EQ(5, mirs_[6].ssa_rep->uses[0]);
   1245   EXPECT_EQ(2, mirs_[6].ssa_rep->uses[1]);
   1246   ASSERT_EQ(1, mirs_[7].ssa_rep->num_defs);
   1247   EXPECT_EQ(12, mirs_[7].ssa_rep->defs[0]);  // 7 -> 12
   1248   ASSERT_EQ(2, mirs_[7].ssa_rep->num_uses);
   1249   EXPECT_EQ(11, mirs_[7].ssa_rep->uses[0]);  // 6 -> 11
   1250   EXPECT_EQ(3, mirs_[7].ssa_rep->uses[1]);
   1251   ASSERT_EQ(1, mirs_[8].ssa_rep->num_defs);
   1252   EXPECT_EQ(8, mirs_[8].ssa_rep->defs[0]);
   1253   ASSERT_EQ(1, mirs_[8].ssa_rep->num_uses);
   1254   EXPECT_EQ(12, mirs_[8].ssa_rep->uses[0]);  // 7 -> 12
   1255 }
   1256 
   1257 TEST_F(GvnDeadCodeEliminationTestSimple, Simple4) {
   1258   static const IFieldDef ifields[] = {
   1259       { 0u, 1u, 0u, false, kDexMemAccessWord },
   1260   };
   1261   static const MIRDef mirs[] = {
   1262       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
   1263       DEF_CONST_WIDE(3, Instruction::CONST_WIDE, 1u, INT64_C(1)),
   1264       DEF_BINOP(3, Instruction::LONG_TO_FLOAT, 3u, 1u, 2u),
   1265       DEF_IGET(3, Instruction::IGET, 4u, 0u, 0u),
   1266       DEF_UNOP(3, Instruction::INT_TO_FLOAT, 5u, 4u),
   1267       DEF_CONST_WIDE(3, Instruction::CONST_WIDE, 6u, INT64_C(1)),
   1268       DEF_BINOP(3, Instruction::LONG_TO_FLOAT, 8u, 6u, 7u),
   1269       DEF_IGET(3, Instruction::IGET, 9u, 0u, 0u),
   1270   };
   1271 
   1272   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 1, 2, 3, 1, 2, 1, 2 };
   1273   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1274 
   1275   PrepareIFields(ifields);
   1276   PrepareMIRs(mirs);
   1277   static const int32_t wide_sregs[] = { 1, 6 };
   1278   MarkAsWideSRegs(wide_sregs);
   1279   PerformGVN_DCE();
   1280 
   1281   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1282   static const size_t diff_indexes[] = { 0, 1, 2, 3, 4 };
   1283   ExpectValueNamesNE(diff_indexes);
   1284   EXPECT_EQ(value_names_[1], value_names_[5]);
   1285   EXPECT_EQ(value_names_[2], value_names_[6]);
   1286   EXPECT_EQ(value_names_[3], value_names_[7]);
   1287 
   1288   const size_t no_null_ck_indexes[] = { 3, 7 };
   1289   ExpectNoNullCheck(no_null_ck_indexes);
   1290 
   1291   static const bool eliminated[] = {
   1292       // Simple elimination of CONST_WIDE+LONG_TO_FLOAT allows simple eliminatiion of IGET.
   1293       false, false, false, false, false, true, true, true
   1294   };
   1295   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1296   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1297     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1298     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1299   }
   1300   // Check that the sregs have been renamed correctly.
   1301   ASSERT_EQ(1, mirs_[2].ssa_rep->num_defs);
   1302   EXPECT_EQ(8, mirs_[2].ssa_rep->defs[0]);   // 3 -> 8
   1303   ASSERT_EQ(2, mirs_[2].ssa_rep->num_uses);
   1304   EXPECT_EQ(1, mirs_[2].ssa_rep->uses[0]);
   1305   EXPECT_EQ(2, mirs_[2].ssa_rep->uses[1]);
   1306   ASSERT_EQ(1, mirs_[3].ssa_rep->num_defs);
   1307   EXPECT_EQ(9, mirs_[3].ssa_rep->defs[0]);   // 4 -> 9
   1308   ASSERT_EQ(1, mirs_[3].ssa_rep->num_uses);
   1309   EXPECT_EQ(0, mirs_[3].ssa_rep->uses[0]);
   1310   ASSERT_EQ(1, mirs_[4].ssa_rep->num_defs);
   1311   EXPECT_EQ(5, mirs_[4].ssa_rep->defs[0]);
   1312   ASSERT_EQ(1, mirs_[4].ssa_rep->num_uses);
   1313   EXPECT_EQ(9, mirs_[4].ssa_rep->uses[0]);   // 4 -> 9
   1314 }
   1315 
   1316 TEST_F(GvnDeadCodeEliminationTestSimple, KillChain1) {
   1317   static const IFieldDef ifields[] = {
   1318       { 0u, 1u, 0u, false, kDexMemAccessWord },
   1319   };
   1320   static const MIRDef mirs[] = {
   1321       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
   1322       DEF_CONST(3, Instruction::CONST, 1u, 1000),
   1323       DEF_CONST(3, Instruction::CONST, 2u, 2000),
   1324       DEF_CONST(3, Instruction::CONST, 3u, 3000),
   1325       DEF_IGET(3, Instruction::IGET, 4u, 0u, 0u),
   1326       DEF_BINOP(3, Instruction::ADD_INT, 5u, 4u, 1u),
   1327       DEF_BINOP(3, Instruction::MUL_INT, 6u, 5u, 2u),
   1328       DEF_BINOP(3, Instruction::SUB_INT, 7u, 6u, 3u),
   1329       DEF_UNOP(3, Instruction::INT_TO_FLOAT, 8u, 7u),
   1330       DEF_IGET(3, Instruction::IGET, 9u, 0u, 0u),
   1331       DEF_BINOP(3, Instruction::ADD_INT, 10u, 9u, 1u),
   1332       DEF_BINOP(3, Instruction::MUL_INT, 11u, 10u, 2u),
   1333       DEF_BINOP(3, Instruction::SUB_INT, 12u, 11u, 3u),
   1334   };
   1335 
   1336   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 3, 4, 5, 4, 5, 6, 4, 5, 4, 5 };
   1337   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1338 
   1339   PrepareIFields(ifields);
   1340   PrepareMIRs(mirs);
   1341   PerformGVN_DCE();
   1342 
   1343   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1344   static const size_t diff_indexes[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
   1345   ExpectValueNamesNE(diff_indexes);
   1346   EXPECT_EQ(value_names_[4], value_names_[9]);
   1347   EXPECT_EQ(value_names_[5], value_names_[10]);
   1348   EXPECT_EQ(value_names_[6], value_names_[11]);
   1349   EXPECT_EQ(value_names_[7], value_names_[12]);
   1350 
   1351   const size_t no_null_ck_indexes[] = { 4, 9 };
   1352   ExpectNoNullCheck(no_null_ck_indexes);
   1353 
   1354   static const bool eliminated[] = {
   1355       false, false, false, false, false, false, false, false, false, true, true, true, true
   1356   };
   1357   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1358   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1359     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1360     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1361   }
   1362   // Check that the sregs have been renamed correctly.
   1363   ASSERT_EQ(1, mirs_[6].ssa_rep->num_defs);
   1364   EXPECT_EQ(11, mirs_[6].ssa_rep->defs[0]);  // 6 -> 11
   1365   ASSERT_EQ(2, mirs_[6].ssa_rep->num_uses);
   1366   EXPECT_EQ(5, mirs_[6].ssa_rep->uses[0]);
   1367   EXPECT_EQ(2, mirs_[6].ssa_rep->uses[1]);
   1368   ASSERT_EQ(1, mirs_[7].ssa_rep->num_defs);
   1369   EXPECT_EQ(12, mirs_[7].ssa_rep->defs[0]);  // 7 -> 12
   1370   ASSERT_EQ(2, mirs_[7].ssa_rep->num_uses);
   1371   EXPECT_EQ(11, mirs_[7].ssa_rep->uses[0]);  // 6 -> 11
   1372   EXPECT_EQ(3, mirs_[7].ssa_rep->uses[1]);
   1373   ASSERT_EQ(1, mirs_[8].ssa_rep->num_defs);
   1374   EXPECT_EQ(8, mirs_[8].ssa_rep->defs[0]);
   1375   ASSERT_EQ(1, mirs_[8].ssa_rep->num_uses);
   1376   EXPECT_EQ(12, mirs_[8].ssa_rep->uses[0]);   // 7 -> 12
   1377 }
   1378 
   1379 TEST_F(GvnDeadCodeEliminationTestSimple, KillChain2) {
   1380   static const IFieldDef ifields[] = {
   1381       { 0u, 1u, 0u, false, kDexMemAccessWord },
   1382   };
   1383   static const MIRDef mirs[] = {
   1384       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
   1385       DEF_CONST(3, Instruction::CONST, 1u, 1000),
   1386       DEF_CONST(3, Instruction::CONST, 2u, 2000),
   1387       DEF_CONST(3, Instruction::CONST, 3u, 3000),
   1388       DEF_IGET(3, Instruction::IGET, 4u, 0u, 0u),
   1389       DEF_BINOP(3, Instruction::ADD_INT, 5u, 4u, 1u),
   1390       DEF_BINOP(3, Instruction::MUL_INT, 6u, 5u, 2u),
   1391       DEF_BINOP(3, Instruction::SUB_INT, 7u, 6u, 3u),
   1392       DEF_UNOP(3, Instruction::INT_TO_FLOAT, 8u, 7u),
   1393       DEF_IGET(3, Instruction::IGET, 9u, 0u, 0u),
   1394       DEF_BINOP(3, Instruction::ADD_INT, 10u, 9u, 1u),
   1395       DEF_BINOP(3, Instruction::MUL_INT, 11u, 10u, 2u),
   1396       DEF_BINOP(3, Instruction::SUB_INT, 12u, 11u, 3u),
   1397       DEF_CONST(3, Instruction::CONST, 13u, 4000),
   1398   };
   1399 
   1400   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 3, 4, 5, 5, 4, 6, 4, 7, 7, 4, 7 };
   1401   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1402 
   1403   PrepareIFields(ifields);
   1404   PrepareMIRs(mirs);
   1405   PerformGVN_DCE();
   1406 
   1407   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1408   static const size_t diff_indexes[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 13 };
   1409   ExpectValueNamesNE(diff_indexes);
   1410   EXPECT_EQ(value_names_[4], value_names_[9]);
   1411   EXPECT_EQ(value_names_[5], value_names_[10]);
   1412   EXPECT_EQ(value_names_[6], value_names_[11]);
   1413   EXPECT_EQ(value_names_[7], value_names_[12]);
   1414 
   1415   const size_t no_null_ck_indexes[] = { 4, 9 };
   1416   ExpectNoNullCheck(no_null_ck_indexes);
   1417 
   1418   static const bool eliminated[] = {
   1419       false, false, false, false, false, false, false, false, false, true, true, true, true, false
   1420   };
   1421   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1422   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1423     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1424     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1425   }
   1426   // Check that the sregs have been renamed correctly.
   1427   ASSERT_EQ(1, mirs_[7].ssa_rep->num_defs);
   1428   EXPECT_EQ(12, mirs_[7].ssa_rep->defs[0]);  // 7 -> 12
   1429   ASSERT_EQ(2, mirs_[7].ssa_rep->num_uses);
   1430   EXPECT_EQ(6, mirs_[7].ssa_rep->uses[0]);
   1431   EXPECT_EQ(3, mirs_[7].ssa_rep->uses[1]);
   1432   ASSERT_EQ(1, mirs_[8].ssa_rep->num_defs);
   1433   EXPECT_EQ(8, mirs_[8].ssa_rep->defs[0]);
   1434   ASSERT_EQ(1, mirs_[8].ssa_rep->num_uses);
   1435   EXPECT_EQ(12, mirs_[8].ssa_rep->uses[0]);   // 7 -> 12
   1436 }
   1437 
   1438 TEST_F(GvnDeadCodeEliminationTestSimple, KillChain3) {
   1439   static const IFieldDef ifields[] = {
   1440       { 0u, 1u, 0u, false, kDexMemAccessWord },
   1441   };
   1442   static const MIRDef mirs[] = {
   1443       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
   1444       DEF_CONST(3, Instruction::CONST, 1u, 1000),
   1445       DEF_CONST(3, Instruction::CONST, 2u, 2000),
   1446       DEF_CONST(3, Instruction::CONST, 3u, 3000),
   1447       DEF_IGET(3, Instruction::IGET, 4u, 0u, 0u),
   1448       DEF_BINOP(3, Instruction::ADD_INT, 5u, 4u, 1u),
   1449       DEF_BINOP(3, Instruction::MUL_INT, 6u, 5u, 2u),
   1450       DEF_BINOP(3, Instruction::SUB_INT, 7u, 6u, 3u),
   1451       DEF_UNOP(3, Instruction::INT_TO_FLOAT, 8u, 7u),
   1452       DEF_IGET(3, Instruction::IGET, 9u, 0u, 0u),
   1453       DEF_BINOP(3, Instruction::ADD_INT, 10u, 9u, 1u),
   1454       DEF_BINOP(3, Instruction::MUL_INT, 11u, 10u, 2u),
   1455       DEF_CONST(3, Instruction::CONST, 12u, 4000),
   1456       DEF_BINOP(3, Instruction::SUB_INT, 13u, 11u, 3u),
   1457   };
   1458 
   1459   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 3, 4, 5, 5, 4, 6, 4, 7, 4, 7, 4 };
   1460   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1461 
   1462   PrepareIFields(ifields);
   1463   PrepareMIRs(mirs);
   1464   PerformGVN_DCE();
   1465 
   1466   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1467   static const size_t diff_indexes[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 12 };
   1468   ExpectValueNamesNE(diff_indexes);
   1469   EXPECT_EQ(value_names_[4], value_names_[9]);
   1470   EXPECT_EQ(value_names_[5], value_names_[10]);
   1471   EXPECT_EQ(value_names_[6], value_names_[11]);
   1472   EXPECT_EQ(value_names_[7], value_names_[13]);
   1473 
   1474   const size_t no_null_ck_indexes[] = { 4, 9 };
   1475   ExpectNoNullCheck(no_null_ck_indexes);
   1476 
   1477   static const bool eliminated[] = {
   1478       false, false, false, false, false, false, false, false, false, true, true, true, false, true
   1479   };
   1480   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1481   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1482     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1483     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1484   }
   1485   // Check that the sregs have been renamed correctly.
   1486   ASSERT_EQ(1, mirs_[7].ssa_rep->num_defs);
   1487   EXPECT_EQ(13, mirs_[7].ssa_rep->defs[0]);  // 7 -> 13
   1488   ASSERT_EQ(2, mirs_[7].ssa_rep->num_uses);
   1489   EXPECT_EQ(6, mirs_[7].ssa_rep->uses[0]);
   1490   EXPECT_EQ(3, mirs_[7].ssa_rep->uses[1]);
   1491   ASSERT_EQ(1, mirs_[8].ssa_rep->num_defs);
   1492   EXPECT_EQ(8, mirs_[8].ssa_rep->defs[0]);
   1493   ASSERT_EQ(1, mirs_[8].ssa_rep->num_uses);
   1494   EXPECT_EQ(13, mirs_[8].ssa_rep->uses[0]);   // 7 -> 13
   1495 }
   1496 
   1497 TEST_F(GvnDeadCodeEliminationTestSimple, KeepChain1) {
   1498   // KillChain2 without the final CONST.
   1499   static const IFieldDef ifields[] = {
   1500       { 0u, 1u, 0u, false, kDexMemAccessWord },
   1501   };
   1502   static const MIRDef mirs[] = {
   1503       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
   1504       DEF_CONST(3, Instruction::CONST, 1u, 1000),
   1505       DEF_CONST(3, Instruction::CONST, 2u, 2000),
   1506       DEF_CONST(3, Instruction::CONST, 3u, 3000),
   1507       DEF_IGET(3, Instruction::IGET, 4u, 0u, 0u),
   1508       DEF_BINOP(3, Instruction::ADD_INT, 5u, 4u, 1u),
   1509       DEF_BINOP(3, Instruction::MUL_INT, 6u, 5u, 2u),
   1510       DEF_BINOP(3, Instruction::SUB_INT, 7u, 6u, 3u),
   1511       DEF_UNOP(3, Instruction::INT_TO_FLOAT, 8u, 7u),
   1512       DEF_IGET(3, Instruction::IGET, 9u, 0u, 0u),
   1513       DEF_BINOP(3, Instruction::ADD_INT, 10u, 9u, 1u),
   1514       DEF_BINOP(3, Instruction::MUL_INT, 11u, 10u, 2u),
   1515       DEF_BINOP(3, Instruction::SUB_INT, 12u, 11u, 3u),
   1516   };
   1517 
   1518   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 3, 4, 5, 5, 4, 6, 4, 7, 7, 4 };
   1519   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1520 
   1521   PrepareIFields(ifields);
   1522   PrepareMIRs(mirs);
   1523   PerformGVN_DCE();
   1524 
   1525   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1526   static const size_t diff_indexes[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
   1527   ExpectValueNamesNE(diff_indexes);
   1528   EXPECT_EQ(value_names_[4], value_names_[9]);
   1529   EXPECT_EQ(value_names_[5], value_names_[10]);
   1530   EXPECT_EQ(value_names_[6], value_names_[11]);
   1531   EXPECT_EQ(value_names_[7], value_names_[12]);
   1532 
   1533   const size_t no_null_ck_indexes[] = { 4, 9 };
   1534   ExpectNoNullCheck(no_null_ck_indexes);
   1535 
   1536   static const bool eliminated[] = {
   1537       false, false, false, false, false, false, false, false, false, false, false, false, false
   1538   };
   1539   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1540   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1541     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1542     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1543   }
   1544 }
   1545 
   1546 TEST_F(GvnDeadCodeEliminationTestSimple, KeepChain2) {
   1547   // KillChain1 with MIRs in the middle of the chain.
   1548   static const IFieldDef ifields[] = {
   1549       { 0u, 1u, 0u, false, kDexMemAccessWord },
   1550   };
   1551   static const MIRDef mirs[] = {
   1552       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
   1553       DEF_CONST(3, Instruction::CONST, 1u, 1000),
   1554       DEF_CONST(3, Instruction::CONST, 2u, 2000),
   1555       DEF_CONST(3, Instruction::CONST, 3u, 3000),
   1556       DEF_IGET(3, Instruction::IGET, 4u, 0u, 0u),
   1557       DEF_BINOP(3, Instruction::ADD_INT, 5u, 4u, 1u),
   1558       DEF_BINOP(3, Instruction::MUL_INT, 6u, 5u, 2u),
   1559       DEF_BINOP(3, Instruction::SUB_INT, 7u, 6u, 3u),
   1560       DEF_UNOP(3, Instruction::INT_TO_FLOAT, 8u, 7u),
   1561       DEF_IGET(3, Instruction::IGET, 9u, 0u, 0u),
   1562       DEF_BINOP(3, Instruction::ADD_INT, 10u, 9u, 1u),
   1563       DEF_CONST(3, Instruction::CONST, 11u, 4000),
   1564       DEF_UNOP(3, Instruction::INT_TO_FLOAT, 12u, 11u),
   1565       DEF_BINOP(3, Instruction::MUL_INT, 13u, 10u, 2u),
   1566       DEF_BINOP(3, Instruction::SUB_INT, 14u, 13u, 3u),
   1567   };
   1568 
   1569   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 3, 4, 5, 4, 5, 6, 4, 5, 4, 7, 4, 5 };
   1570   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1571 
   1572   PrepareIFields(ifields);
   1573   PrepareMIRs(mirs);
   1574   PerformGVN_DCE();
   1575 
   1576   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1577   static const size_t diff_indexes[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
   1578   ExpectValueNamesNE(diff_indexes);
   1579   EXPECT_EQ(value_names_[4], value_names_[9]);
   1580   EXPECT_EQ(value_names_[5], value_names_[10]);
   1581   EXPECT_EQ(value_names_[6], value_names_[13]);
   1582   EXPECT_EQ(value_names_[7], value_names_[14]);
   1583 
   1584   const size_t no_null_ck_indexes[] = { 4, 9 };
   1585   ExpectNoNullCheck(no_null_ck_indexes);
   1586 
   1587   static const bool eliminated[] = {
   1588       false, false, false, false, false, false, false, false, false,
   1589       false, false, false, false, false, false
   1590   };
   1591   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1592   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1593     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1594     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1595   }
   1596 }
   1597 
   1598 TEST_F(GvnDeadCodeEliminationTestDiamond, CreatePhi1) {
   1599   static const MIRDef mirs[] = {
   1600       DEF_CONST(3, Instruction::CONST, 0u, 1000),
   1601       DEF_CONST(4, Instruction::CONST, 1u, 1000),
   1602   };
   1603 
   1604   static const int32_t sreg_to_vreg_map[] = { 0, 0 };
   1605   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1606 
   1607   PrepareMIRs(mirs);
   1608   PerformGVN_DCE();
   1609 
   1610   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1611   EXPECT_EQ(value_names_[0], value_names_[1]);
   1612 
   1613   static const bool eliminated[] = {
   1614       false, true,
   1615   };
   1616   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1617   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1618     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1619     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1620   }
   1621   // Check that we've created a single-input Phi to replace the CONST 3u.
   1622   BasicBlock* bb4 = cu_.mir_graph->GetBasicBlock(4);
   1623   MIR* phi = bb4->first_mir_insn;
   1624   ASSERT_TRUE(phi != nullptr);
   1625   ASSERT_EQ(kMirOpPhi, static_cast<int>(phi->dalvikInsn.opcode));
   1626   ASSERT_EQ(1, phi->ssa_rep->num_uses);
   1627   EXPECT_EQ(0, phi->ssa_rep->uses[0]);
   1628   ASSERT_EQ(1, phi->ssa_rep->num_defs);
   1629   EXPECT_EQ(1, phi->ssa_rep->defs[0]);
   1630   EXPECT_EQ(0u, phi->dalvikInsn.vA);
   1631 }
   1632 
   1633 TEST_F(GvnDeadCodeEliminationTestDiamond, CreatePhi2) {
   1634   static const MIRDef mirs[] = {
   1635       DEF_CONST(3, Instruction::CONST, 0u, 1000),
   1636       DEF_MOVE(4, Instruction::MOVE, 1u, 0u),
   1637       DEF_CONST(4, Instruction::CONST, 2u, 1000),
   1638   };
   1639 
   1640   static const int32_t sreg_to_vreg_map[] = { 0, 1, 0 };
   1641   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1642 
   1643   PrepareMIRs(mirs);
   1644   PerformGVN_DCE();
   1645 
   1646   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1647   EXPECT_EQ(value_names_[0], value_names_[1]);
   1648   EXPECT_EQ(value_names_[0], value_names_[2]);
   1649 
   1650   static const bool eliminated[] = {
   1651       false, false, true,
   1652   };
   1653   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1654   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1655     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1656     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1657   }
   1658   // Check that we've created a single-input Phi to replace the CONST 3u.
   1659   BasicBlock* bb4 = cu_.mir_graph->GetBasicBlock(4);
   1660   MIR* phi = bb4->first_mir_insn;
   1661   ASSERT_TRUE(phi != nullptr);
   1662   ASSERT_EQ(kMirOpPhi, static_cast<int>(phi->dalvikInsn.opcode));
   1663   ASSERT_EQ(1, phi->ssa_rep->num_uses);
   1664   EXPECT_EQ(0, phi->ssa_rep->uses[0]);
   1665   ASSERT_EQ(1, phi->ssa_rep->num_defs);
   1666   EXPECT_EQ(2, phi->ssa_rep->defs[0]);
   1667   EXPECT_EQ(0u, phi->dalvikInsn.vA);
   1668   MIR* move = phi->next;
   1669   ASSERT_TRUE(move != nullptr);
   1670   ASSERT_EQ(Instruction::MOVE, move->dalvikInsn.opcode);
   1671   ASSERT_EQ(1, move->ssa_rep->num_uses);
   1672   EXPECT_EQ(2, move->ssa_rep->uses[0]);
   1673   ASSERT_EQ(1, move->ssa_rep->num_defs);
   1674   EXPECT_EQ(1, move->ssa_rep->defs[0]);
   1675   EXPECT_EQ(1u, move->dalvikInsn.vA);
   1676   EXPECT_EQ(0u, move->dalvikInsn.vB);
   1677 }
   1678 
   1679 TEST_F(GvnDeadCodeEliminationTestDiamond, CreatePhi3) {
   1680   static const IFieldDef ifields[] = {
   1681       { 0u, 1u, 0u, false, kDexMemAccessWord },
   1682   };
   1683   static const MIRDef mirs[] = {
   1684       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
   1685       DEF_CONST(4, Instruction::CONST, 1u, 1000),
   1686       DEF_IPUT(4, Instruction::IPUT, 1u, 0u, 0u),
   1687       DEF_CONST(5, Instruction::CONST, 3u, 2000),
   1688       DEF_IPUT(5, Instruction::IPUT, 3u, 0u, 0u),
   1689       DEF_IGET(6, Instruction::IGET, 5u, 0u, 0u),
   1690   };
   1691 
   1692   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2 /* dummy */, 1, 2 /* dummy */, 1 };
   1693   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1694 
   1695   PrepareIFields(ifields);
   1696   PrepareMIRs(mirs);
   1697   PerformGVN_DCE();
   1698 
   1699   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1700   static const size_t diff_indexes[] = { 0, 1, 3, 5 };
   1701   ExpectValueNamesNE(diff_indexes);
   1702 
   1703   const size_t no_null_ck_indexes[] = { 2, 4, 5 };
   1704   ExpectNoNullCheck(no_null_ck_indexes);
   1705 
   1706   static const bool eliminated[] = {
   1707       false, false, false, false, false, true,
   1708   };
   1709   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1710   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1711     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1712     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1713   }
   1714   // Check that we've created a two-input Phi to replace the IGET 5u.
   1715   BasicBlock* bb6 = cu_.mir_graph->GetBasicBlock(6);
   1716   MIR* phi = bb6->first_mir_insn;
   1717   ASSERT_TRUE(phi != nullptr);
   1718   ASSERT_EQ(kMirOpPhi, static_cast<int>(phi->dalvikInsn.opcode));
   1719   ASSERT_EQ(2, phi->ssa_rep->num_uses);
   1720   EXPECT_EQ(1, phi->ssa_rep->uses[0]);
   1721   EXPECT_EQ(3, phi->ssa_rep->uses[1]);
   1722   ASSERT_EQ(1, phi->ssa_rep->num_defs);
   1723   EXPECT_EQ(5, phi->ssa_rep->defs[0]);
   1724   EXPECT_EQ(1u, phi->dalvikInsn.vA);
   1725 }
   1726 
   1727 TEST_F(GvnDeadCodeEliminationTestDiamond, KillChainInAnotherBlock1) {
   1728   static const IFieldDef ifields[] = {
   1729       { 0u, 1u, 0u, false, kDexMemAccessObject },  // linked list
   1730   };
   1731   static const MIRDef mirs[] = {
   1732       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
   1733       DEF_IGET(3, Instruction::IGET_OBJECT, 1u, 0u, 0u),
   1734       DEF_IGET(3, Instruction::IGET_OBJECT, 2u, 1u, 0u),
   1735       DEF_IGET(3, Instruction::IGET_OBJECT, 3u, 2u, 0u),
   1736       DEF_IGET(3, Instruction::IGET_OBJECT, 4u, 3u, 0u),
   1737       DEF_IFZ(3, Instruction::IF_NEZ, 4u),
   1738       DEF_IGET(4, Instruction::IGET_OBJECT, 6u, 0u, 0u),
   1739       DEF_IGET(4, Instruction::IGET_OBJECT, 7u, 6u, 0u),
   1740       DEF_IGET(4, Instruction::IGET_OBJECT, 8u, 7u, 0u),
   1741       DEF_IGET(4, Instruction::IGET_OBJECT, 9u, 8u, 0u),
   1742   };
   1743 
   1744   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 1, 2, 3 /* dummy */, 1, 2, 1, 2 };
   1745   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1746 
   1747   PrepareIFields(ifields);
   1748   PrepareMIRs(mirs);
   1749   PerformGVN_DCE();
   1750 
   1751   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1752   static const size_t diff_indexes[] = { 0, 1, 2, 3, 4 };
   1753   ExpectValueNamesNE(diff_indexes);
   1754   EXPECT_EQ(value_names_[1], value_names_[6]);
   1755   EXPECT_EQ(value_names_[2], value_names_[7]);
   1756   EXPECT_EQ(value_names_[3], value_names_[8]);
   1757   EXPECT_EQ(value_names_[4], value_names_[9]);
   1758 
   1759   const size_t no_null_ck_indexes[] = { 1, 6, 7, 8, 9 };
   1760   ExpectNoNullCheck(no_null_ck_indexes);
   1761 
   1762   static const bool eliminated[] = {
   1763       false, false, false, false, false, false, true, true, true, true,
   1764   };
   1765   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1766   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1767     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1768     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1769   }
   1770   // Check that we've created two single-input Phis to replace the IGET 8u and IGET 9u;
   1771   // the IGET 6u and IGET 7u were killed without a replacement.
   1772   BasicBlock* bb4 = cu_.mir_graph->GetBasicBlock(4);
   1773   MIR* phi1 = bb4->first_mir_insn;
   1774   ASSERT_TRUE(phi1 != nullptr);
   1775   ASSERT_EQ(kMirOpPhi, static_cast<int>(phi1->dalvikInsn.opcode));
   1776   MIR* phi2 = phi1->next;
   1777   ASSERT_TRUE(phi2 != nullptr);
   1778   ASSERT_EQ(kMirOpPhi, static_cast<int>(phi2->dalvikInsn.opcode));
   1779   ASSERT_TRUE(phi2->next == &mirs_[6]);
   1780   if (phi1->dalvikInsn.vA == 2u) {
   1781     std::swap(phi1, phi2);
   1782   }
   1783   ASSERT_EQ(1, phi1->ssa_rep->num_uses);
   1784   EXPECT_EQ(3, phi1->ssa_rep->uses[0]);
   1785   ASSERT_EQ(1, phi1->ssa_rep->num_defs);
   1786   EXPECT_EQ(8, phi1->ssa_rep->defs[0]);
   1787   EXPECT_EQ(1u, phi1->dalvikInsn.vA);
   1788   ASSERT_EQ(1, phi2->ssa_rep->num_uses);
   1789   EXPECT_EQ(4, phi2->ssa_rep->uses[0]);
   1790   ASSERT_EQ(1, phi2->ssa_rep->num_defs);
   1791   EXPECT_EQ(9, phi2->ssa_rep->defs[0]);
   1792   EXPECT_EQ(2u, phi2->dalvikInsn.vA);
   1793 }
   1794 
   1795 TEST_F(GvnDeadCodeEliminationTestDiamond, KillChainInAnotherBlock2) {
   1796   static const IFieldDef ifields[] = {
   1797       { 0u, 1u, 0u, false, kDexMemAccessObject },  // linked list
   1798   };
   1799   static const MIRDef mirs[] = {
   1800       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
   1801       DEF_IGET(3, Instruction::IGET_OBJECT, 1u, 0u, 0u),
   1802       DEF_IGET(3, Instruction::IGET_OBJECT, 2u, 1u, 0u),
   1803       DEF_IGET(3, Instruction::IGET_OBJECT, 3u, 2u, 0u),
   1804       DEF_IGET(3, Instruction::IGET_OBJECT, 4u, 3u, 0u),
   1805       DEF_IFZ(3, Instruction::IF_NEZ, 4u),
   1806       DEF_IGET(4, Instruction::IGET_OBJECT, 6u, 0u, 0u),
   1807       DEF_IGET(4, Instruction::IGET_OBJECT, 7u, 6u, 0u),
   1808       DEF_IGET(4, Instruction::IGET_OBJECT, 8u, 7u, 0u),
   1809       DEF_CONST(4, Instruction::CONST, 9u, 1000),
   1810   };
   1811 
   1812   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 1, 2, 3 /* dummy */, 1, 2, 1, 2 };
   1813   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1814 
   1815   PrepareIFields(ifields);
   1816   PrepareMIRs(mirs);
   1817   PerformGVN_DCE();
   1818 
   1819   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1820   static const size_t diff_indexes[] = { 0, 1, 2, 3, 4, 9 };
   1821   ExpectValueNamesNE(diff_indexes);
   1822   EXPECT_EQ(value_names_[1], value_names_[6]);
   1823   EXPECT_EQ(value_names_[2], value_names_[7]);
   1824   EXPECT_EQ(value_names_[3], value_names_[8]);
   1825 
   1826   const size_t no_null_ck_indexes[] = { 1, 6, 7, 8 };
   1827   ExpectNoNullCheck(no_null_ck_indexes);
   1828 
   1829   static const bool eliminated[] = {
   1830       false, false, false, false, false, false, true, true, true, false,
   1831   };
   1832   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1833   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1834     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1835     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1836   }
   1837   // Check that we've created a single-input Phi to replace the IGET 8u;
   1838   // the IGET 6u and IGET 7u were killed without a replacement.
   1839   BasicBlock* bb4 = cu_.mir_graph->GetBasicBlock(4);
   1840   MIR* phi = bb4->first_mir_insn;
   1841   ASSERT_TRUE(phi != nullptr);
   1842   ASSERT_EQ(kMirOpPhi, static_cast<int>(phi->dalvikInsn.opcode));
   1843   ASSERT_TRUE(phi->next == &mirs_[6]);
   1844   ASSERT_EQ(1, phi->ssa_rep->num_uses);
   1845   EXPECT_EQ(3, phi->ssa_rep->uses[0]);
   1846   ASSERT_EQ(1, phi->ssa_rep->num_defs);
   1847   EXPECT_EQ(8, phi->ssa_rep->defs[0]);
   1848   EXPECT_EQ(1u, phi->dalvikInsn.vA);
   1849 }
   1850 
   1851 TEST_F(GvnDeadCodeEliminationTestLoop, IFieldLoopVariable) {
   1852   static const IFieldDef ifields[] = {
   1853       { 0u, 1u, 0u, false, kDexMemAccessWord },
   1854   };
   1855   static const MIRDef mirs[] = {
   1856       DEF_UNIQUE_REF(3, Instruction::NEW_INSTANCE, 0u),
   1857       DEF_CONST(3, Instruction::CONST, 1u, 1),
   1858       DEF_CONST(3, Instruction::CONST, 2u, 0),
   1859       DEF_IPUT(3, Instruction::IPUT, 2u, 0u, 0u),
   1860       DEF_IGET(4, Instruction::IGET, 4u, 0u, 0u),
   1861       DEF_BINOP(4, Instruction::ADD_INT, 5u, 4u, 1u),
   1862       DEF_IPUT(4, Instruction::IPUT, 5u, 0u, 0u),
   1863   };
   1864 
   1865   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 3 /* dummy */, 2, 2 };
   1866   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1867 
   1868   PrepareIFields(ifields);
   1869   PrepareMIRs(mirs);
   1870   PerformGVN_DCE();
   1871 
   1872   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1873   static const size_t diff_indexes[] = { 0, 1, 2, 4, 5 };
   1874   ExpectValueNamesNE(diff_indexes);
   1875 
   1876   const size_t no_null_ck_indexes[] = { 3, 4, 6 };
   1877   ExpectNoNullCheck(no_null_ck_indexes);
   1878 
   1879   static const bool eliminated[] = {
   1880       false, false, false, false, true, false, false,
   1881   };
   1882   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1883   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1884     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1885     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1886   }
   1887   // Check that we've created a two-input Phi to replace the IGET 3u.
   1888   BasicBlock* bb4 = cu_.mir_graph->GetBasicBlock(4);
   1889   MIR* phi = bb4->first_mir_insn;
   1890   ASSERT_TRUE(phi != nullptr);
   1891   ASSERT_EQ(kMirOpPhi, static_cast<int>(phi->dalvikInsn.opcode));
   1892   ASSERT_TRUE(phi->next == &mirs_[4]);
   1893   ASSERT_EQ(2, phi->ssa_rep->num_uses);
   1894   EXPECT_EQ(2, phi->ssa_rep->uses[0]);
   1895   EXPECT_EQ(5, phi->ssa_rep->uses[1]);
   1896   ASSERT_EQ(1, phi->ssa_rep->num_defs);
   1897   EXPECT_EQ(4, phi->ssa_rep->defs[0]);
   1898   EXPECT_EQ(2u, phi->dalvikInsn.vA);
   1899 }
   1900 
   1901 TEST_F(GvnDeadCodeEliminationTestDiamond, LongOverlaps1) {
   1902   static const MIRDef mirs[] = {
   1903       DEF_CONST_WIDE(3, Instruction::CONST_WIDE, 0u, 1000u),
   1904       DEF_CONST_WIDE(3, Instruction::CONST_WIDE, 2u, 1000u),
   1905       DEF_MOVE_WIDE(4, Instruction::MOVE_WIDE, 4u, 0u),
   1906       DEF_MOVE_WIDE(4, Instruction::MOVE_WIDE, 6u, 2u),
   1907       DEF_MOVE_WIDE(4, Instruction::MOVE_WIDE, 8u, 4u),
   1908       DEF_MOVE_WIDE(4, Instruction::MOVE_WIDE, 10u, 6u),
   1909   };
   1910 
   1911   // The last insn should overlap the first and second.
   1912   static const int32_t sreg_to_vreg_map[] = { 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3 };
   1913   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1914 
   1915   PrepareMIRs(mirs);
   1916   static const int32_t wide_sregs[] = { 0, 2, 4, 6, 8, 10 };
   1917   MarkAsWideSRegs(wide_sregs);
   1918   PerformGVN_DCE();
   1919 
   1920   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1921   EXPECT_EQ(value_names_[0], value_names_[1]);
   1922   EXPECT_EQ(value_names_[0], value_names_[2]);
   1923   EXPECT_EQ(value_names_[0], value_names_[3]);
   1924   EXPECT_EQ(value_names_[0], value_names_[4]);
   1925 
   1926   static const bool eliminated[] = {
   1927       false, false, false, false, false, false,
   1928   };
   1929   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1930   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1931     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1932     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1933   }
   1934 }
   1935 
   1936 TEST_F(GvnDeadCodeEliminationTestSimple, LongOverlaps2) {
   1937   static const MIRDef mirs[] = {
   1938       DEF_CONST_WIDE(3, Instruction::CONST_WIDE, 0u, 1000u),
   1939       DEF_MOVE_WIDE(3, Instruction::MOVE_WIDE, 2u, 0u),
   1940       DEF_MOVE_WIDE(3, Instruction::MOVE_WIDE, 4u, 2u),
   1941   };
   1942 
   1943   // The last insn should overlap the first and second.
   1944   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 3, 1, 2 };
   1945   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1946 
   1947   PrepareMIRs(mirs);
   1948   static const int32_t wide_sregs[] = { 0, 2, 4 };
   1949   MarkAsWideSRegs(wide_sregs);
   1950   PerformGVN_DCE();
   1951 
   1952   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1953   EXPECT_EQ(value_names_[0], value_names_[1]);
   1954   EXPECT_EQ(value_names_[0], value_names_[2]);
   1955 
   1956   static const bool eliminated[] = {
   1957       false, true, true,
   1958   };
   1959   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1960   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1961     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1962     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1963   }
   1964   // Check that the CONST_WIDE registers have been correctly renamed.
   1965   MIR* const_wide = &mirs_[0];
   1966   ASSERT_EQ(2u, const_wide->ssa_rep->num_defs);
   1967   EXPECT_EQ(4, const_wide->ssa_rep->defs[0]);
   1968   EXPECT_EQ(5, const_wide->ssa_rep->defs[1]);
   1969   EXPECT_EQ(1u, const_wide->dalvikInsn.vA);
   1970 }
   1971 
   1972 TEST_F(GvnDeadCodeEliminationTestSimple, LongOverlaps3) {
   1973   static const MIRDef mirs[] = {
   1974       DEF_CONST_WIDE(3, Instruction::CONST_WIDE, 0u, 1000u),
   1975       DEF_MOVE_WIDE(3, Instruction::MOVE_WIDE, 2u, 0u),
   1976       DEF_MOVE_WIDE(3, Instruction::MOVE_WIDE, 4u, 2u),
   1977   };
   1978 
   1979   // The last insn should overlap the first and second.
   1980   static const int32_t sreg_to_vreg_map[] = { 2, 3, 0, 1, 1, 2 };
   1981   PrepareSRegToVRegMap(sreg_to_vreg_map);
   1982 
   1983   PrepareMIRs(mirs);
   1984   static const int32_t wide_sregs[] = { 0, 2, 4 };
   1985   MarkAsWideSRegs(wide_sregs);
   1986   PerformGVN_DCE();
   1987 
   1988   ASSERT_EQ(arraysize(mirs), value_names_.size());
   1989   EXPECT_EQ(value_names_[0], value_names_[1]);
   1990   EXPECT_EQ(value_names_[0], value_names_[2]);
   1991 
   1992   static const bool eliminated[] = {
   1993       false, true, true,
   1994   };
   1995   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   1996   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   1997     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   1998     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   1999   }
   2000   // Check that the CONST_WIDE registers have been correctly renamed.
   2001   MIR* const_wide = &mirs_[0];
   2002   ASSERT_EQ(2u, const_wide->ssa_rep->num_defs);
   2003   EXPECT_EQ(4, const_wide->ssa_rep->defs[0]);
   2004   EXPECT_EQ(5, const_wide->ssa_rep->defs[1]);
   2005   EXPECT_EQ(1u, const_wide->dalvikInsn.vA);
   2006 }
   2007 
   2008 TEST_F(GvnDeadCodeEliminationTestSimple, MixedOverlaps1) {
   2009   static const MIRDef mirs[] = {
   2010       DEF_CONST(3, Instruction::CONST, 0u, 1000u),
   2011       DEF_MOVE(3, Instruction::MOVE, 1u, 0u),
   2012       DEF_CONST(3, Instruction::CONST, 2u, 2000u),
   2013       { 3, Instruction::INT_TO_LONG, 0, 0u, 1, { 2u }, 2, { 3u, 4u } },
   2014       DEF_MOVE_WIDE(3, Instruction::MOVE_WIDE, 5u, 3u),
   2015       DEF_CONST(3, Instruction::CONST, 7u, 3000u),
   2016       DEF_CONST(3, Instruction::CONST, 8u, 4000u),
   2017   };
   2018 
   2019   static const int32_t sreg_to_vreg_map[] = { 1, 2, 0, 0, 1, 3, 4, 0, 1 };
   2020   PrepareSRegToVRegMap(sreg_to_vreg_map);
   2021 
   2022   PrepareMIRs(mirs);
   2023   static const int32_t wide_sregs[] = { 3, 5 };
   2024   MarkAsWideSRegs(wide_sregs);
   2025   PerformGVN_DCE();
   2026 
   2027   ASSERT_EQ(arraysize(mirs), value_names_.size());
   2028   static const size_t diff_indexes[] = { 0, 2, 3, 5, 6 };
   2029   ExpectValueNamesNE(diff_indexes);
   2030   EXPECT_EQ(value_names_[0], value_names_[1]);
   2031   EXPECT_EQ(value_names_[3], value_names_[4]);
   2032 
   2033   static const bool eliminated[] = {
   2034       false, true, false, false, true, false, false,
   2035   };
   2036   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   2037   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   2038     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   2039     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   2040   }
   2041   // Check renamed registers in CONST.
   2042   MIR* cst = &mirs_[0];
   2043   ASSERT_EQ(Instruction::CONST, cst->dalvikInsn.opcode);
   2044   ASSERT_EQ(0, cst->ssa_rep->num_uses);
   2045   ASSERT_EQ(1, cst->ssa_rep->num_defs);
   2046   EXPECT_EQ(1, cst->ssa_rep->defs[0]);
   2047   EXPECT_EQ(2u, cst->dalvikInsn.vA);
   2048   // Check renamed registers in INT_TO_LONG.
   2049   MIR* int_to_long = &mirs_[3];
   2050   ASSERT_EQ(Instruction::INT_TO_LONG, int_to_long->dalvikInsn.opcode);
   2051   ASSERT_EQ(1, int_to_long->ssa_rep->num_uses);
   2052   EXPECT_EQ(2, int_to_long->ssa_rep->uses[0]);
   2053   ASSERT_EQ(2, int_to_long->ssa_rep->num_defs);
   2054   EXPECT_EQ(5, int_to_long->ssa_rep->defs[0]);
   2055   EXPECT_EQ(6, int_to_long->ssa_rep->defs[1]);
   2056   EXPECT_EQ(3u, int_to_long->dalvikInsn.vA);
   2057   EXPECT_EQ(0u, int_to_long->dalvikInsn.vB);
   2058 }
   2059 
   2060 TEST_F(GvnDeadCodeEliminationTestSimple, UnusedRegs1) {
   2061   static const MIRDef mirs[] = {
   2062       DEF_CONST(3, Instruction::CONST, 0u, 1000u),
   2063       DEF_CONST(3, Instruction::CONST, 1u, 2000u),
   2064       DEF_BINOP(3, Instruction::ADD_INT, 2u, 1u, 0u),
   2065       DEF_CONST(3, Instruction::CONST, 3u, 1000u),            // NOT killed (b/21702651).
   2066       DEF_BINOP(3, Instruction::ADD_INT, 4u, 1u, 3u),         // Killed (RecordPass)
   2067       DEF_CONST(3, Instruction::CONST, 5u, 2000u),            // Killed with 9u (BackwardPass)
   2068       DEF_BINOP(3, Instruction::ADD_INT, 6u, 5u, 0u),         // Killed (RecordPass)
   2069       DEF_CONST(3, Instruction::CONST, 7u, 4000u),
   2070       DEF_MOVE(3, Instruction::MOVE, 8u, 0u),                 // Killed with 6u (BackwardPass)
   2071   };
   2072 
   2073   static const int32_t sreg_to_vreg_map[] = { 1, 2, 3, 0, 3, 0, 3, 4, 0 };
   2074   PrepareSRegToVRegMap(sreg_to_vreg_map);
   2075 
   2076   PrepareMIRs(mirs);
   2077   PerformGVN_DCE();
   2078 
   2079   ASSERT_EQ(arraysize(mirs), value_names_.size());
   2080   static const size_t diff_indexes[] = { 0, 1, 2, 7 };
   2081   ExpectValueNamesNE(diff_indexes);
   2082   EXPECT_EQ(value_names_[0], value_names_[3]);
   2083   EXPECT_EQ(value_names_[2], value_names_[4]);
   2084   EXPECT_EQ(value_names_[1], value_names_[5]);
   2085   EXPECT_EQ(value_names_[2], value_names_[6]);
   2086   EXPECT_EQ(value_names_[0], value_names_[8]);
   2087 
   2088   static const bool eliminated[] = {
   2089       false, false, false, false, true, true, true, false, true,
   2090   };
   2091   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   2092   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   2093     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   2094     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   2095   }
   2096 }
   2097 
   2098 TEST_F(GvnDeadCodeEliminationTestSimple, UnusedRegs2) {
   2099   static const MIRDef mirs[] = {
   2100       DEF_CONST(3, Instruction::CONST, 0u, 1000u),
   2101       DEF_CONST(3, Instruction::CONST, 1u, 2000u),
   2102       DEF_BINOP(3, Instruction::ADD_INT, 2u, 1u, 0u),
   2103       DEF_CONST(3, Instruction::CONST, 3u, 1000u),            // Killed (BackwardPass; b/21702651)
   2104       DEF_BINOP(3, Instruction::ADD_INT, 4u, 1u, 3u),         // Killed (RecordPass)
   2105       DEF_CONST_WIDE(3, Instruction::CONST_WIDE, 5u, 4000u),
   2106       { 3, Instruction::LONG_TO_INT, 0, 0u, 2, { 5u, 6u }, 1, { 7u } },
   2107       DEF_BINOP(3, Instruction::ADD_INT, 8u, 7u, 0u),
   2108       DEF_CONST_WIDE(3, Instruction::CONST_WIDE, 9u, 4000u),  // Killed with 12u (BackwardPass)
   2109       DEF_CONST(3, Instruction::CONST, 11u, 6000u),
   2110       { 3, Instruction::LONG_TO_INT, 0, 0u, 2, { 9u, 10u }, 1, { 12u } },  // Killed with 9u (BP)
   2111   };
   2112 
   2113   static const int32_t sreg_to_vreg_map[] = {
   2114       2, 3, 4, 1, 4, 5, 6 /* high word */, 0, 7, 0, 1 /* high word */, 8, 0
   2115   };
   2116   PrepareSRegToVRegMap(sreg_to_vreg_map);
   2117 
   2118   PrepareMIRs(mirs);
   2119   static const int32_t wide_sregs[] = { 5, 9 };
   2120   MarkAsWideSRegs(wide_sregs);
   2121   PerformGVN_DCE();
   2122 
   2123   ASSERT_EQ(arraysize(mirs), value_names_.size());
   2124   static const size_t diff_indexes[] = { 0, 1, 2, 5, 6, 7, 9 };
   2125   ExpectValueNamesNE(diff_indexes);
   2126   EXPECT_EQ(value_names_[0], value_names_[3]);
   2127   EXPECT_EQ(value_names_[2], value_names_[4]);
   2128   EXPECT_EQ(value_names_[5], value_names_[8]);
   2129   EXPECT_EQ(value_names_[6], value_names_[10]);
   2130 
   2131   static const bool eliminated[] = {
   2132       false, false, false, true, true, false, false, false, true, false, true,
   2133   };
   2134   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   2135   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   2136     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   2137     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   2138   }
   2139 }
   2140 
   2141 TEST_F(GvnDeadCodeEliminationTestSimple, ArrayLengthThrows) {
   2142   static const MIRDef mirs[] = {
   2143       DEF_CONST(3, Instruction::CONST, 0u, 0),              // null
   2144       DEF_UNOP(3, Instruction::ARRAY_LENGTH, 1u, 0u),       // null.length
   2145       DEF_CONST(3, Instruction::CONST, 2u, 1000u),          // Overwrite the array-length dest.
   2146   };
   2147 
   2148   static const int32_t sreg_to_vreg_map[] = { 0, 1, 1 };
   2149   PrepareSRegToVRegMap(sreg_to_vreg_map);
   2150 
   2151   PrepareMIRs(mirs);
   2152   PerformGVN_DCE();
   2153 
   2154   ASSERT_EQ(arraysize(mirs), value_names_.size());
   2155   static const size_t diff_indexes[] = { 0, 1, 2 };
   2156   ExpectValueNamesNE(diff_indexes);
   2157 
   2158   static const bool eliminated[] = {
   2159       false, false, false,
   2160   };
   2161   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   2162   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   2163     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   2164     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   2165   }
   2166 }
   2167 
   2168 TEST_F(GvnDeadCodeEliminationTestSimple, Dependancy) {
   2169   static const MIRDef mirs[] = {
   2170       DEF_MOVE(3, Instruction::MOVE, 5u, 1u),                 // move v5,v1
   2171       DEF_MOVE(3, Instruction::MOVE, 6u, 1u),                 // move v12,v1
   2172       DEF_MOVE(3, Instruction::MOVE, 7u, 0u),                 // move v13,v0
   2173       DEF_MOVE_WIDE(3, Instruction::MOVE_WIDE, 8u, 2u),       // move v0_1,v2_3
   2174       DEF_MOVE(3, Instruction::MOVE, 10u, 6u),                // move v3,v12
   2175       DEF_MOVE(3, Instruction::MOVE, 11u, 4u),                // move v2,v4
   2176       DEF_MOVE(3, Instruction::MOVE, 12u, 7u),                // move v4,v13
   2177       DEF_MOVE(3, Instruction::MOVE, 13, 11u),                // move v12,v2
   2178       DEF_MOVE(3, Instruction::MOVE, 14u, 10u),               // move v2,v3
   2179       DEF_MOVE(3, Instruction::MOVE, 15u, 5u),                // move v3,v5
   2180       DEF_MOVE(3, Instruction::MOVE, 16u, 12u),               // move v5,v4
   2181   };
   2182 
   2183   static const int32_t sreg_to_vreg_map[] = { 0, 1, 2, 3, 4, 5, 12, 13, 0, 1, 3, 2, 4, 12, 2, 3, 5 };
   2184   PrepareSRegToVRegMap(sreg_to_vreg_map);
   2185 
   2186   PrepareMIRs(mirs);
   2187   static const int32_t wide_sregs[] = { 2, 8 };
   2188   MarkAsWideSRegs(wide_sregs);
   2189   PerformGVN_DCE();
   2190 
   2191   static const bool eliminated[] = {
   2192       false, false, false, false, false, false, false, true, true, false, false,
   2193   };
   2194   static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
   2195   for (size_t i = 0; i != arraysize(eliminated); ++i) {
   2196     bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
   2197     EXPECT_EQ(eliminated[i], actually_eliminated) << i;
   2198   }
   2199 }
   2200 
   2201 }  // namespace art
   2202