type_inference_test.cc revision c91df2d6339dd4adf2da582372451df19ce2ff44
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
28namespace art {
29
30class 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
633TEST_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
689TEST_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
744TEST_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
812TEST_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
879TEST_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
946TEST_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
1013TEST_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
1039TEST_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
1065TEST_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
1093TEST_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
1121TEST_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
1149TEST_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
1179TEST_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
1236TEST_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
1293TEST_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
1328TEST_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
1365TEST_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
1401TEST_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
1440TEST_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
1479TEST_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
1510TEST_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
1543TEST_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
1575TEST_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
1606TEST_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
1641TEST_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
1676TEST_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
1706TEST_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
1727TEST_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
1762TEST_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
1797TEST_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
1825TEST_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
1853TEST_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
1882TEST_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
1936TEST_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
1965TEST_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
1994TEST_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
2016TEST_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