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 "base/logging.h"
     18 #include "compiler_ir.h"
     19 #include "dataflow_iterator-inl.h"
     20 #include "dex_flags.h"
     21 #include "dex/mir_field_info.h"
     22 #include "dex/mir_graph.h"
     23 #include "driver/dex_compilation_unit.h"
     24 #include "gtest/gtest.h"
     25 #include "type_inference.h"
     26 #include "utils/test_dex_file_builder.h"
     27 
     28 namespace art {
     29 
     30 class TypeInferenceTest : public testing::Test {
     31  protected:
     32   struct TypeDef {
     33     const char* descriptor;
     34   };
     35 
     36   struct FieldDef {
     37     const char* class_descriptor;
     38     const char* type;
     39     const char* name;
     40   };
     41 
     42   struct MethodDef {
     43     const char* class_descriptor;
     44     const char* signature;
     45     const char* name;
     46     InvokeType type;
     47   };
     48 
     49   struct BBDef {
     50     static constexpr size_t kMaxSuccessors = 4;
     51     static constexpr size_t kMaxPredecessors = 4;
     52 
     53     BBType type;
     54     size_t num_successors;
     55     BasicBlockId successors[kMaxPredecessors];
     56     size_t num_predecessors;
     57     BasicBlockId predecessors[kMaxPredecessors];
     58   };
     59 
     60   struct MIRDef {
     61     static constexpr size_t kMaxSsaDefs = 2;
     62     static constexpr size_t kMaxSsaUses = 4;
     63 
     64     BasicBlockId bbid;
     65     Instruction::Code opcode;
     66     int64_t value;
     67     uint32_t metadata;
     68     size_t num_uses;
     69     int32_t uses[kMaxSsaUses];
     70     size_t num_defs;
     71     int32_t defs[kMaxSsaDefs];
     72   };
     73 
     74 #define DEF_SUCC0() \
     75     0u, { }
     76 #define DEF_SUCC1(s1) \
     77     1u, { s1 }
     78 #define DEF_SUCC2(s1, s2) \
     79     2u, { s1, s2 }
     80 #define DEF_SUCC3(s1, s2, s3) \
     81     3u, { s1, s2, s3 }
     82 #define DEF_SUCC4(s1, s2, s3, s4) \
     83     4u, { s1, s2, s3, s4 }
     84 #define DEF_PRED0() \
     85     0u, { }
     86 #define DEF_PRED1(p1) \
     87     1u, { p1 }
     88 #define DEF_PRED2(p1, p2) \
     89     2u, { p1, p2 }
     90 #define DEF_PRED3(p1, p2, p3) \
     91     3u, { p1, p2, p3 }
     92 #define DEF_PRED4(p1, p2, p3, p4) \
     93     4u, { p1, p2, p3, p4 }
     94 #define DEF_BB(type, succ, pred) \
     95     { type, succ, pred }
     96 
     97 #define DEF_CONST(bb, opcode, reg, value) \
     98     { bb, opcode, value, 0u, 0, { }, 1, { reg } }
     99 #define DEF_CONST_WIDE(bb, opcode, reg, value) \
    100     { bb, opcode, value, 0u, 0, { }, 2, { reg, reg + 1 } }
    101 #define DEF_CONST_STRING(bb, opcode, reg, index) \
    102     { bb, opcode, index, 0u, 0, { }, 1, { reg } }
    103 #define DEF_IGET(bb, opcode, reg, obj, field_info) \
    104     { bb, opcode, 0u, field_info, 1, { obj }, 1, { reg } }
    105 #define DEF_IGET_WIDE(bb, opcode, reg, obj, field_info) \
    106     { bb, opcode, 0u, field_info, 1, { obj }, 2, { reg, reg + 1 } }
    107 #define DEF_IPUT(bb, opcode, reg, obj, field_info) \
    108     { bb, opcode, 0u, field_info, 2, { reg, obj }, 0, { } }
    109 #define DEF_IPUT_WIDE(bb, opcode, reg, obj, field_info) \
    110     { bb, opcode, 0u, field_info, 3, { reg, reg + 1, obj }, 0, { } }
    111 #define DEF_SGET(bb, opcode, reg, field_info) \
    112     { bb, opcode, 0u, field_info, 0, { }, 1, { reg } }
    113 #define DEF_SGET_WIDE(bb, opcode, reg, field_info) \
    114     { bb, opcode, 0u, field_info, 0, { }, 2, { reg, reg + 1 } }
    115 #define DEF_SPUT(bb, opcode, reg, field_info) \
    116     { bb, opcode, 0u, field_info, 1, { reg }, 0, { } }
    117 #define DEF_SPUT_WIDE(bb, opcode, reg, field_info) \
    118     { bb, opcode, 0u, field_info, 2, { reg, reg + 1 }, 0, { } }
    119 #define DEF_AGET(bb, opcode, reg, obj, idx) \
    120     { bb, opcode, 0u, 0u, 2, { obj, idx }, 1, { reg } }
    121 #define DEF_AGET_WIDE(bb, opcode, reg, obj, idx) \
    122     { bb, opcode, 0u, 0u, 2, { obj, idx }, 2, { reg, reg + 1 } }
    123 #define DEF_APUT(bb, opcode, reg, obj, idx) \
    124     { bb, opcode, 0u, 0u, 3, { reg, obj, idx }, 0, { } }
    125 #define DEF_APUT_WIDE(bb, opcode, reg, obj, idx) \
    126     { bb, opcode, 0u, 0u, 4, { reg, reg + 1, obj, idx }, 0, { } }
    127 #define DEF_INVOKE0(bb, opcode, method_idx) \
    128     { bb, opcode, 0u, method_idx, 0, { }, 0, { } }
    129 #define DEF_INVOKE1(bb, opcode, reg, method_idx) \
    130     { bb, opcode, 0u, method_idx, 1, { reg }, 0, { } }
    131 #define DEF_INVOKE2(bb, opcode, reg1, reg2, method_idx) \
    132     { bb, opcode, 0u, method_idx, 2, { reg1, reg2 }, 0, { } }
    133 #define DEF_IFZ(bb, opcode, reg) \
    134     { bb, opcode, 0u, 0u, 1, { reg }, 0, { } }
    135 #define DEF_MOVE(bb, opcode, reg, src) \
    136     { bb, opcode, 0u, 0u, 1, { src }, 1, { reg } }
    137 #define DEF_MOVE_WIDE(bb, opcode, reg, src) \
    138     { bb, opcode, 0u, 0u, 2, { src, src + 1 }, 2, { reg, reg + 1 } }
    139 #define DEF_PHI2(bb, reg, src1, src2) \
    140     { bb, static_cast<Instruction::Code>(kMirOpPhi), 0, 0u, 2u, { src1, src2 }, 1, { reg } }
    141 #define DEF_BINOP(bb, opcode, result, src1, src2) \
    142     { bb, opcode, 0u, 0u, 2, { src1, src2 }, 1, { result } }
    143 #define DEF_UNOP(bb, opcode, result, src) DEF_MOVE(bb, opcode, result, src)
    144 #define DEF_NULOP(bb, opcode, result) DEF_CONST(bb, opcode, result, 0)
    145 #define DEF_NULOP_WIDE(bb, opcode, result) DEF_CONST_WIDE(bb, opcode, result, 0)
    146 #define DEF_CHECK_CAST(bb, opcode, reg, type) \
    147     { bb, opcode, 0, type, 1, { reg }, 0, { } }
    148 #define DEF_NEW_ARRAY(bb, opcode, reg, length, type) \
    149     { bb, opcode, 0, type, 1, { length }, 1, { reg } }
    150 
    151   void AddTypes(const TypeDef* defs, size_t count) {
    152     for (size_t i = 0; i != count; ++i) {
    153       const TypeDef* def = &defs[i];
    154       dex_file_builder_.AddType(def->descriptor);
    155     }
    156   }
    157 
    158   template <size_t count>
    159   void PrepareTypes(const TypeDef (&defs)[count]) {
    160     type_defs_ = defs;
    161     type_count_ = count;
    162     AddTypes(defs, count);
    163   }
    164 
    165   void AddFields(const FieldDef* defs, size_t count) {
    166     for (size_t i = 0; i != count; ++i) {
    167       const FieldDef* def = &defs[i];
    168       dex_file_builder_.AddField(def->class_descriptor, def->type, def->name);
    169     }
    170   }
    171 
    172   template <size_t count>
    173   void PrepareIFields(const FieldDef (&defs)[count]) {
    174     ifield_defs_ = defs;
    175     ifield_count_ = count;
    176     AddFields(defs, count);
    177   }
    178 
    179   template <size_t count>
    180   void PrepareSFields(const FieldDef (&defs)[count]) {
    181     sfield_defs_ = defs;
    182     sfield_count_ = count;
    183     AddFields(defs, count);
    184   }
    185 
    186   void AddMethods(const MethodDef* defs, size_t count) {
    187     for (size_t i = 0; i != count; ++i) {
    188       const MethodDef* def = &defs[i];
    189       dex_file_builder_.AddMethod(def->class_descriptor, def->signature, def->name);
    190     }
    191   }
    192 
    193   template <size_t count>
    194   void PrepareMethods(const MethodDef (&defs)[count]) {
    195     method_defs_ = defs;
    196     method_count_ = count;
    197     AddMethods(defs, count);
    198   }
    199 
    200   DexMemAccessType AccessTypeForDescriptor(const char* descriptor) {
    201     switch (descriptor[0]) {
    202       case 'I':
    203       case 'F':
    204         return kDexMemAccessWord;
    205       case 'J':
    206       case 'D':
    207         return kDexMemAccessWide;
    208       case '[':
    209       case 'L':
    210         return kDexMemAccessObject;
    211       case 'Z':
    212         return kDexMemAccessBoolean;
    213       case 'B':
    214         return kDexMemAccessByte;
    215       case 'C':
    216         return kDexMemAccessChar;
    217       case 'S':
    218         return kDexMemAccessShort;
    219       default:
    220         LOG(FATAL) << "Bad descriptor: " << descriptor;
    221         UNREACHABLE();
    222     }
    223   }
    224 
    225   size_t CountIns(const std::string& test_method_signature, bool is_static) {
    226     const char* sig = test_method_signature.c_str();
    227     CHECK_EQ(sig[0], '(');
    228     ++sig;
    229     size_t result = is_static ? 0u : 1u;
    230     while (*sig != ')') {
    231       result += (AccessTypeForDescriptor(sig) == kDexMemAccessWide) ? 2u : 1u;
    232       while (*sig == '[') {
    233         ++sig;
    234       }
    235       if (*sig == 'L') {
    236         do {
    237           ++sig;
    238           CHECK(*sig != '\0' && *sig != ')');
    239         } while (*sig != ';');
    240       }
    241       ++sig;
    242     }
    243     return result;
    244   }
    245 
    246   void BuildDexFile(const std::string& test_method_signature, bool is_static) {
    247     dex_file_builder_.AddMethod(kClassName, test_method_signature, kMethodName);
    248     dex_file_ = dex_file_builder_.Build(kDexLocation);
    249     cu_.dex_file = dex_file_.get();
    250     cu_.method_idx = dex_file_builder_.GetMethodIdx(kClassName, test_method_signature, kMethodName);
    251     cu_.access_flags = is_static ? kAccStatic : 0u;
    252     cu_.mir_graph->m_units_.push_back(new (cu_.mir_graph->arena_) DexCompilationUnit(
    253         &cu_, cu_.class_loader, cu_.class_linker, *cu_.dex_file, nullptr /* code_item not used */,
    254         0u /* class_def_idx not used */, 0u /* method_index not used */,
    255         cu_.access_flags, nullptr /* verified_method not used */));
    256     cu_.mir_graph->current_method_ = 0u;
    257     code_item_ = static_cast<DexFile::CodeItem*>(
    258         cu_.arena.Alloc(sizeof(DexFile::CodeItem), kArenaAllocMisc));
    259 
    260     code_item_->ins_size_ = CountIns(test_method_signature, is_static);
    261     code_item_->registers_size_ = kLocalVRs + code_item_->ins_size_;
    262     cu_.mir_graph->current_code_item_ = code_item_;
    263     cu_.mir_graph->num_ssa_regs_ = kMaxSsaRegs;
    264 
    265     cu_.mir_graph->ifield_lowering_infos_.clear();
    266     cu_.mir_graph->ifield_lowering_infos_.reserve(ifield_count_);
    267     for (size_t i = 0u; i != ifield_count_; ++i) {
    268       const FieldDef* def = &ifield_defs_[i];
    269       uint32_t field_idx =
    270           dex_file_builder_.GetFieldIdx(def->class_descriptor, def->type, def->name);
    271       MirIFieldLoweringInfo field_info(field_idx, AccessTypeForDescriptor(def->type), false);
    272       field_info.declaring_dex_file_ = cu_.dex_file;
    273       field_info.declaring_field_idx_ = field_idx;
    274       cu_.mir_graph->ifield_lowering_infos_.push_back(field_info);
    275     }
    276 
    277     cu_.mir_graph->sfield_lowering_infos_.clear();
    278     cu_.mir_graph->sfield_lowering_infos_.reserve(sfield_count_);
    279     for (size_t i = 0u; i != sfield_count_; ++i) {
    280       const FieldDef* def = &sfield_defs_[i];
    281       uint32_t field_idx =
    282           dex_file_builder_.GetFieldIdx(def->class_descriptor, def->type, def->name);
    283       MirSFieldLoweringInfo field_info(field_idx, AccessTypeForDescriptor(def->type));
    284       field_info.declaring_dex_file_ = cu_.dex_file;
    285       field_info.declaring_field_idx_ = field_idx;
    286       cu_.mir_graph->sfield_lowering_infos_.push_back(field_info);
    287     }
    288 
    289     cu_.mir_graph->method_lowering_infos_.clear();
    290     cu_.mir_graph->method_lowering_infos_.reserve(ifield_count_);
    291     for (size_t i = 0u; i != method_count_; ++i) {
    292       const MethodDef* def = &method_defs_[i];
    293       uint32_t method_idx =
    294           dex_file_builder_.GetMethodIdx(def->class_descriptor, def->signature, def->name);
    295       MirMethodLoweringInfo method_info(method_idx, def->type, false);
    296       method_info.declaring_dex_file_ = cu_.dex_file;
    297       method_info.declaring_method_idx_ = method_idx;
    298       cu_.mir_graph->method_lowering_infos_.push_back(method_info);
    299     }
    300   }
    301 
    302   void DoPrepareBasicBlocks(const BBDef* defs, size_t count) {
    303     cu_.mir_graph->block_id_map_.clear();
    304     cu_.mir_graph->block_list_.clear();
    305     ASSERT_LT(3u, count);  // null, entry, exit and at least one bytecode block.
    306     ASSERT_EQ(kNullBlock, defs[0].type);
    307     ASSERT_EQ(kEntryBlock, defs[1].type);
    308     ASSERT_EQ(kExitBlock, defs[2].type);
    309     for (size_t i = 0u; i != count; ++i) {
    310       const BBDef* def = &defs[i];
    311       BasicBlock* bb = cu_.mir_graph->CreateNewBB(def->type);
    312       if (def->num_successors <= 2) {
    313         bb->successor_block_list_type = kNotUsed;
    314         bb->fall_through = (def->num_successors >= 1) ? def->successors[0] : 0u;
    315         bb->taken = (def->num_successors >= 2) ? def->successors[1] : 0u;
    316       } else {
    317         bb->successor_block_list_type = kPackedSwitch;
    318         bb->fall_through = 0u;
    319         bb->taken = 0u;
    320         bb->successor_blocks.reserve(def->num_successors);
    321         for (size_t j = 0u; j != def->num_successors; ++j) {
    322           SuccessorBlockInfo* successor_block_info =
    323               static_cast<SuccessorBlockInfo*>(cu_.arena.Alloc(sizeof(SuccessorBlockInfo),
    324                                                                kArenaAllocSuccessor));
    325           successor_block_info->block = j;
    326           successor_block_info->key = 0u;  // Not used by class init check elimination.
    327           bb->successor_blocks.push_back(successor_block_info);
    328         }
    329       }
    330       bb->predecessors.assign(def->predecessors, def->predecessors + def->num_predecessors);
    331       if (def->type == kDalvikByteCode || def->type == kEntryBlock || def->type == kExitBlock) {
    332         bb->data_flow_info = static_cast<BasicBlockDataFlow*>(
    333             cu_.arena.Alloc(sizeof(BasicBlockDataFlow), kArenaAllocDFInfo));
    334         bb->data_flow_info->live_in_v = live_in_v_;
    335       }
    336     }
    337     ASSERT_EQ(count, cu_.mir_graph->block_list_.size());
    338     cu_.mir_graph->entry_block_ = cu_.mir_graph->block_list_[1];
    339     ASSERT_EQ(kEntryBlock, cu_.mir_graph->entry_block_->block_type);
    340     cu_.mir_graph->exit_block_ = cu_.mir_graph->block_list_[2];
    341     ASSERT_EQ(kExitBlock, cu_.mir_graph->exit_block_->block_type);
    342   }
    343 
    344   template <size_t count>
    345   void PrepareBasicBlocks(const BBDef (&defs)[count]) {
    346     DoPrepareBasicBlocks(defs, count);
    347   }
    348 
    349   void PrepareSingleBlock() {
    350     static const BBDef bbs[] = {
    351         DEF_BB(kNullBlock, DEF_SUCC0(), DEF_PRED0()),
    352         DEF_BB(kEntryBlock, DEF_SUCC1(3), DEF_PRED0()),
    353         DEF_BB(kExitBlock, DEF_SUCC0(), DEF_PRED1(3)),
    354         DEF_BB(kDalvikByteCode, DEF_SUCC1(2), DEF_PRED1(1)),
    355     };
    356     PrepareBasicBlocks(bbs);
    357   }
    358 
    359   void PrepareDiamond() {
    360     static const BBDef bbs[] = {
    361         DEF_BB(kNullBlock, DEF_SUCC0(), DEF_PRED0()),
    362         DEF_BB(kEntryBlock, DEF_SUCC1(3), DEF_PRED0()),
    363         DEF_BB(kExitBlock, DEF_SUCC0(), DEF_PRED1(6)),
    364         DEF_BB(kDalvikByteCode, DEF_SUCC2(4, 5), DEF_PRED1(1)),
    365         DEF_BB(kDalvikByteCode, DEF_SUCC1(6), DEF_PRED1(3)),
    366         DEF_BB(kDalvikByteCode, DEF_SUCC1(6), DEF_PRED1(3)),
    367         DEF_BB(kDalvikByteCode, DEF_SUCC1(2), DEF_PRED2(4, 5)),
    368     };
    369     PrepareBasicBlocks(bbs);
    370   }
    371 
    372   void PrepareLoop() {
    373     static const BBDef bbs[] = {
    374         DEF_BB(kNullBlock, DEF_SUCC0(), DEF_PRED0()),
    375         DEF_BB(kEntryBlock, DEF_SUCC1(3), DEF_PRED0()),
    376         DEF_BB(kExitBlock, DEF_SUCC0(), DEF_PRED1(5)),
    377         DEF_BB(kDalvikByteCode, DEF_SUCC1(4), DEF_PRED1(1)),
    378         DEF_BB(kDalvikByteCode, DEF_SUCC2(5, 4), DEF_PRED2(3, 4)),  // "taken" loops to self.
    379         DEF_BB(kDalvikByteCode, DEF_SUCC1(2), DEF_PRED1(4)),
    380     };
    381     PrepareBasicBlocks(bbs);
    382   }
    383 
    384   void DoPrepareMIRs(const MIRDef* defs, size_t count) {
    385     mir_count_ = count;
    386     mirs_ = cu_.arena.AllocArray<MIR>(count, kArenaAllocMIR);
    387     ssa_reps_.resize(count);
    388     for (size_t i = 0u; i != count; ++i) {
    389       const MIRDef* def = &defs[i];
    390       MIR* mir = &mirs_[i];
    391       ASSERT_LT(def->bbid, cu_.mir_graph->block_list_.size());
    392       BasicBlock* bb = cu_.mir_graph->block_list_[def->bbid];
    393       bb->AppendMIR(mir);
    394       mir->dalvikInsn.opcode = def->opcode;
    395       mir->dalvikInsn.vB = static_cast<int32_t>(def->value);
    396       mir->dalvikInsn.vB_wide = def->value;
    397       if (IsInstructionIGetOrIPut(def->opcode)) {
    398         ASSERT_LT(def->metadata, cu_.mir_graph->ifield_lowering_infos_.size());
    399         mir->meta.ifield_lowering_info = def->metadata;
    400         ASSERT_EQ(cu_.mir_graph->ifield_lowering_infos_[def->metadata].MemAccessType(),
    401                   IGetOrIPutMemAccessType(def->opcode));
    402         cu_.mir_graph->merged_df_flags_ |= DF_IFIELD;
    403       } else if (IsInstructionSGetOrSPut(def->opcode)) {
    404         ASSERT_LT(def->metadata, cu_.mir_graph->sfield_lowering_infos_.size());
    405         mir->meta.sfield_lowering_info = def->metadata;
    406         ASSERT_EQ(cu_.mir_graph->sfield_lowering_infos_[def->metadata].MemAccessType(),
    407                   SGetOrSPutMemAccessType(def->opcode));
    408         cu_.mir_graph->merged_df_flags_ |= DF_SFIELD;
    409       } else if (IsInstructionInvoke(def->opcode)) {
    410         ASSERT_LT(def->metadata, cu_.mir_graph->method_lowering_infos_.size());
    411         mir->meta.method_lowering_info = def->metadata;
    412         mir->dalvikInsn.vA = def->num_uses;
    413         cu_.mir_graph->merged_df_flags_ |= DF_FORMAT_35C;
    414       } else if (def->opcode == static_cast<Instruction::Code>(kMirOpPhi)) {
    415         mir->meta.phi_incoming =
    416             allocator_->AllocArray<BasicBlockId>(def->num_uses, kArenaAllocDFInfo);
    417         ASSERT_EQ(def->num_uses, bb->predecessors.size());
    418         std::copy(bb->predecessors.begin(), bb->predecessors.end(), mir->meta.phi_incoming);
    419       } else if (def->opcode == Instruction::CHECK_CAST) {
    420         ASSERT_LT(def->metadata, type_count_);
    421         mir->dalvikInsn.vB = dex_file_builder_.GetTypeIdx(type_defs_[def->metadata].descriptor);
    422         cu_.mir_graph->merged_df_flags_ |= DF_CHK_CAST;
    423       } else if (def->opcode == Instruction::NEW_ARRAY) {
    424         ASSERT_LT(def->metadata, type_count_);
    425         mir->dalvikInsn.vC = dex_file_builder_.GetTypeIdx(type_defs_[def->metadata].descriptor);
    426       }
    427       mir->ssa_rep = &ssa_reps_[i];
    428       mir->ssa_rep->num_uses = def->num_uses;
    429       mir->ssa_rep->uses = const_cast<int32_t*>(def->uses);  // Not modified by LVN.
    430       mir->ssa_rep->num_defs = def->num_defs;
    431       mir->ssa_rep->defs = const_cast<int32_t*>(def->defs);  // Not modified by LVN.
    432       mir->dalvikInsn.opcode = def->opcode;
    433       mir->offset = i;  // LVN uses offset only for debug output
    434       mir->optimization_flags = 0u;
    435     }
    436     code_item_->insns_size_in_code_units_ = 2u * count;
    437   }
    438 
    439   template <size_t count>
    440   void PrepareMIRs(const MIRDef (&defs)[count]) {
    441     DoPrepareMIRs(defs, count);
    442   }
    443 
    444   // BasicBlockDataFlow::vreg_to_ssa_map_exit is used only for check-casts.
    445   void AllocEndingVRegToSRegMaps() {
    446     AllNodesIterator iterator(cu_.mir_graph.get());
    447     for (BasicBlock* bb = iterator.Next(); bb != nullptr; bb = iterator.Next()) {
    448       if (bb->data_flow_info != nullptr) {
    449         if (bb->data_flow_info->vreg_to_ssa_map_exit == nullptr) {
    450           size_t num_vregs = code_item_->registers_size_;
    451           bb->data_flow_info->vreg_to_ssa_map_exit = static_cast<int32_t*>(
    452               cu_.arena.AllocArray<int32_t>(num_vregs, kArenaAllocDFInfo));
    453           std::fill_n(bb->data_flow_info->vreg_to_ssa_map_exit, num_vregs, INVALID_SREG);
    454         }
    455       }
    456     }
    457   }
    458 
    459   template <size_t count>
    460   void MapVRegToSReg(int vreg, int32_t sreg, const BasicBlockId (&bb_ids)[count]) {
    461     AllocEndingVRegToSRegMaps();
    462     for (BasicBlockId bb_id : bb_ids) {
    463       BasicBlock* bb = cu_.mir_graph->GetBasicBlock(bb_id);
    464       CHECK(bb != nullptr);
    465       CHECK(bb->data_flow_info != nullptr);
    466       CHECK(bb->data_flow_info->vreg_to_ssa_map_exit != nullptr);
    467       bb->data_flow_info->vreg_to_ssa_map_exit[vreg] = sreg;
    468     }
    469   }
    470 
    471   void PerformTypeInference() {
    472     cu_.mir_graph->SSATransformationStart();
    473     cu_.mir_graph->ComputeDFSOrders();
    474     cu_.mir_graph->ComputeDominators();
    475     cu_.mir_graph->ComputeTopologicalSortOrder();
    476     cu_.mir_graph->SSATransformationEnd();
    477     ASSERT_TRUE(type_inference_ == nullptr);
    478     type_inference_.reset(new (allocator_.get()) TypeInference(cu_.mir_graph.get(),
    479                                                                allocator_.get()));
    480     RepeatingPreOrderDfsIterator iter(cu_.mir_graph.get());
    481     bool changed = false;
    482     for (BasicBlock* bb = iter.Next(changed); bb != nullptr; bb = iter.Next(changed)) {
    483       changed = type_inference_->Apply(bb);
    484     }
    485     type_inference_->Finish();
    486   }
    487 
    488   TypeInferenceTest()
    489       : pool_(),
    490         cu_(&pool_, kRuntimeISA, nullptr, nullptr),
    491         mir_count_(0u),
    492         mirs_(nullptr),
    493         code_item_(nullptr),
    494         ssa_reps_(),
    495         allocator_(),
    496         live_in_v_(new (&cu_.arena) ArenaBitVector(&cu_.arena, kMaxSsaRegs, false, kBitMapMisc)),
    497         type_defs_(nullptr),
    498         type_count_(0u),
    499         ifield_defs_(nullptr),
    500         ifield_count_(0u),
    501         sfield_defs_(nullptr),
    502         sfield_count_(0u),
    503         method_defs_(nullptr),
    504         method_count_(0u),
    505         dex_file_builder_(),
    506         dex_file_(nullptr) {
    507     cu_.mir_graph.reset(new MIRGraph(&cu_, &cu_.arena));
    508     allocator_.reset(ScopedArenaAllocator::Create(&cu_.arena_stack));
    509     // Bind all possible sregs to live vregs for test purposes.
    510     live_in_v_->SetInitialBits(kMaxSsaRegs);
    511     cu_.mir_graph->reg_location_ = static_cast<RegLocation*>(cu_.arena.Alloc(
    512         kMaxSsaRegs * sizeof(cu_.mir_graph->reg_location_[0]), kArenaAllocRegAlloc));
    513     cu_.mir_graph->method_sreg_ = kMaxSsaRegs - 1u;
    514     cu_.mir_graph->reg_location_[cu_.mir_graph->GetMethodSReg()].location = kLocCompilerTemp;
    515     // Bind all possible sregs to live vregs for test purposes.
    516     live_in_v_->SetInitialBits(kMaxSsaRegs);
    517     cu_.mir_graph->ssa_base_vregs_.reserve(kMaxSsaRegs);
    518     cu_.mir_graph->ssa_subscripts_.reserve(kMaxSsaRegs);
    519     for (unsigned int i = 0; i < kMaxSsaRegs; i++) {
    520       cu_.mir_graph->ssa_base_vregs_.push_back(i);
    521       cu_.mir_graph->ssa_subscripts_.push_back(0);
    522     }
    523   }
    524 
    525   enum ExpectFlags : uint32_t {
    526     kExpectWide         = 0x0001u,
    527     kExpectNarrow       = 0x0002u,
    528     kExpectFp           = 0x0004u,
    529     kExpectCore         = 0x0008u,
    530     kExpectRef          = 0x0010u,
    531     kExpectArrayWide    = 0x0020u,
    532     kExpectArrayNarrow  = 0x0040u,
    533     kExpectArrayFp      = 0x0080u,
    534     kExpectArrayCore    = 0x0100u,
    535     kExpectArrayRef     = 0x0200u,
    536     kExpectNull         = 0x0400u,
    537     kExpectHigh         = 0x0800u,  // Reserved for ExpectSRegType().
    538   };
    539 
    540   struct SRegExpectation {
    541     uint32_t array_depth;
    542     uint32_t flags;
    543   };
    544 
    545   void ExpectSRegType(int s_reg, const SRegExpectation& expectation, bool check_loc = true) {
    546     uint32_t flags = expectation.flags;
    547     uint32_t array_depth = expectation.array_depth;
    548     TypeInference::Type type = type_inference_->sregs_[s_reg];
    549 
    550     if (check_loc) {
    551       RegLocation loc = cu_.mir_graph->reg_location_[s_reg];
    552       EXPECT_EQ((flags & kExpectWide) != 0u, loc.wide) << s_reg;
    553       EXPECT_EQ((flags & kExpectFp) != 0u, loc.fp) << s_reg;
    554       EXPECT_EQ((flags & kExpectCore) != 0u, loc.core) << s_reg;
    555       EXPECT_EQ((flags & kExpectRef) != 0u, loc.ref) << s_reg;
    556       EXPECT_EQ((flags & kExpectHigh) != 0u, loc.high_word) << s_reg;
    557     }
    558 
    559     EXPECT_EQ((flags & kExpectWide) != 0u, type.Wide()) << s_reg;
    560     EXPECT_EQ((flags & kExpectNarrow) != 0u, type.Narrow()) << s_reg;
    561     EXPECT_EQ((flags & kExpectFp) != 0u, type.Fp()) << s_reg;
    562     EXPECT_EQ((flags & kExpectCore) != 0u, type.Core()) << s_reg;
    563     EXPECT_EQ((flags & kExpectRef) != 0u, type.Ref()) << s_reg;
    564     EXPECT_EQ((flags & kExpectHigh) == 0u, type.LowWord()) << s_reg;
    565     EXPECT_EQ((flags & kExpectHigh) != 0u, type.HighWord()) << s_reg;
    566 
    567     if ((flags & kExpectRef) != 0u) {
    568       EXPECT_EQ((flags & kExpectNull) != 0u, !type.NonNull()) << s_reg;
    569     } else {
    570       // Null should be checked only for references.
    571       ASSERT_EQ((flags & kExpectNull), 0u);
    572     }
    573 
    574     ASSERT_EQ(array_depth, type.ArrayDepth()) << s_reg;
    575     if (array_depth != 0u) {
    576       ASSERT_NE((flags & kExpectRef), 0u);
    577       TypeInference::Type nested_type = type.NestedType();
    578       EXPECT_EQ((flags & kExpectArrayWide) != 0u, nested_type.Wide()) << s_reg;
    579       EXPECT_EQ((flags & kExpectArrayNarrow) != 0u, nested_type.Narrow()) << s_reg;
    580       EXPECT_EQ((flags & kExpectArrayFp) != 0u, nested_type.Fp()) << s_reg;
    581       EXPECT_EQ((flags & kExpectArrayCore) != 0u, nested_type.Core()) << s_reg;
    582       EXPECT_EQ((flags & kExpectArrayRef) != 0u, nested_type.Ref()) << s_reg;
    583     }
    584     if (!type.Narrow() && type.LowWord() &&
    585         (expectation.flags & (kExpectWide | kExpectNarrow | kExpectHigh)) == kExpectWide) {
    586       SRegExpectation high_expectation = { array_depth, flags | kExpectHigh };
    587       ExpectSRegType(s_reg + 1, high_expectation);
    588     }
    589   }
    590 
    591   void ExpectCore(int s_reg, bool core) {
    592     EXPECT_EQ(core, type_inference_->sregs_[s_reg].Core());
    593   }
    594 
    595   void ExpectRef(int s_reg, bool ref) {
    596     EXPECT_EQ(ref, type_inference_->sregs_[s_reg].Ref());
    597   }
    598 
    599   void ExpectArrayDepth(int s_reg, uint32_t array_depth) {
    600     EXPECT_EQ(array_depth, type_inference_->sregs_[s_reg].ArrayDepth());
    601   }
    602 
    603   static constexpr size_t kMaxSsaRegs = 16384u;
    604   static constexpr uint16_t kLocalVRs = 1000u;
    605 
    606   static constexpr const char* kDexLocation = "TypeInferenceDexFile;";
    607   static constexpr const char* kClassName = "LTypeInferenceTest;";
    608   static constexpr const char* kMethodName = "test";
    609 
    610   ArenaPool pool_;
    611   CompilationUnit cu_;
    612   size_t mir_count_;
    613   MIR* mirs_;
    614   DexFile::CodeItem* code_item_;
    615   std::vector<SSARepresentation> ssa_reps_;
    616   std::unique_ptr<ScopedArenaAllocator> allocator_;
    617   std::unique_ptr<TypeInference> type_inference_;
    618   ArenaBitVector* live_in_v_;
    619 
    620   const TypeDef* type_defs_;
    621   size_t type_count_;
    622   const FieldDef* ifield_defs_;
    623   size_t ifield_count_;
    624   const FieldDef* sfield_defs_;
    625   size_t sfield_count_;
    626   const MethodDef* method_defs_;
    627   size_t method_count_;
    628 
    629   TestDexFileBuilder dex_file_builder_;
    630   std::unique_ptr<const DexFile> dex_file_;
    631 };
    632 
    633 TEST_F(TypeInferenceTest, IGet) {
    634   static const FieldDef ifields[] = {
    635       { kClassName, "B", "byteField" },
    636       { kClassName, "C", "charField" },
    637       { kClassName, "D", "doubleField" },
    638       { kClassName, "F", "floatField" },
    639       { kClassName, "I", "intField" },
    640       { kClassName, "J", "longField" },
    641       { kClassName, "S", "shortField" },
    642       { kClassName, "Z", "booleanField" },
    643       { kClassName, "Ljava/lang/Object;", "objectField" },
    644       { kClassName, "[Ljava/lang/Object;", "objectArrayField" },
    645   };
    646   constexpr uint32_t thiz = kLocalVRs;
    647   static const MIRDef mirs[] = {
    648       DEF_IGET(3u, Instruction::IGET_BYTE, 0u, thiz, 0u),
    649       DEF_IGET(3u, Instruction::IGET_CHAR, 1u, thiz, 1u),
    650       DEF_IGET_WIDE(3u, Instruction::IGET_WIDE, 2u, thiz, 2u),
    651       DEF_IGET(3u, Instruction::IGET, 4u, thiz, 3u),
    652       DEF_IGET(3u, Instruction::IGET, 5u, thiz, 4u),
    653       DEF_IGET_WIDE(3u, Instruction::IGET_WIDE, 6u, thiz, 5u),
    654       DEF_IGET(3u, Instruction::IGET_SHORT, 8u, thiz, 6u),
    655       DEF_IGET(3u, Instruction::IGET_BOOLEAN, 9u, thiz, 7u),
    656       DEF_IGET(3u, Instruction::IGET_OBJECT, 10u, thiz, 8u),
    657       DEF_IGET(3u, Instruction::IGET_OBJECT, 11u, thiz, 9u),
    658   };
    659 
    660   PrepareIFields(ifields);
    661   BuildDexFile("()V", false);
    662   PrepareSingleBlock();
    663   PrepareMIRs(mirs);
    664   PerformTypeInference();
    665 
    666   ASSERT_EQ(arraysize(mirs), mir_count_);
    667   static const SRegExpectation expectations[] = {
    668       { 0u, kExpectCore | kExpectNarrow },
    669       { 0u, kExpectCore | kExpectNarrow },
    670       { 0u, kExpectFp | kExpectWide },
    671       { 0u, kExpectFp | kExpectNarrow },
    672       { 0u, kExpectCore | kExpectNarrow },
    673       { 0u, kExpectCore | kExpectWide },
    674       { 0u, kExpectCore | kExpectNarrow },
    675       { 0u, kExpectCore | kExpectNarrow },
    676       { 0u, kExpectRef | kExpectNarrow },
    677       { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow },
    678   };
    679   static_assert(arraysize(expectations) == arraysize(mirs), "array size mismatch");
    680   for (size_t i = 0; i != arraysize(expectations); ++i) {
    681     EXPECT_EQ(mirs[i].opcode, mirs_[i].dalvikInsn.opcode);
    682     ASSERT_LE(1u, mirs_[i].ssa_rep->num_defs);
    683     ExpectSRegType(mirs_[i].ssa_rep->defs[0], expectations[i]);
    684   }
    685   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
    686   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
    687 }
    688 
    689 TEST_F(TypeInferenceTest, SGet) {
    690   static const FieldDef sfields[] = {
    691       { kClassName, "B", "staticByteField" },
    692       { kClassName, "C", "staticCharField" },
    693       { kClassName, "D", "staticDoubleField" },
    694       { kClassName, "F", "staticFloatField" },
    695       { kClassName, "I", "staticIntField" },
    696       { kClassName, "J", "staticLongField" },
    697       { kClassName, "S", "staticShortField" },
    698       { kClassName, "Z", "staticBooleanField" },
    699       { kClassName, "Ljava/lang/Object;", "staticObjectField" },
    700       { kClassName, "[Ljava/lang/Object;", "staticObjectArrayField" },
    701   };
    702   static const MIRDef mirs[] = {
    703       DEF_SGET(3u, Instruction::SGET_BYTE, 0u, 0u),
    704       DEF_SGET(3u, Instruction::SGET_CHAR, 1u, 1u),
    705       DEF_SGET_WIDE(3u, Instruction::SGET_WIDE, 2u, 2u),
    706       DEF_SGET(3u, Instruction::SGET, 4u, 3u),
    707       DEF_SGET(3u, Instruction::SGET, 5u, 4u),
    708       DEF_SGET_WIDE(3u, Instruction::SGET_WIDE, 6u, 5u),
    709       DEF_SGET(3u, Instruction::SGET_SHORT, 8u, 6u),
    710       DEF_SGET(3u, Instruction::SGET_BOOLEAN, 9u, 7u),
    711       DEF_SGET(3u, Instruction::SGET_OBJECT, 10u, 8u),
    712       DEF_SGET(3u, Instruction::SGET_OBJECT, 11u, 9u),
    713   };
    714 
    715   PrepareSFields(sfields);
    716   BuildDexFile("()V", true);
    717   PrepareSingleBlock();
    718   PrepareMIRs(mirs);
    719   PerformTypeInference();
    720 
    721   ASSERT_EQ(arraysize(mirs), mir_count_);
    722   static const SRegExpectation expectations[] = {
    723       { 0u, kExpectCore | kExpectNarrow },
    724       { 0u, kExpectCore | kExpectNarrow },
    725       { 0u, kExpectFp | kExpectWide },
    726       { 0u, kExpectFp | kExpectNarrow },
    727       { 0u, kExpectCore | kExpectNarrow },
    728       { 0u, kExpectCore | kExpectWide },
    729       { 0u, kExpectCore | kExpectNarrow },
    730       { 0u, kExpectCore | kExpectNarrow },
    731       { 0u, kExpectRef | kExpectNarrow },
    732       { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow },
    733   };
    734   static_assert(arraysize(expectations) == arraysize(mirs), "array size mismatch");
    735   for (size_t i = 0; i != arraysize(expectations); ++i) {
    736     EXPECT_EQ(mirs[i].opcode, mirs_[i].dalvikInsn.opcode);
    737     ASSERT_LE(1u, mirs_[i].ssa_rep->num_defs);
    738     ExpectSRegType(mirs_[i].ssa_rep->defs[0], expectations[i]);
    739   }
    740   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
    741   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
    742 }
    743 
    744 TEST_F(TypeInferenceTest, IPut) {
    745   static const FieldDef ifields[] = {
    746       { kClassName, "B", "byteField" },
    747       { kClassName, "C", "charField" },
    748       { kClassName, "D", "doubleField" },
    749       { kClassName, "F", "floatField" },
    750       { kClassName, "I", "intField" },
    751       { kClassName, "J", "longField" },
    752       { kClassName, "S", "shortField" },
    753       { kClassName, "Z", "booleanField" },
    754       { kClassName, "Ljava/lang/Object;", "objectField" },
    755       { kClassName, "[Ljava/lang/Object;", "objectArrayField" },
    756   };
    757   constexpr uint32_t thiz = kLocalVRs;
    758   static const MIRDef mirs[] = {
    759       DEF_CONST(3u, Instruction::CONST, 0u, 0),
    760       DEF_IPUT(3u, Instruction::IPUT_BYTE, 0u, thiz, 0u),
    761       DEF_CONST(3u, Instruction::CONST, 1u, 0),
    762       DEF_IPUT(3u, Instruction::IPUT_CHAR, 1u, thiz, 1u),
    763       DEF_CONST_WIDE(3u, Instruction::CONST_WIDE, 2u, 0),
    764       DEF_IPUT_WIDE(3u, Instruction::IPUT_WIDE, 2u, thiz, 2u),
    765       DEF_CONST(3u, Instruction::CONST, 4u, 0),
    766       DEF_IPUT(3u, Instruction::IPUT, 4u, thiz, 3u),
    767       DEF_CONST(3u, Instruction::CONST, 5u, 0),
    768       DEF_IPUT(3u, Instruction::IPUT, 5u, thiz, 4u),
    769       DEF_CONST_WIDE(3u, Instruction::CONST_WIDE, 6u, 0),
    770       DEF_IPUT_WIDE(3u, Instruction::IPUT_WIDE, 6u, thiz, 5u),
    771       DEF_CONST(3u, Instruction::CONST, 8u, 0),
    772       DEF_IPUT(3u, Instruction::IPUT_SHORT, 8u, thiz, 6u),
    773       DEF_CONST(3u, Instruction::CONST, 9u, 0),
    774       DEF_IPUT(3u, Instruction::IPUT_BOOLEAN, 9u, thiz, 7u),
    775       DEF_CONST(3u, Instruction::CONST, 10u, 0),
    776       DEF_IPUT(3u, Instruction::IPUT_OBJECT, 10u, thiz, 8u),
    777       DEF_CONST(3u, Instruction::CONST, 11u, 0),
    778       DEF_IPUT(3u, Instruction::IPUT_OBJECT, 11u, thiz, 9u),
    779   };
    780 
    781   PrepareIFields(ifields);
    782   BuildDexFile("()V", false);
    783   PrepareSingleBlock();
    784   PrepareMIRs(mirs);
    785   PerformTypeInference();
    786 
    787   ASSERT_EQ(arraysize(mirs), mir_count_);
    788   static const SRegExpectation expectations[] = {
    789       // One expectation for every 2 MIRs.
    790       { 0u, kExpectCore | kExpectNarrow },
    791       { 0u, kExpectCore | kExpectNarrow },
    792       { 0u, kExpectFp | kExpectWide },
    793       { 0u, kExpectFp | kExpectNarrow },
    794       { 0u, kExpectCore | kExpectNarrow },
    795       { 0u, kExpectCore | kExpectWide },
    796       { 0u, kExpectCore | kExpectNarrow },
    797       { 0u, kExpectCore | kExpectNarrow },
    798       { 0u, kExpectRef | kExpectNarrow | kExpectNull },
    799       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow },
    800   };
    801   static_assert(2 * arraysize(expectations) == arraysize(mirs), "array size mismatch");
    802   for (size_t i = 0; i != arraysize(expectations); ++i) {
    803     EXPECT_EQ(mirs[2 * i].opcode, mirs_[2 * i].dalvikInsn.opcode);
    804     EXPECT_EQ(mirs[2 * i + 1].opcode, mirs_[2 * i + 1].dalvikInsn.opcode);
    805     ASSERT_LE(1u, mirs_[2 * i].ssa_rep->num_defs);
    806     ExpectSRegType(mirs_[2 * i].ssa_rep->defs[0], expectations[i]);
    807   }
    808   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
    809   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
    810 }
    811 
    812 TEST_F(TypeInferenceTest, SPut) {
    813   static const FieldDef sfields[] = {
    814       { kClassName, "B", "staticByteField" },
    815       { kClassName, "C", "staticCharField" },
    816       { kClassName, "D", "staticDoubleField" },
    817       { kClassName, "F", "staticFloatField" },
    818       { kClassName, "I", "staticIntField" },
    819       { kClassName, "J", "staticLongField" },
    820       { kClassName, "S", "staticShortField" },
    821       { kClassName, "Z", "staticBooleanField" },
    822       { kClassName, "Ljava/lang/Object;", "staticObjectField" },
    823       { kClassName, "[Ljava/lang/Object;", "staticObjectArrayField" },
    824   };
    825   static const MIRDef mirs[] = {
    826       DEF_CONST(3u, Instruction::CONST, 0u, 0),
    827       DEF_SPUT(3u, Instruction::SPUT_BYTE, 0u, 0u),
    828       DEF_CONST(3u, Instruction::CONST, 1u, 0),
    829       DEF_SPUT(3u, Instruction::SPUT_CHAR, 1u, 1u),
    830       DEF_CONST_WIDE(3u, Instruction::CONST_WIDE, 2u, 0),
    831       DEF_SPUT_WIDE(3u, Instruction::SPUT_WIDE, 2u, 2u),
    832       DEF_CONST(3u, Instruction::CONST, 4u, 0),
    833       DEF_SPUT(3u, Instruction::SPUT, 4u, 3u),
    834       DEF_CONST(3u, Instruction::CONST, 5u, 0),
    835       DEF_SPUT(3u, Instruction::SPUT, 5u, 4u),
    836       DEF_CONST_WIDE(3u, Instruction::CONST_WIDE, 6u, 0),
    837       DEF_SPUT_WIDE(3u, Instruction::SPUT_WIDE, 6u, 5u),
    838       DEF_CONST(3u, Instruction::CONST, 8u, 0),
    839       DEF_SPUT(3u, Instruction::SPUT_SHORT, 8u, 6u),
    840       DEF_CONST(3u, Instruction::CONST, 9u, 0),
    841       DEF_SPUT(3u, Instruction::SPUT_BOOLEAN, 9u, 7u),
    842       DEF_CONST(3u, Instruction::CONST, 10u, 0),
    843       DEF_SPUT(3u, Instruction::SPUT_OBJECT, 10u, 8u),
    844       DEF_CONST(3u, Instruction::CONST, 11u, 0),
    845       DEF_SPUT(3u, Instruction::SPUT_OBJECT, 11u, 9u),
    846   };
    847 
    848   PrepareSFields(sfields);
    849   BuildDexFile("()V", true);
    850   PrepareSingleBlock();
    851   PrepareMIRs(mirs);
    852   PerformTypeInference();
    853 
    854   ASSERT_EQ(arraysize(mirs), mir_count_);
    855   static const SRegExpectation expectations[] = {
    856       // One expectation for every 2 MIRs.
    857       { 0u, kExpectCore | kExpectNarrow },
    858       { 0u, kExpectCore | kExpectNarrow },
    859       { 0u, kExpectFp | kExpectWide },
    860       { 0u, kExpectFp | kExpectNarrow },
    861       { 0u, kExpectCore | kExpectNarrow },
    862       { 0u, kExpectCore | kExpectWide },
    863       { 0u, kExpectCore | kExpectNarrow },
    864       { 0u, kExpectCore | kExpectNarrow },
    865       { 0u, kExpectRef | kExpectNarrow | kExpectNull },
    866       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow },
    867   };
    868   static_assert(2 * arraysize(expectations) == arraysize(mirs), "array size mismatch");
    869   for (size_t i = 0; i != arraysize(expectations); ++i) {
    870     EXPECT_EQ(mirs[2 * i].opcode, mirs_[2 * i].dalvikInsn.opcode);
    871     EXPECT_EQ(mirs[2 * i + 1].opcode, mirs_[2 * i + 1].dalvikInsn.opcode);
    872     ASSERT_LE(1u, mirs_[2 * i].ssa_rep->num_defs);
    873     ExpectSRegType(mirs_[2 * i].ssa_rep->defs[0], expectations[i]);
    874   }
    875   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
    876   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
    877 }
    878 
    879 TEST_F(TypeInferenceTest, MethodReturnType) {
    880   static const MethodDef methods[] = {
    881       { kClassName, "()B", "byteFoo", kStatic },
    882       { kClassName, "()C", "charFoo", kStatic },
    883       { kClassName, "()D", "doubleFoo", kStatic },
    884       { kClassName, "()F", "floatFoo", kStatic },
    885       { kClassName, "()I", "intFoo", kStatic },
    886       { kClassName, "()J", "longFoo", kStatic },
    887       { kClassName, "()S", "shortFoo", kStatic },
    888       { kClassName, "()Z", "booleanFoo", kStatic },
    889       { kClassName, "()Ljava/lang/Object;", "objectFoo", kStatic },
    890       { kClassName, "()[Ljava/lang/Object;", "objectArrayFoo", kStatic },
    891   };
    892   static const MIRDef mirs[] = {
    893       DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 0u),
    894       DEF_NULOP(3u, Instruction::MOVE_RESULT, 0u),
    895       DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 1u),
    896       DEF_NULOP(3u, Instruction::MOVE_RESULT, 1u),
    897       DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 2u),
    898       DEF_NULOP_WIDE(3u, Instruction::MOVE_RESULT_WIDE, 2u),
    899       DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 3u),
    900       DEF_NULOP(3u, Instruction::MOVE_RESULT, 4u),
    901       DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 4u),
    902       DEF_NULOP(3u, Instruction::MOVE_RESULT, 5u),
    903       DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 5u),
    904       DEF_NULOP_WIDE(3u, Instruction::MOVE_RESULT_WIDE, 6u),
    905       DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 6u),
    906       DEF_NULOP(3u, Instruction::MOVE_RESULT, 8u),
    907       DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 7u),
    908       DEF_NULOP(3u, Instruction::MOVE_RESULT, 9u),
    909       DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 8u),
    910       DEF_NULOP(3u, Instruction::MOVE_RESULT_OBJECT, 10u),
    911       DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 9u),
    912       DEF_NULOP(3u, Instruction::MOVE_RESULT_OBJECT, 11u),
    913   };
    914 
    915   PrepareMethods(methods);
    916   BuildDexFile("()V", true);
    917   PrepareSingleBlock();
    918   PrepareMIRs(mirs);
    919   PerformTypeInference();
    920 
    921   ASSERT_EQ(arraysize(mirs), mir_count_);
    922   static const SRegExpectation expectations[] = {
    923       // One expectation for every 2 MIRs.
    924       { 0u, kExpectCore | kExpectNarrow },
    925       { 0u, kExpectCore | kExpectNarrow },
    926       { 0u, kExpectFp | kExpectWide },
    927       { 0u, kExpectFp | kExpectNarrow },
    928       { 0u, kExpectCore | kExpectNarrow },
    929       { 0u, kExpectCore | kExpectWide },
    930       { 0u, kExpectCore | kExpectNarrow },
    931       { 0u, kExpectCore | kExpectNarrow },
    932       { 0u, kExpectRef | kExpectNarrow },
    933       { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow },
    934   };
    935   static_assert(2 * arraysize(expectations) == arraysize(mirs), "array size mismatch");
    936   for (size_t i = 0; i != arraysize(expectations); ++i) {
    937     EXPECT_EQ(mirs[2 * i].opcode, mirs_[2 * i].dalvikInsn.opcode);
    938     EXPECT_EQ(mirs[2 * i + 1].opcode, mirs_[2 * i + 1].dalvikInsn.opcode);
    939     ASSERT_LE(1u, mirs_[2 * i + 1].ssa_rep->num_defs);
    940     ExpectSRegType(mirs_[2 * i + 1].ssa_rep->defs[0], expectations[i]);
    941   }
    942   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
    943   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
    944 }
    945 
    946 TEST_F(TypeInferenceTest, MethodArgType) {
    947   static const MethodDef methods[] = {
    948       { kClassName, "(B)V", "fooByte", kStatic },
    949       { kClassName, "(C)V", "fooChar", kStatic },
    950       { kClassName, "(D)V", "fooDouble", kStatic },
    951       { kClassName, "(F)V", "fooFloat", kStatic },
    952       { kClassName, "(I)V", "fooInt", kStatic },
    953       { kClassName, "(J)V", "fooLong", kStatic },
    954       { kClassName, "(S)V", "fooShort", kStatic },
    955       { kClassName, "(Z)V", "fooBoolean", kStatic },
    956       { kClassName, "(Ljava/lang/Object;)V", "fooObject", kStatic },
    957       { kClassName, "([Ljava/lang/Object;)V", "fooObjectArray", kStatic },
    958   };
    959   static const MIRDef mirs[] = {
    960       DEF_CONST(3u, Instruction::CONST, 0u, 0),
    961       DEF_INVOKE1(3u, Instruction::INVOKE_STATIC, 0u, 0u),
    962       DEF_CONST(3u, Instruction::CONST, 1u, 0),
    963       DEF_INVOKE1(3u, Instruction::INVOKE_STATIC, 1u, 1u),
    964       DEF_CONST_WIDE(3u, Instruction::CONST_WIDE, 2u, 0),
    965       DEF_INVOKE2(3u, Instruction::INVOKE_STATIC, 2u, 3u, 2u),
    966       DEF_CONST(3u, Instruction::CONST, 4u, 0),
    967       DEF_INVOKE1(3u, Instruction::INVOKE_STATIC, 4u, 3u),
    968       DEF_CONST(3u, Instruction::CONST, 5u, 0),
    969       DEF_INVOKE1(3u, Instruction::INVOKE_STATIC, 5u, 4u),
    970       DEF_CONST_WIDE(3u, Instruction::CONST_WIDE, 6u, 0),
    971       DEF_INVOKE2(3u, Instruction::INVOKE_STATIC, 6u, 7u, 5u),
    972       DEF_CONST(3u, Instruction::CONST, 8u, 0),
    973       DEF_INVOKE1(3u, Instruction::INVOKE_STATIC, 8u, 6u),
    974       DEF_CONST(3u, Instruction::CONST, 9u, 0),
    975       DEF_INVOKE1(3u, Instruction::INVOKE_STATIC, 9u, 7u),
    976       DEF_CONST(3u, Instruction::CONST, 10u, 0),
    977       DEF_INVOKE1(3u, Instruction::INVOKE_STATIC, 10u, 8u),
    978       DEF_CONST(3u, Instruction::CONST, 11u, 0),
    979       DEF_INVOKE1(3u, Instruction::INVOKE_STATIC, 11u, 9u),
    980   };
    981 
    982   PrepareMethods(methods);
    983   BuildDexFile("()V", true);
    984   PrepareSingleBlock();
    985   PrepareMIRs(mirs);
    986   PerformTypeInference();
    987 
    988   ASSERT_EQ(arraysize(mirs), mir_count_);
    989   static const SRegExpectation expectations[] = {
    990       // One expectation for every 2 MIRs.
    991       { 0u, kExpectCore | kExpectNarrow },
    992       { 0u, kExpectCore | kExpectNarrow },
    993       { 0u, kExpectFp | kExpectWide },
    994       { 0u, kExpectFp | kExpectNarrow },
    995       { 0u, kExpectCore | kExpectNarrow },
    996       { 0u, kExpectCore | kExpectWide },
    997       { 0u, kExpectCore | kExpectNarrow },
    998       { 0u, kExpectCore | kExpectNarrow },
    999       { 0u, kExpectRef | kExpectNarrow | kExpectNull },
   1000       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow },
   1001   };
   1002   static_assert(2 * arraysize(expectations) == arraysize(mirs), "array size mismatch");
   1003   for (size_t i = 0; i != arraysize(expectations); ++i) {
   1004     EXPECT_EQ(mirs[2 * i].opcode, mirs_[2 * i].dalvikInsn.opcode);
   1005     EXPECT_EQ(mirs[2 * i + 1].opcode, mirs_[2 * i + 1].dalvikInsn.opcode);
   1006     ASSERT_LE(1u, mirs_[2 * i].ssa_rep->num_defs);
   1007     ExpectSRegType(mirs_[2 * i].ssa_rep->defs[0], expectations[i]);
   1008   }
   1009   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1010   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1011 }
   1012 
   1013 TEST_F(TypeInferenceTest, APut1) {
   1014   static const MIRDef mirs[] = {
   1015       DEF_CONST(3u, Instruction::CONST, 0u, 0),  // Object[] array
   1016       DEF_CONST(3u, Instruction::CONST, 1u, 0),  // value; can't even determine whether core or fp.
   1017       DEF_CONST(3u, Instruction::CONST, 2u, 0),  // index
   1018       DEF_APUT(3u, Instruction::APUT, 1u, 0u, 2u),
   1019   };
   1020 
   1021   BuildDexFile("()V", true);
   1022   PrepareSingleBlock();
   1023   PrepareMIRs(mirs);
   1024   PerformTypeInference();
   1025 
   1026   ASSERT_EQ(arraysize(mirs), mir_count_);
   1027   static const SRegExpectation expectations[] = {
   1028       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayNarrow },
   1029       { 0u, kExpectNarrow },
   1030       { 0u, kExpectCore | kExpectNarrow },
   1031   };
   1032   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1033     ExpectSRegType(sreg, expectations[sreg]);
   1034   }
   1035   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1036   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1037 }
   1038 
   1039 TEST_F(TypeInferenceTest, APut2) {
   1040   static const MIRDef mirs[] = {
   1041       DEF_CONST(3u, Instruction::CONST, 0u, 0),  // Object[] array
   1042       DEF_CONST(3u, Instruction::CONST, 1u, 0),  // Object[] value
   1043       DEF_CONST(3u, Instruction::CONST, 2u, 0),  // index
   1044       DEF_APUT(3u, Instruction::APUT_OBJECT, 1u, 0u, 2u),
   1045   };
   1046 
   1047   BuildDexFile("()V", true);
   1048   PrepareSingleBlock();
   1049   PrepareMIRs(mirs);
   1050   PerformTypeInference();
   1051 
   1052   ASSERT_EQ(arraysize(mirs), mir_count_);
   1053   static const SRegExpectation expectations[] = {
   1054       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow },
   1055       { 0u, kExpectRef | kExpectNarrow | kExpectNull },
   1056       { 0u, kExpectCore | kExpectNarrow },
   1057   };
   1058   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1059     ExpectSRegType(sreg, expectations[sreg]);
   1060   }
   1061   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1062   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1063 }
   1064 
   1065 TEST_F(TypeInferenceTest, APut3) {
   1066   static const MIRDef mirs[] = {
   1067       // Either array1 or array2 could be Object[][] but there is no way to tell from the bytecode.
   1068       DEF_CONST(3u, Instruction::CONST, 0u, 0),  // Object[] array1
   1069       DEF_CONST(3u, Instruction::CONST, 1u, 0),  // Object[] array2
   1070       DEF_CONST(3u, Instruction::CONST, 2u, 0),  // index
   1071       DEF_APUT(3u, Instruction::APUT_OBJECT, 0u, 1u, 2u),
   1072       DEF_APUT(3u, Instruction::APUT_OBJECT, 1u, 0u, 2u),
   1073   };
   1074 
   1075   BuildDexFile("()V", true);
   1076   PrepareSingleBlock();
   1077   PrepareMIRs(mirs);
   1078   PerformTypeInference();
   1079 
   1080   ASSERT_EQ(arraysize(mirs), mir_count_);
   1081   static const SRegExpectation expectations[] = {
   1082       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow },
   1083       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow },
   1084       { 0u, kExpectCore | kExpectNarrow },
   1085   };
   1086   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1087     ExpectSRegType(sreg, expectations[sreg]);
   1088   }
   1089   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1090   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1091 }
   1092 
   1093 TEST_F(TypeInferenceTest, APut4) {
   1094   static const MIRDef mirs[] = {
   1095       DEF_CONST(3u, Instruction::CONST, 0u, 0),
   1096       DEF_CONST(3u, Instruction::CONST, 1u, 0),  // index
   1097       DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u),  // Object[] array
   1098       DEF_CONST(3u, Instruction::CONST, 3u, 0),  // value; can't even determine whether core or fp.
   1099       DEF_APUT(3u, Instruction::APUT, 3u, 2u, 1u),
   1100   };
   1101 
   1102   BuildDexFile("()V", true);
   1103   PrepareSingleBlock();
   1104   PrepareMIRs(mirs);
   1105   PerformTypeInference();
   1106 
   1107   ASSERT_EQ(arraysize(mirs), mir_count_);
   1108   static const SRegExpectation expectations[] = {
   1109       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow },
   1110       { 0u, kExpectCore | kExpectNarrow },
   1111       { 1u, kExpectRef | kExpectNarrow | kExpectArrayNarrow },
   1112       { 0u, kExpectNarrow },
   1113   };
   1114   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1115     ExpectSRegType(sreg, expectations[sreg]);
   1116   }
   1117   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1118   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1119 }
   1120 
   1121 TEST_F(TypeInferenceTest, APut5) {
   1122   static const MIRDef mirs[] = {
   1123       DEF_CONST(3u, Instruction::CONST, 0u, 0),
   1124       DEF_CONST(3u, Instruction::CONST, 1u, 0),  // index
   1125       DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u),  // Object[] array
   1126       DEF_CONST(3u, Instruction::CONST, 3u, 0),  // Object[] value
   1127       DEF_APUT(3u, Instruction::APUT_OBJECT, 3u, 2u, 1u),
   1128   };
   1129 
   1130   BuildDexFile("()V", true);
   1131   PrepareSingleBlock();
   1132   PrepareMIRs(mirs);
   1133   PerformTypeInference();
   1134 
   1135   ASSERT_EQ(arraysize(mirs), mir_count_);
   1136   static const SRegExpectation expectations[] = {
   1137       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow },
   1138       { 0u, kExpectCore | kExpectNarrow },
   1139       { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow },
   1140       { 0u, kExpectRef | kExpectNarrow | kExpectNull },
   1141   };
   1142   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1143     ExpectSRegType(sreg, expectations[sreg]);
   1144   }
   1145   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1146   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1147 }
   1148 
   1149 TEST_F(TypeInferenceTest, APut6) {
   1150   static const MIRDef mirs[] = {
   1151       DEF_CONST(3u, Instruction::CONST, 0u, 0),
   1152       DEF_CONST(3u, Instruction::CONST, 1u, 0),  // index
   1153       // Either array1 or array2 could be Object[][] but there is no way to tell from the bytecode.
   1154       DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u),  // Object[] array1
   1155       DEF_AGET(3u, Instruction::AGET_OBJECT, 3u, 0u, 1u),  // Object[] array2
   1156       DEF_APUT(3u, Instruction::APUT_OBJECT, 2u, 3u, 1u),
   1157       DEF_APUT(3u, Instruction::APUT_OBJECT, 3u, 2u, 1u),
   1158   };
   1159 
   1160   BuildDexFile("()V", true);
   1161   PrepareSingleBlock();
   1162   PrepareMIRs(mirs);
   1163   PerformTypeInference();
   1164 
   1165   ASSERT_EQ(arraysize(mirs), mir_count_);
   1166   static const SRegExpectation expectations[] = {
   1167       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow },
   1168       { 0u, kExpectCore | kExpectNarrow },
   1169       { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow },
   1170       { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow },
   1171   };
   1172   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1173     ExpectSRegType(sreg, expectations[sreg]);
   1174   }
   1175   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1176   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1177 }
   1178 
   1179 TEST_F(TypeInferenceTest, TwoNullObjectArraysInLoop) {
   1180   static const MIRDef mirs[] = {
   1181       // void foo() {
   1182       //   Object[] array1 = ((Object[])null)[0];
   1183       //   Object[] array2 = ((Object[])null)[0];
   1184       //   for (int i = 0; i != 3; ++i) {
   1185       //     Object[] a1 = null;  // One of these could be Object[][] but not both.
   1186       //     Object[] a2 = null;  // But they will be deduced as Object[].
   1187       //     try { a1[0] = a2; } catch (Throwable ignored) { }
   1188       //     try { a2[0] = a1; } catch (Throwable ignored) { }
   1189       //     array1 = a1;
   1190       //     array2 = a2;
   1191       //   }
   1192       // }
   1193       //
   1194       // Omitting the try-catch:
   1195       DEF_CONST(3u, Instruction::CONST, 0u, 0),            // null
   1196       DEF_CONST(3u, Instruction::CONST, 1u, 0),            // index
   1197       DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u),  // array1
   1198       DEF_AGET(3u, Instruction::AGET_OBJECT, 3u, 0u, 1u),  // array2
   1199       DEF_PHI2(4u, 4u, 2u, 8u),  // ? + [L -> [? gives [L (see array-length below)
   1200       DEF_PHI2(4u, 5u, 3u, 9u),  // ? + [L -> ? gives ?
   1201       DEF_AGET(4u, Instruction::AGET_OBJECT, 6u, 0u, 1u),  // a1
   1202       DEF_AGET(4u, Instruction::AGET_OBJECT, 7u, 0u, 1u),  // a2
   1203       DEF_APUT(4u, Instruction::APUT_OBJECT, 6u, 7u, 1u),
   1204       DEF_APUT(4u, Instruction::APUT_OBJECT, 7u, 6u, 1u),
   1205       DEF_MOVE(4u, Instruction::MOVE_OBJECT, 8u, 6u),
   1206       DEF_MOVE(4u, Instruction::MOVE_OBJECT, 9u, 7u),
   1207       DEF_UNOP(5u, Instruction::ARRAY_LENGTH, 10u, 4u),
   1208   };
   1209 
   1210   BuildDexFile("()V", true);
   1211   PrepareLoop();
   1212   PrepareMIRs(mirs);
   1213   PerformTypeInference();
   1214 
   1215   ASSERT_EQ(arraysize(mirs), mir_count_);
   1216   static const SRegExpectation expectations[] = {
   1217       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow },
   1218       { 0u, kExpectCore | kExpectNarrow },
   1219       { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow },
   1220       { 0u, kExpectRef | kExpectNarrow },
   1221       { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow },
   1222       { 0u, kExpectRef | kExpectNarrow },
   1223       { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow },
   1224       { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow },
   1225       { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow },
   1226       { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow },
   1227       { 0u, kExpectCore | kExpectNarrow },
   1228   };
   1229   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1230     ExpectSRegType(sreg, expectations[sreg]);
   1231   }
   1232   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1233   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1234 }
   1235 
   1236 TEST_F(TypeInferenceTest, ArrayArrayFloat) {
   1237   static const MethodDef methods[] = {
   1238       { kClassName, "(F)V", "fooFloat", kStatic },
   1239   };
   1240   static const MIRDef mirs[] = {
   1241       // void foo() {
   1242       //   try {
   1243       //     float[][][] aaaf = null;
   1244       //     float[][] array = aaaf[0];  // Make sure array is treated as properly typed.
   1245       //     array[0][0] = 0.0f;      // const + aget-object[1] + aput
   1246       //     fooFloat(array[0][0]);   // aget-object[2] + aget + invoke
   1247       //     // invoke: signature => input is F.
   1248       //     // aget: output is F => base is [F (precise)
   1249       //     // aget-object[2]: output is [F => base is [[F (precise)
   1250       //     // aput: unknown input type => base is [?
   1251       //     // aget-object[1]: base is [[F => result is L or [F, merge with [? => result is [F
   1252       //     // aput (again): base is [F => result is F
   1253       //     // const: F determined by the aput reprocessing.
   1254       //   } catch (Throwable ignored) {
   1255       //   }
   1256       // }
   1257       //
   1258       // Omitting the try-catch:
   1259       DEF_CONST(3u, Instruction::CONST, 0u, 0),             // 0
   1260       DEF_CONST(3u, Instruction::CONST, 1u, 0),             // aaaf
   1261       DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 1u, 0u),   // array = aaaf[0]
   1262       DEF_CONST(3u, Instruction::CONST, 3u, 0),             // 0.0f
   1263       DEF_AGET(3u, Instruction::AGET_OBJECT, 4u, 2u, 0u),   // array[0]
   1264       DEF_APUT(3u, Instruction::APUT, 3u, 4u, 0u),          // array[0][0] = 0.0f
   1265       DEF_AGET(3u, Instruction::AGET_OBJECT, 5u, 2u, 0u),   // array[0]
   1266       DEF_AGET(3u, Instruction::AGET, 6u, 5u, 0u),          // array[0][0]
   1267       DEF_INVOKE1(3u, Instruction::INVOKE_STATIC, 6u, 0u),  // fooFloat(array[0][0])
   1268   };
   1269 
   1270   PrepareMethods(methods);
   1271   BuildDexFile("()V", true);
   1272   PrepareSingleBlock();
   1273   PrepareMIRs(mirs);
   1274   PerformTypeInference();
   1275 
   1276   ASSERT_EQ(arraysize(mirs), mir_count_);
   1277   static const SRegExpectation expectations[] = {
   1278       { 0u, kExpectCore | kExpectNarrow },
   1279       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow },
   1280       { 2u, kExpectRef | kExpectNarrow | kExpectArrayFp | kExpectArrayNarrow },
   1281       { 0u, kExpectFp | kExpectNarrow },
   1282       { 1u, kExpectRef | kExpectNarrow | kExpectArrayFp | kExpectArrayNarrow },
   1283       { 1u, kExpectRef | kExpectNarrow | kExpectArrayFp | kExpectArrayNarrow },
   1284       { 0u, kExpectFp | kExpectNarrow },
   1285   };
   1286   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1287     ExpectSRegType(sreg, expectations[sreg]);
   1288   }
   1289   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1290   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1291 }
   1292 
   1293 TEST_F(TypeInferenceTest, CheckCast1) {
   1294   static const TypeDef types[] = {
   1295       { "[I" },
   1296   };
   1297   static const MIRDef mirs[] = {
   1298       DEF_CONST(3u, Instruction::CONST, 0u, 0),
   1299       DEF_CONST(3u, Instruction::CONST, 1u, 0),
   1300       DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u),
   1301       DEF_CHECK_CAST(4u, Instruction::CHECK_CAST, 2u, 0u),
   1302       DEF_CHECK_CAST(5u, Instruction::CHECK_CAST, 2u, 0u),
   1303       // Pseudo-phi from [I and [I into L infers only L but not [.
   1304       DEF_MOVE(6u, Instruction::MOVE_OBJECT, 3u, 2u),
   1305   };
   1306   PrepareTypes(types);
   1307   BuildDexFile("()V", true);
   1308   PrepareDiamond();
   1309   PrepareMIRs(mirs);
   1310   static const BasicBlockId v0_def_blocks[] = { 3u, 4u, 5u, 6u };
   1311   MapVRegToSReg(2, 2, v0_def_blocks);
   1312   PerformTypeInference();
   1313 
   1314   ASSERT_EQ(arraysize(mirs), mir_count_);
   1315   static const SRegExpectation expectations[] = {
   1316       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow },
   1317       { 0u, kExpectCore | kExpectNarrow },
   1318       { 0u, kExpectRef | kExpectNarrow },
   1319       { 0u, kExpectRef | kExpectNarrow },
   1320   };
   1321   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1322     ExpectSRegType(sreg, expectations[sreg]);
   1323   }
   1324   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1325   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1326 }
   1327 
   1328 TEST_F(TypeInferenceTest, CheckCast2) {
   1329   static const TypeDef types[] = {
   1330       { "[I" },
   1331   };
   1332   static const MIRDef mirs[] = {
   1333       DEF_CONST(3u, Instruction::CONST, 0u, 0),
   1334       DEF_CONST(3u, Instruction::CONST, 1u, 0),
   1335       DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u),
   1336       DEF_CHECK_CAST(4u, Instruction::CHECK_CAST, 2u, 0u),
   1337       DEF_CHECK_CAST(5u, Instruction::CHECK_CAST, 2u, 0u),
   1338       // Pseudo-phi from [I and [I into [? infers [I.
   1339       DEF_MOVE(6u, Instruction::MOVE_OBJECT, 3u, 2u),
   1340       DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 4u, 2u),
   1341   };
   1342   PrepareTypes(types);
   1343   BuildDexFile("()V", true);
   1344   PrepareDiamond();
   1345   PrepareMIRs(mirs);
   1346   static const BasicBlockId v0_def_blocks[] = { 3u, 4u, 5u, 6u };
   1347   MapVRegToSReg(2, 2, v0_def_blocks);
   1348   PerformTypeInference();
   1349 
   1350   ASSERT_EQ(arraysize(mirs), mir_count_);
   1351   static const SRegExpectation expectations[] = {
   1352       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow },
   1353       { 0u, kExpectCore | kExpectNarrow },
   1354       { 0u, kExpectRef | kExpectNarrow },
   1355       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayNarrow },
   1356       { 0u, kExpectCore | kExpectNarrow },
   1357   };
   1358   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1359     ExpectSRegType(sreg, expectations[sreg]);
   1360   }
   1361   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1362   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1363 }
   1364 
   1365 TEST_F(TypeInferenceTest, CheckCast3) {
   1366   static const TypeDef types[] = {
   1367       { "[I" },
   1368       { "[F" },
   1369   };
   1370   static const MIRDef mirs[] = {
   1371       DEF_CONST(3u, Instruction::CONST, 0u, 0),
   1372       DEF_CONST(3u, Instruction::CONST, 1u, 0),
   1373       DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u),
   1374       DEF_CHECK_CAST(4u, Instruction::CHECK_CAST, 2u, 0u),
   1375       DEF_CHECK_CAST(5u, Instruction::CHECK_CAST, 2u, 1u),
   1376       // Pseudo-phi from [I and [F into L correctly leaves it as L.
   1377       DEF_MOVE(6u, Instruction::MOVE_OBJECT, 3u, 2u),
   1378   };
   1379   PrepareTypes(types);
   1380   BuildDexFile("()V", true);
   1381   PrepareDiamond();
   1382   PrepareMIRs(mirs);
   1383   static const BasicBlockId v0_def_blocks[] = { 3u, 4u, 5u, 6u };
   1384   MapVRegToSReg(2, 2, v0_def_blocks);
   1385   PerformTypeInference();
   1386 
   1387   ASSERT_EQ(arraysize(mirs), mir_count_);
   1388   static const SRegExpectation expectations[] = {
   1389       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow },
   1390       { 0u, kExpectCore | kExpectNarrow },
   1391       { 0u, kExpectRef | kExpectNarrow },
   1392       { 0u, kExpectRef | kExpectNarrow },
   1393   };
   1394   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1395     ExpectSRegType(sreg, expectations[sreg]);
   1396   }
   1397   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1398   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1399 }
   1400 
   1401 TEST_F(TypeInferenceTest, CheckCastConflict1) {
   1402   static const TypeDef types[] = {
   1403       { "[I" },
   1404       { "[F" },
   1405   };
   1406   static const MIRDef mirs[] = {
   1407       DEF_CONST(3u, Instruction::CONST, 0u, 0),
   1408       DEF_CONST(3u, Instruction::CONST, 1u, 0),
   1409       DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u),
   1410       DEF_CHECK_CAST(4u, Instruction::CHECK_CAST, 2u, 0u),
   1411       DEF_CHECK_CAST(5u, Instruction::CHECK_CAST, 2u, 1u),
   1412       // Pseudo-phi from [I and [F into [? infers conflict [I/[F.
   1413       DEF_MOVE(6u, Instruction::MOVE_OBJECT, 3u, 2u),
   1414       DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 4u, 2u),
   1415   };
   1416   PrepareTypes(types);
   1417   BuildDexFile("()V", true);
   1418   PrepareDiamond();
   1419   PrepareMIRs(mirs);
   1420   static const BasicBlockId v0_def_blocks[] = { 3u, 4u, 5u, 6u };
   1421   MapVRegToSReg(2, 2, v0_def_blocks);
   1422   PerformTypeInference();
   1423 
   1424   ASSERT_EQ(arraysize(mirs), mir_count_);
   1425   static const SRegExpectation expectations[] = {
   1426       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow },
   1427       { 0u, kExpectCore | kExpectNarrow },
   1428       { 0u, kExpectRef | kExpectNarrow },
   1429       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow },
   1430       { 0u, kExpectCore | kExpectNarrow },
   1431   };
   1432   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1433     ExpectSRegType(sreg, expectations[sreg], false);
   1434   }
   1435   // The type conflict in array element wasn't propagated to an SSA reg.
   1436   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1437   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1438 }
   1439 
   1440 TEST_F(TypeInferenceTest, CheckCastConflict2) {
   1441   static const TypeDef types[] = {
   1442       { "[I" },
   1443       { "[F" },
   1444   };
   1445   static const MIRDef mirs[] = {
   1446       DEF_CONST(3u, Instruction::CONST, 0u, 0),
   1447       DEF_CONST(3u, Instruction::CONST, 1u, 0),
   1448       DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u),
   1449       DEF_CHECK_CAST(4u, Instruction::CHECK_CAST, 2u, 0u),
   1450       DEF_CHECK_CAST(5u, Instruction::CHECK_CAST, 2u, 1u),
   1451       // Pseudo-phi from [I and [F into [? infers conflict [I/[F.
   1452       DEF_MOVE(6u, Instruction::MOVE_OBJECT, 3u, 2u),
   1453       DEF_AGET(6u, Instruction::AGET, 4u, 2u, 1u),
   1454   };
   1455   PrepareTypes(types);
   1456   BuildDexFile("()V", true);
   1457   PrepareDiamond();
   1458   PrepareMIRs(mirs);
   1459   static const BasicBlockId v0_def_blocks[] = { 3u, 4u, 5u, 6u };
   1460   MapVRegToSReg(2, 2, v0_def_blocks);
   1461   PerformTypeInference();
   1462 
   1463   ASSERT_EQ(arraysize(mirs), mir_count_);
   1464   static const SRegExpectation expectations[] = {
   1465       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow },
   1466       { 0u, kExpectCore | kExpectNarrow },
   1467       { 0u, kExpectRef | kExpectNarrow },
   1468       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow },
   1469       { 0u, kExpectCore | kExpectFp | kExpectNarrow },
   1470   };
   1471   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1472     ExpectSRegType(sreg, expectations[sreg], false);
   1473   }
   1474   // Type conflict in an SSA reg, register promotion disabled.
   1475   EXPECT_NE(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1476   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1477 }
   1478 
   1479 TEST_F(TypeInferenceTest, Phi1) {
   1480   static const TypeDef types[] = {
   1481       { "[I" },
   1482   };
   1483   static const MIRDef mirs[] = {
   1484       DEF_CONST(3u, Instruction::CONST, 0u, 100),
   1485       DEF_NEW_ARRAY(4u, Instruction::NEW_ARRAY, 1u, 0u, 0u),
   1486       DEF_NEW_ARRAY(5u, Instruction::NEW_ARRAY, 2u, 0u, 0u),
   1487       // Phi from [I and [I infers only L but not [.
   1488       DEF_PHI2(6u, 3u, 1u, 2u),
   1489   };
   1490   PrepareTypes(types);
   1491   BuildDexFile("()V", true);
   1492   PrepareDiamond();
   1493   PrepareMIRs(mirs);
   1494   PerformTypeInference();
   1495 
   1496   ASSERT_EQ(arraysize(mirs), mir_count_);
   1497   static const SRegExpectation expectations[] = {
   1498       { 0u, kExpectCore | kExpectNarrow },
   1499       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayNarrow },
   1500       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayNarrow },
   1501       { 0u, kExpectRef | kExpectNarrow },
   1502   };
   1503   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1504     ExpectSRegType(sreg, expectations[sreg]);
   1505   }
   1506   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1507   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1508 }
   1509 
   1510 TEST_F(TypeInferenceTest, Phi2) {
   1511   static const TypeDef types[] = {
   1512       { "[F" },
   1513   };
   1514   static const MIRDef mirs[] = {
   1515       DEF_CONST(3u, Instruction::CONST, 0u, 100),
   1516       DEF_NEW_ARRAY(4u, Instruction::NEW_ARRAY, 1u, 0u, 0u),
   1517       DEF_NEW_ARRAY(5u, Instruction::NEW_ARRAY, 2u, 0u, 0u),
   1518       // Phi from [F and [F into [? infers [F.
   1519       DEF_PHI2(6u, 3u, 1u, 2u),
   1520       DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 4u, 3u),
   1521   };
   1522   PrepareTypes(types);
   1523   BuildDexFile("()V", true);
   1524   PrepareDiamond();
   1525   PrepareMIRs(mirs);
   1526   PerformTypeInference();
   1527 
   1528   ASSERT_EQ(arraysize(mirs), mir_count_);
   1529   static const SRegExpectation expectations[] = {
   1530       { 0u, kExpectCore | kExpectNarrow },
   1531       { 1u, kExpectRef | kExpectNarrow | kExpectArrayFp | kExpectArrayNarrow },
   1532       { 1u, kExpectRef | kExpectNarrow | kExpectArrayFp | kExpectArrayNarrow },
   1533       { 1u, kExpectRef | kExpectNarrow | kExpectArrayFp | kExpectArrayNarrow },
   1534       { 0u, kExpectCore | kExpectNarrow },
   1535   };
   1536   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1537     ExpectSRegType(sreg, expectations[sreg]);
   1538   }
   1539   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1540   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1541 }
   1542 
   1543 TEST_F(TypeInferenceTest, Phi3) {
   1544   static const TypeDef types[] = {
   1545       { "[I" },
   1546       { "[F" },
   1547   };
   1548   static const MIRDef mirs[] = {
   1549       DEF_CONST(3u, Instruction::CONST, 0u, 100),
   1550       DEF_NEW_ARRAY(4u, Instruction::NEW_ARRAY, 1u, 0u, 0u),
   1551       DEF_NEW_ARRAY(5u, Instruction::NEW_ARRAY, 2u, 0u, 1u),
   1552       // Phi from [I and [F infers L.
   1553       DEF_PHI2(6u, 3u, 1u, 2u),
   1554   };
   1555   PrepareTypes(types);
   1556   BuildDexFile("()V", true);
   1557   PrepareDiamond();
   1558   PrepareMIRs(mirs);
   1559   PerformTypeInference();
   1560 
   1561   ASSERT_EQ(arraysize(mirs), mir_count_);
   1562   static const SRegExpectation expectations[] = {
   1563       { 0u, kExpectCore | kExpectNarrow },
   1564       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayNarrow },
   1565       { 1u, kExpectRef | kExpectNarrow | kExpectArrayFp | kExpectArrayNarrow },
   1566       { 0u, kExpectRef | kExpectNarrow },
   1567   };
   1568   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1569     ExpectSRegType(sreg, expectations[sreg]);
   1570   }
   1571   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1572   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1573 }
   1574 
   1575 TEST_F(TypeInferenceTest, Phi4) {
   1576   static const TypeDef types[] = {
   1577       { "[I" },
   1578   };
   1579   static const MIRDef mirs[] = {
   1580       DEF_CONST(3u, Instruction::CONST, 0u, 100),
   1581       DEF_NEW_ARRAY(4u, Instruction::NEW_ARRAY, 1u, 0u, 0u),
   1582       DEF_CONST(5u, Instruction::CONST, 2u, 0),
   1583       // Pseudo-phi from [I and null infers L.
   1584       DEF_PHI2(6u, 3u, 1u, 2u),
   1585   };
   1586   PrepareTypes(types);
   1587   BuildDexFile("()V", true);
   1588   PrepareDiamond();
   1589   PrepareMIRs(mirs);
   1590   PerformTypeInference();
   1591 
   1592   ASSERT_EQ(arraysize(mirs), mir_count_);
   1593   static const SRegExpectation expectations[] = {
   1594       { 0u, kExpectCore | kExpectNarrow },
   1595       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayNarrow },
   1596       { 0u, kExpectRef | kExpectNarrow | kExpectNull },
   1597       { 0u, kExpectRef | kExpectNarrow },
   1598   };
   1599   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1600     ExpectSRegType(sreg, expectations[sreg]);
   1601   }
   1602   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1603   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1604 }
   1605 
   1606 TEST_F(TypeInferenceTest, PhiConflict1) {
   1607   static const TypeDef types[] = {
   1608       { "[I" },
   1609       { "[F" },
   1610   };
   1611   static const MIRDef mirs[] = {
   1612       DEF_CONST(3u, Instruction::CONST, 0u, 100),
   1613       DEF_NEW_ARRAY(4u, Instruction::NEW_ARRAY, 1u, 0u, 0u),
   1614       DEF_NEW_ARRAY(5u, Instruction::NEW_ARRAY, 2u, 0u, 1u),
   1615       // Pseudo-phi from [I and [F into [? infers conflict [I/[F (then propagated upwards).
   1616       DEF_PHI2(6u, 3u, 1u, 2u),
   1617       DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 4u, 3u),
   1618   };
   1619   PrepareTypes(types);
   1620   BuildDexFile("()V", true);
   1621   PrepareDiamond();
   1622   PrepareMIRs(mirs);
   1623   PerformTypeInference();
   1624 
   1625   ASSERT_EQ(arraysize(mirs), mir_count_);
   1626   static const SRegExpectation expectations[] = {
   1627       { 0u, kExpectCore | kExpectNarrow },
   1628       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow },
   1629       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow },
   1630       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow },
   1631       { 0u, kExpectCore | kExpectNarrow },
   1632   };
   1633   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1634     ExpectSRegType(sreg, expectations[sreg], false);
   1635   }
   1636   // The type conflict in array element wasn't propagated to an SSA reg.
   1637   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1638   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1639 }
   1640 
   1641 TEST_F(TypeInferenceTest, PhiConflict2) {
   1642   static const TypeDef types[] = {
   1643       { "[I" },
   1644       { "[F" },
   1645   };
   1646   static const MIRDef mirs[] = {
   1647       DEF_CONST(3u, Instruction::CONST, 0u, 100),
   1648       DEF_NEW_ARRAY(4u, Instruction::NEW_ARRAY, 1u, 0u, 0u),
   1649       DEF_NEW_ARRAY(5u, Instruction::NEW_ARRAY, 2u, 0u, 1u),
   1650       // Pseudo-phi from [I and [F into [? infers conflict [I/[F (then propagated upwards).
   1651       DEF_PHI2(6u, 3u, 1u, 2u),
   1652       DEF_AGET(6u, Instruction::AGET, 4u, 3u, 0u),
   1653   };
   1654   PrepareTypes(types);
   1655   BuildDexFile("()V", true);
   1656   PrepareDiamond();
   1657   PrepareMIRs(mirs);
   1658   PerformTypeInference();
   1659 
   1660   ASSERT_EQ(arraysize(mirs), mir_count_);
   1661   static const SRegExpectation expectations[] = {
   1662       { 0u, kExpectCore | kExpectNarrow },
   1663       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow },
   1664       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow },
   1665       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow },
   1666       { 0u, kExpectCore | kExpectFp | kExpectNarrow },
   1667   };
   1668   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1669     ExpectSRegType(sreg, expectations[sreg], false);
   1670   }
   1671   // Type conflict in an SSA reg, register promotion disabled.
   1672   EXPECT_NE(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1673   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1674 }
   1675 
   1676 TEST_F(TypeInferenceTest, Wide1) {
   1677   static const MIRDef mirs[] = {
   1678       DEF_CONST(3u, Instruction::CONST, 0u, 0),
   1679       DEF_CONST(3u, Instruction::CONST, 1u, 0),  // index
   1680       DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u),  // long[]
   1681       DEF_CONST_WIDE(3u, Instruction::CONST_WIDE, 3u, 0),  // long
   1682       DEF_APUT_WIDE(3u, Instruction::APUT_WIDE, 3u, 2u, 1u),
   1683       { 3u, Instruction::RETURN_OBJECT, 0, 0u, 1u, { 2u }, 0u, { } },
   1684   };
   1685 
   1686   BuildDexFile("()[J", true);
   1687   PrepareSingleBlock();
   1688   PrepareMIRs(mirs);
   1689   PerformTypeInference();
   1690 
   1691   ASSERT_EQ(arraysize(mirs), mir_count_);
   1692   static const SRegExpectation expectations[] = {
   1693       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow },
   1694       { 0u, kExpectCore | kExpectNarrow },
   1695       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayWide },
   1696       { 0u, kExpectCore | kExpectWide },
   1697       // NOTE: High word checked implicitly for sreg = 3.
   1698   };
   1699   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1700     ExpectSRegType(sreg, expectations[sreg], false);
   1701   }
   1702   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1703   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1704 }
   1705 
   1706 TEST_F(TypeInferenceTest, WideSizeConflict1) {
   1707   static const MIRDef mirs[] = {
   1708       DEF_CONST_WIDE(3u, Instruction::CONST_WIDE, 0u, 0),
   1709       DEF_MOVE(3u, Instruction::MOVE, 2u, 0u),
   1710   };
   1711 
   1712   BuildDexFile("()V", true);
   1713   PrepareSingleBlock();
   1714   PrepareMIRs(mirs);
   1715   PerformTypeInference();
   1716 
   1717   ASSERT_EQ(arraysize(mirs), mir_count_);
   1718   static const SRegExpectation expectations[] = {
   1719       { 0u, kExpectNarrow | kExpectWide },
   1720       { 0u, kExpectNarrow | kExpectWide },
   1721   };
   1722   ExpectSRegType(0u, expectations[0], false);
   1723   ExpectSRegType(2u, expectations[1], false);
   1724   EXPECT_TRUE(cu_.mir_graph->PuntToInterpreter());
   1725 }
   1726 
   1727 TEST_F(TypeInferenceTest, ArrayLongLength) {
   1728   static const FieldDef sfields[] = {
   1729       { kClassName, "[J", "arrayLongField" },
   1730   };
   1731   static const MIRDef mirs[] = {
   1732       DEF_CONST(4u, Instruction::CONST, 0u, 0),
   1733       DEF_SGET(5u, Instruction::SGET_OBJECT, 1u, 0u),
   1734       DEF_PHI2(6u, 2u, 0u, 1u),
   1735       DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 3u, 2u),
   1736       DEF_SGET(6u, Instruction::SGET_OBJECT, 4u, 0u),
   1737       DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 5u, 4u),
   1738   };
   1739 
   1740   PrepareSFields(sfields);
   1741   BuildDexFile("()V", true);
   1742   PrepareDiamond();
   1743   PrepareMIRs(mirs);
   1744   PerformTypeInference();
   1745 
   1746   ASSERT_EQ(arraysize(mirs), mir_count_);
   1747   static const SRegExpectation expectations[] = {
   1748       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayCore | kExpectArrayWide },
   1749       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayWide },
   1750       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayWide },
   1751       { 0u, kExpectCore | kExpectNarrow },
   1752       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayWide },
   1753       { 0u, kExpectCore | kExpectNarrow },
   1754   };
   1755   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1756     ExpectSRegType(sreg, expectations[sreg]);
   1757   }
   1758   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1759   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1760 }
   1761 
   1762 TEST_F(TypeInferenceTest, ArrayArrayObjectLength) {
   1763   static const FieldDef sfields[] = {
   1764       { kClassName, "[[Ljava/lang/Object;", "arrayLongField" },
   1765   };
   1766   static const MIRDef mirs[] = {
   1767       DEF_CONST(4u, Instruction::CONST, 0u, 0),
   1768       DEF_SGET(5u, Instruction::SGET_OBJECT, 1u, 0u),
   1769       DEF_PHI2(6u, 2u, 0u, 1u),
   1770       DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 3u, 2u),
   1771       DEF_SGET(6u, Instruction::SGET_OBJECT, 4u, 0u),
   1772       DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 5u, 4u),
   1773   };
   1774 
   1775   PrepareSFields(sfields);
   1776   BuildDexFile("()V", true);
   1777   PrepareDiamond();
   1778   PrepareMIRs(mirs);
   1779   PerformTypeInference();
   1780 
   1781   ASSERT_EQ(arraysize(mirs), mir_count_);
   1782   static const SRegExpectation expectations[] = {
   1783       { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow },
   1784       { 2u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow },
   1785       { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow },
   1786       { 0u, kExpectCore | kExpectNarrow },
   1787       { 2u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow },
   1788       { 0u, kExpectCore | kExpectNarrow },
   1789   };
   1790   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1791     ExpectSRegType(sreg, expectations[sreg]);
   1792   }
   1793   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1794   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1795 }
   1796 
   1797 TEST_F(TypeInferenceTest, SGetAdd0SPut) {
   1798   static const FieldDef sfields[] = {
   1799       { kClassName, "I", "staticIntField" },
   1800   };
   1801   static const MIRDef mirs[] = {
   1802       DEF_SGET(3u, Instruction::SGET, 0u, 0u),
   1803       DEF_UNOP(3u, Instruction::ADD_INT_LIT8, 1u, 0u),  // +0
   1804       DEF_SPUT(3u, Instruction::SPUT, 1u, 0u),
   1805   };
   1806 
   1807   PrepareSFields(sfields);
   1808   BuildDexFile("()V", true);
   1809   PrepareSingleBlock();
   1810   PrepareMIRs(mirs);
   1811   PerformTypeInference();
   1812 
   1813   ASSERT_EQ(arraysize(mirs), mir_count_);
   1814   static const SRegExpectation expectations[] = {
   1815       { 0u, kExpectCore | kExpectNarrow },
   1816       { 0u, kExpectCore | kExpectNarrow },
   1817   };
   1818   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1819     ExpectSRegType(sreg, expectations[sreg]);
   1820   }
   1821   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1822   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1823 }
   1824 
   1825 TEST_F(TypeInferenceTest, MoveObjectNull) {
   1826   static const MethodDef methods[] = {
   1827       { kClassName, "([I[D)V", "foo", kStatic },
   1828   };
   1829   static const MIRDef mirs[] = {
   1830       DEF_CONST(3u, Instruction::CONST, 0u, 0),
   1831       DEF_MOVE(3u, Instruction::MOVE_OBJECT, 1u, 0u),
   1832       DEF_INVOKE2(3u, Instruction::INVOKE_STATIC, 0u, 1u, 0u),
   1833   };
   1834 
   1835   PrepareMethods(methods);
   1836   BuildDexFile("()V", true);
   1837   PrepareSingleBlock();
   1838   PrepareMIRs(mirs);
   1839   PerformTypeInference();
   1840 
   1841   ASSERT_EQ(arraysize(mirs), mir_count_);
   1842   static const SRegExpectation expectation = {
   1843       1u,
   1844       kExpectRef | kExpectNarrow | kExpectNull |
   1845       kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow | kExpectArrayWide
   1846   };
   1847   ExpectSRegType(0u, expectation);
   1848   ExpectSRegType(1u, expectation);
   1849   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1850   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1851 }
   1852 
   1853 TEST_F(TypeInferenceTest, MoveNull1) {
   1854   static const MethodDef methods[] = {
   1855       { kClassName, "([I[D)V", "foo", kStatic },
   1856   };
   1857   static const MIRDef mirs[] = {
   1858       DEF_CONST(3u, Instruction::CONST, 0u, 0),
   1859       DEF_MOVE(3u, Instruction::MOVE, 1u, 0u),
   1860       DEF_INVOKE2(3u, Instruction::INVOKE_STATIC, 0u, 1u, 0u),
   1861   };
   1862 
   1863   PrepareMethods(methods);
   1864   BuildDexFile("()V", true);
   1865   PrepareSingleBlock();
   1866   PrepareMIRs(mirs);
   1867   PerformTypeInference();
   1868 
   1869   ASSERT_EQ(arraysize(mirs), mir_count_);
   1870   static const SRegExpectation expectation = {
   1871       1u,
   1872       kExpectCore | kExpectRef | kExpectFp | kExpectNarrow | kExpectNull |
   1873       kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow | kExpectArrayWide
   1874   };
   1875   ExpectSRegType(0u, expectation);
   1876   ExpectSRegType(1u, expectation);
   1877   // Type conflict using move instead of move-object for null, register promotion disabled.
   1878   EXPECT_NE(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1879   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1880 }
   1881 
   1882 TEST_F(TypeInferenceTest, MoveNull2) {
   1883   static const FieldDef sfields[] = {
   1884       { kClassName, "[F", "staticArrayArrayFloatField" },
   1885       { kClassName, "[I", "staticArrayIntField" },
   1886       { kClassName, "[[I", "staticArrayArrayIntField" },
   1887   };
   1888   static const MIRDef mirs[] = {
   1889       DEF_CONST(4u, Instruction::CONST, 0u, 0),
   1890       DEF_MOVE(4u, Instruction::MOVE_OBJECT, 1u, 0u),
   1891       DEF_MOVE(4u, Instruction::MOVE_OBJECT, 2u, 1u),
   1892       DEF_SGET(5u, Instruction::SGET_OBJECT, 3u, 0u),
   1893       DEF_SGET(5u, Instruction::SGET_OBJECT, 4u, 1u),
   1894       DEF_SGET(5u, Instruction::SGET_OBJECT, 5u, 2u),
   1895       DEF_PHI2(6u, 6u, 0u, 3u),
   1896       DEF_PHI2(6u, 7u, 1u, 4u),
   1897       DEF_PHI2(6u, 8u, 2u, 5u),
   1898       DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 9u, 6u),
   1899       DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 10u, 7u),
   1900       DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 11u, 8u),
   1901       { 6u, Instruction::RETURN_OBJECT, 0, 0u, 1u, { 8u }, 0u, { } },
   1902   };
   1903 
   1904   PrepareSFields(sfields);
   1905   BuildDexFile("()[[I", true);
   1906   PrepareDiamond();
   1907   PrepareMIRs(mirs);
   1908   PerformTypeInference();
   1909 
   1910   ASSERT_EQ(arraysize(mirs), mir_count_);
   1911   static const SRegExpectation expectations[] = {
   1912       { 1u, kExpectRef | kExpectNarrow | kExpectNull |
   1913           kExpectArrayCore | kExpectArrayFp | kExpectArrayRef | kExpectArrayNarrow },
   1914       { 1u, kExpectRef | kExpectNarrow | kExpectNull |
   1915           kExpectArrayCore | kExpectArrayFp | kExpectArrayRef | kExpectArrayNarrow},
   1916       { 1u, kExpectRef | kExpectNarrow | kExpectNull |
   1917           kExpectArrayCore | kExpectArrayFp | kExpectArrayRef | kExpectArrayNarrow},
   1918       { 1u, kExpectRef | kExpectNarrow | kExpectArrayFp | kExpectArrayNarrow },
   1919       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayNarrow },
   1920       { 2u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayNarrow },
   1921       { 1u, kExpectRef | kExpectNarrow | kExpectArrayFp | kExpectArrayNarrow },
   1922       { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayNarrow },
   1923       { 2u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayNarrow },
   1924       { 0u, kExpectCore | kExpectNarrow },
   1925       { 0u, kExpectCore | kExpectNarrow },
   1926       { 0u, kExpectCore | kExpectNarrow },
   1927   };
   1928   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   1929     ExpectSRegType(sreg, expectations[sreg]);
   1930   }
   1931   // Type conflict in array type not propagated to actual register.
   1932   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1933   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1934 }
   1935 
   1936 TEST_F(TypeInferenceTest, ReuseNull1) {
   1937   static const FieldDef sfields[] = {
   1938       { kClassName, "[I", "staticArrayLongField" },
   1939       { kClassName, "[[F", "staticArrayArrayFloatField" },
   1940   };
   1941   static const MIRDef mirs[] = {
   1942       DEF_CONST(3u, Instruction::CONST, 0u, 0),
   1943       DEF_SPUT(3u, Instruction::SPUT_OBJECT, 0u, 0u),
   1944       DEF_SPUT(3u, Instruction::SPUT_OBJECT, 0u, 1u),
   1945   };
   1946 
   1947   PrepareSFields(sfields);
   1948   BuildDexFile("()V", true);
   1949   PrepareSingleBlock();
   1950   PrepareMIRs(mirs);
   1951   PerformTypeInference();
   1952 
   1953   ASSERT_EQ(arraysize(mirs), mir_count_);
   1954   static const SRegExpectation expectation = {
   1955       1u,
   1956       kExpectRef | kExpectNarrow | kExpectNull |
   1957       kExpectArrayCore | kExpectArrayRef | kExpectArrayFp | kExpectArrayNarrow
   1958   };
   1959   ExpectSRegType(0u, expectation);
   1960   // Type conflict in array type not propagated to actual register.
   1961   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1962   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1963 }
   1964 
   1965 TEST_F(TypeInferenceTest, ReuseNull2) {
   1966   static const FieldDef sfields[] = {
   1967       { kClassName, "[J", "staticArrayLongField" },
   1968       { kClassName, "[[F", "staticArrayArrayFloatField" },
   1969   };
   1970   static const MIRDef mirs[] = {
   1971       DEF_CONST(3u, Instruction::CONST, 0u, 0),
   1972       DEF_SPUT(3u, Instruction::SPUT_OBJECT, 0u, 0u),
   1973       DEF_SPUT(3u, Instruction::SPUT_OBJECT, 0u, 1u),
   1974   };
   1975 
   1976   PrepareSFields(sfields);
   1977   BuildDexFile("()V", true);
   1978   PrepareSingleBlock();
   1979   PrepareMIRs(mirs);
   1980   PerformTypeInference();
   1981 
   1982   ASSERT_EQ(arraysize(mirs), mir_count_);
   1983   static const SRegExpectation expectation = {
   1984       1u,
   1985       kExpectRef | kExpectNarrow | kExpectNull |
   1986       kExpectArrayCore | kExpectArrayRef | kExpectArrayFp | kExpectArrayNarrow | kExpectArrayWide
   1987   };
   1988   ExpectSRegType(0u, expectation);
   1989   // Type conflict in array type not propagated to actual register.
   1990   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   1991   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   1992 }
   1993 
   1994 TEST_F(TypeInferenceTest, ArgIsNonNull) {
   1995   constexpr uint32_t thiz = kLocalVRs;
   1996   static const MIRDef mirs[] = {
   1997       DEF_MOVE(3u, Instruction::MOVE_OBJECT, 0u, thiz),
   1998   };
   1999 
   2000   BuildDexFile("(Ljava/lang/Object;)V", true);
   2001   PrepareSingleBlock();
   2002   PrepareMIRs(mirs);
   2003   PerformTypeInference();
   2004 
   2005   ASSERT_EQ(arraysize(mirs), mir_count_);
   2006   static const SRegExpectation expectation = {
   2007       0u,
   2008       kExpectRef | kExpectNarrow
   2009   };
   2010   ExpectSRegType(0u, expectation);
   2011   // Type conflict in array type not propagated to actual register.
   2012   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   2013   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   2014 }
   2015 
   2016 TEST_F(TypeInferenceTest, IfCc) {
   2017   static const FieldDef sfields[] = {
   2018       { kClassName, "I", "intField" },
   2019   };
   2020   static const MIRDef mirs[] = {
   2021       DEF_SGET(3u, Instruction::SGET, 0u, 0u),
   2022       DEF_CONST(3u, Instruction::CONST, 1u, 0u),
   2023       { 3u, Instruction::IF_EQ, 0, 0u, 2, { 0u, 1u }, 0, { } },
   2024   };
   2025 
   2026   PrepareSFields(sfields);
   2027   BuildDexFile("()V", false);
   2028   PrepareDiamond();
   2029   PrepareMIRs(mirs);
   2030   PerformTypeInference();
   2031 
   2032   ASSERT_EQ(arraysize(mirs), mir_count_);
   2033   static const SRegExpectation expectations[] = {
   2034       { 0u, kExpectCore | kExpectNarrow },
   2035       { 0u, kExpectCore | kExpectNarrow },
   2036   };
   2037   for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) {
   2038     ExpectSRegType(sreg, expectations[sreg]);
   2039   }
   2040   EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u);
   2041   EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter());
   2042 }
   2043 
   2044 }  // namespace art
   2045