Home | History | Annotate | Download | only in dex
      1 /*
      2  * Copyright (C) 2014 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 "dex/mir_field_info.h"
     18 #include "global_value_numbering.h"
     19 #include "local_value_numbering.h"
     20 #include "gtest/gtest.h"
     21 
     22 namespace art {
     23 
     24 class LocalValueNumberingTest : public testing::Test {
     25  protected:
     26   struct IFieldDef {
     27     uint16_t field_idx;
     28     uintptr_t declaring_dex_file;
     29     uint16_t declaring_field_idx;
     30     bool is_volatile;
     31     DexMemAccessType type;
     32   };
     33 
     34   struct SFieldDef {
     35     uint16_t field_idx;
     36     uintptr_t declaring_dex_file;
     37     uint16_t declaring_field_idx;
     38     bool is_volatile;
     39     DexMemAccessType type;
     40   };
     41 
     42   struct MIRDef {
     43     static constexpr size_t kMaxSsaDefs = 2;
     44     static constexpr size_t kMaxSsaUses = 4;
     45 
     46     Instruction::Code opcode;
     47     int64_t value;
     48     uint32_t field_info;
     49     size_t num_uses;
     50     int32_t uses[kMaxSsaUses];
     51     size_t num_defs;
     52     int32_t defs[kMaxSsaDefs];
     53   };
     54 
     55 #define DEF_CONST(opcode, reg, value) \
     56     { opcode, value, 0u, 0, { }, 1, { reg } }
     57 #define DEF_CONST_WIDE(opcode, reg, value) \
     58     { opcode, value, 0u, 0, { }, 2, { reg, reg + 1 } }
     59 #define DEF_CONST_STRING(opcode, reg, index) \
     60     { opcode, index, 0u, 0, { }, 1, { reg } }
     61 #define DEF_IGET(opcode, reg, obj, field_info) \
     62     { opcode, 0u, field_info, 1, { obj }, 1, { reg } }
     63 #define DEF_IGET_WIDE(opcode, reg, obj, field_info) \
     64     { opcode, 0u, field_info, 1, { obj }, 2, { reg, reg + 1 } }
     65 #define DEF_IPUT(opcode, reg, obj, field_info) \
     66     { opcode, 0u, field_info, 2, { reg, obj }, 0, { } }
     67 #define DEF_IPUT_WIDE(opcode, reg, obj, field_info) \
     68     { opcode, 0u, field_info, 3, { reg, reg + 1, obj }, 0, { } }
     69 #define DEF_SGET(opcode, reg, field_info) \
     70     { opcode, 0u, field_info, 0, { }, 1, { reg } }
     71 #define DEF_SGET_WIDE(opcode, reg, field_info) \
     72     { opcode, 0u, field_info, 0, { }, 2, { reg, reg + 1 } }
     73 #define DEF_SPUT(opcode, reg, field_info) \
     74     { opcode, 0u, field_info, 1, { reg }, 0, { } }
     75 #define DEF_SPUT_WIDE(opcode, reg, field_info) \
     76     { opcode, 0u, field_info, 2, { reg, reg + 1 }, 0, { } }
     77 #define DEF_AGET(opcode, reg, obj, idx) \
     78     { opcode, 0u, 0u, 2, { obj, idx }, 1, { reg } }
     79 #define DEF_AGET_WIDE(opcode, reg, obj, idx) \
     80     { opcode, 0u, 0u, 2, { obj, idx }, 2, { reg, reg + 1 } }
     81 #define DEF_APUT(opcode, reg, obj, idx) \
     82     { opcode, 0u, 0u, 3, { reg, obj, idx }, 0, { } }
     83 #define DEF_APUT_WIDE(opcode, reg, obj, idx) \
     84     { opcode, 0u, 0u, 4, { reg, reg + 1, obj, idx }, 0, { } }
     85 #define DEF_INVOKE1(opcode, reg) \
     86     { opcode, 0u, 0u, 1, { reg }, 0, { } }
     87 #define DEF_UNIQUE_REF(opcode, reg) \
     88     { opcode, 0u, 0u, 0, { }, 1, { reg } }  // CONST_CLASS, CONST_STRING, NEW_ARRAY, ...
     89 #define DEF_DIV_REM(opcode, result, dividend, divisor) \
     90     { opcode, 0u, 0u, 2, { dividend, divisor }, 1, { result } }
     91 #define DEF_DIV_REM_WIDE(opcode, result, dividend, divisor) \
     92     { opcode, 0u, 0u, 4, { dividend, dividend + 1, divisor, divisor + 1 }, 2, { result, result + 1 } }
     93 
     94   void DoPrepareIFields(const IFieldDef* defs, size_t count) {
     95     cu_.mir_graph->ifield_lowering_infos_.clear();
     96     cu_.mir_graph->ifield_lowering_infos_.reserve(count);
     97     for (size_t i = 0u; i != count; ++i) {
     98       const IFieldDef* def = &defs[i];
     99       MirIFieldLoweringInfo field_info(def->field_idx, def->type, false);
    100       if (def->declaring_dex_file != 0u) {
    101         field_info.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file);
    102         field_info.declaring_field_idx_ = def->declaring_field_idx;
    103         field_info.flags_ &= ~(def->is_volatile ? 0u : MirSFieldLoweringInfo::kFlagIsVolatile);
    104       }
    105       cu_.mir_graph->ifield_lowering_infos_.push_back(field_info);
    106     }
    107   }
    108 
    109   template <size_t count>
    110   void PrepareIFields(const IFieldDef (&defs)[count]) {
    111     DoPrepareIFields(defs, count);
    112   }
    113 
    114   void DoPrepareSFields(const SFieldDef* defs, size_t count) {
    115     cu_.mir_graph->sfield_lowering_infos_.clear();
    116     cu_.mir_graph->sfield_lowering_infos_.reserve(count);
    117     for (size_t i = 0u; i != count; ++i) {
    118       const SFieldDef* def = &defs[i];
    119       MirSFieldLoweringInfo field_info(def->field_idx, def->type);
    120       // Mark even unresolved fields as initialized.
    121       field_info.flags_ |= MirSFieldLoweringInfo::kFlagClassIsInitialized;
    122       // NOTE: MirSFieldLoweringInfo::kFlagClassIsInDexCache isn't used by LVN.
    123       if (def->declaring_dex_file != 0u) {
    124         field_info.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file);
    125         field_info.declaring_field_idx_ = def->declaring_field_idx;
    126         field_info.flags_ &= ~(def->is_volatile ? 0u : MirSFieldLoweringInfo::kFlagIsVolatile);
    127       }
    128       cu_.mir_graph->sfield_lowering_infos_.push_back(field_info);
    129     }
    130   }
    131 
    132   template <size_t count>
    133   void PrepareSFields(const SFieldDef (&defs)[count]) {
    134     DoPrepareSFields(defs, count);
    135   }
    136 
    137   void DoPrepareMIRs(const MIRDef* defs, size_t count) {
    138     mir_count_ = count;
    139     mirs_ = cu_.arena.AllocArray<MIR>(count, kArenaAllocMIR);
    140     ssa_reps_.resize(count);
    141     for (size_t i = 0u; i != count; ++i) {
    142       const MIRDef* def = &defs[i];
    143       MIR* mir = &mirs_[i];
    144       mir->dalvikInsn.opcode = def->opcode;
    145       mir->dalvikInsn.vB = static_cast<int32_t>(def->value);
    146       mir->dalvikInsn.vB_wide = def->value;
    147       if (IsInstructionIGetOrIPut(def->opcode)) {
    148         ASSERT_LT(def->field_info, cu_.mir_graph->ifield_lowering_infos_.size());
    149         mir->meta.ifield_lowering_info = def->field_info;
    150         ASSERT_EQ(cu_.mir_graph->ifield_lowering_infos_[def->field_info].MemAccessType(),
    151                   IGetOrIPutMemAccessType(def->opcode));
    152       } else if (IsInstructionSGetOrSPut(def->opcode)) {
    153         ASSERT_LT(def->field_info, cu_.mir_graph->sfield_lowering_infos_.size());
    154         mir->meta.sfield_lowering_info = def->field_info;
    155         ASSERT_EQ(cu_.mir_graph->sfield_lowering_infos_[def->field_info].MemAccessType(),
    156                   SGetOrSPutMemAccessType(def->opcode));
    157       }
    158       mir->ssa_rep = &ssa_reps_[i];
    159       mir->ssa_rep->num_uses = def->num_uses;
    160       mir->ssa_rep->uses = const_cast<int32_t*>(def->uses);  // Not modified by LVN.
    161       mir->ssa_rep->num_defs = def->num_defs;
    162       mir->ssa_rep->defs = const_cast<int32_t*>(def->defs);  // Not modified by LVN.
    163       mir->dalvikInsn.opcode = def->opcode;
    164       mir->offset = i;  // LVN uses offset only for debug output
    165       mir->optimization_flags = 0u;
    166 
    167       if (i != 0u) {
    168         mirs_[i - 1u].next = mir;
    169       }
    170     }
    171     mirs_[count - 1u].next = nullptr;
    172   }
    173 
    174   template <size_t count>
    175   void PrepareMIRs(const MIRDef (&defs)[count]) {
    176     DoPrepareMIRs(defs, count);
    177   }
    178 
    179   void MakeSFieldUninitialized(uint32_t sfield_index) {
    180     CHECK_LT(sfield_index, cu_.mir_graph->sfield_lowering_infos_.size());
    181     cu_.mir_graph->sfield_lowering_infos_[sfield_index].flags_ &=
    182         ~MirSFieldLoweringInfo::kFlagClassIsInitialized;
    183   }
    184 
    185   template <size_t count>
    186   void MarkAsWideSRegs(const int32_t (&sregs)[count]) {
    187     for (int32_t sreg : sregs) {
    188       cu_.mir_graph->reg_location_[sreg].wide = true;
    189       cu_.mir_graph->reg_location_[sreg + 1].wide = true;
    190       cu_.mir_graph->reg_location_[sreg + 1].high_word = true;
    191     }
    192   }
    193 
    194   void PerformLVN() {
    195     cu_.mir_graph->temp_.gvn.ifield_ids =  GlobalValueNumbering::PrepareGvnFieldIds(
    196         allocator_.get(), cu_.mir_graph->ifield_lowering_infos_);
    197     cu_.mir_graph->temp_.gvn.sfield_ids =  GlobalValueNumbering::PrepareGvnFieldIds(
    198         allocator_.get(), cu_.mir_graph->sfield_lowering_infos_);
    199     gvn_.reset(new (allocator_.get()) GlobalValueNumbering(&cu_, allocator_.get(),
    200                                                            GlobalValueNumbering::kModeLvn));
    201     lvn_.reset(new (allocator_.get()) LocalValueNumbering(gvn_.get(), 0u, allocator_.get()));
    202     value_names_.resize(mir_count_);
    203     for (size_t i = 0; i != mir_count_; ++i) {
    204       value_names_[i] =  lvn_->GetValueNumber(&mirs_[i]);
    205     }
    206     EXPECT_TRUE(gvn_->Good());
    207   }
    208 
    209   LocalValueNumberingTest()
    210       : pool_(),
    211         cu_(&pool_, kRuntimeISA, nullptr, nullptr),
    212         mir_count_(0u),
    213         mirs_(nullptr),
    214         ssa_reps_(),
    215         allocator_(),
    216         gvn_(),
    217         lvn_(),
    218         value_names_() {
    219     cu_.mir_graph.reset(new MIRGraph(&cu_, &cu_.arena));
    220     allocator_.reset(ScopedArenaAllocator::Create(&cu_.arena_stack));
    221     // By default, the zero-initialized reg_location_[.] with ref == false tells LVN that
    222     // 0 constants are integral, not references, and the values are all narrow.
    223     // Nothing else is used by LVN/GVN. Tests can override the default values as needed.
    224     cu_.mir_graph->reg_location_ = static_cast<RegLocation*>(cu_.arena.Alloc(
    225         kMaxSsaRegs * sizeof(cu_.mir_graph->reg_location_[0]), kArenaAllocRegAlloc));
    226     cu_.mir_graph->num_ssa_regs_ = kMaxSsaRegs;
    227   }
    228 
    229   static constexpr size_t kMaxSsaRegs = 16384u;
    230 
    231   ArenaPool pool_;
    232   CompilationUnit cu_;
    233   size_t mir_count_;
    234   MIR* mirs_;
    235   std::vector<SSARepresentation> ssa_reps_;
    236   std::unique_ptr<ScopedArenaAllocator> allocator_;
    237   std::unique_ptr<GlobalValueNumbering> gvn_;
    238   std::unique_ptr<LocalValueNumbering> lvn_;
    239   std::vector<uint16_t> value_names_;
    240 };
    241 
    242 TEST_F(LocalValueNumberingTest, IGetIGetInvokeIGet) {
    243   static const IFieldDef ifields[] = {
    244       { 1u, 1u, 1u, false, kDexMemAccessWord },
    245   };
    246   static const MIRDef mirs[] = {
    247       DEF_IGET(Instruction::IGET, 0u, 10u, 0u),
    248       DEF_IGET(Instruction::IGET, 1u, 10u, 0u),
    249       DEF_INVOKE1(Instruction::INVOKE_VIRTUAL, 11u),
    250       DEF_IGET(Instruction::IGET, 2u, 10u, 0u),
    251   };
    252 
    253   PrepareIFields(ifields);
    254   PrepareMIRs(mirs);
    255   PerformLVN();
    256   ASSERT_EQ(value_names_.size(), 4u);
    257   EXPECT_EQ(value_names_[0], value_names_[1]);
    258   EXPECT_NE(value_names_[0], value_names_[3]);
    259   EXPECT_EQ(mirs_[0].optimization_flags, 0u);
    260   EXPECT_EQ(mirs_[1].optimization_flags, MIR_IGNORE_NULL_CHECK);
    261   EXPECT_EQ(mirs_[2].optimization_flags, 0u);
    262   EXPECT_EQ(mirs_[3].optimization_flags, MIR_IGNORE_NULL_CHECK);
    263 }
    264 
    265 TEST_F(LocalValueNumberingTest, IGetIPutIGetIGetIGet) {
    266   static const IFieldDef ifields[] = {
    267       { 1u, 1u, 1u, false, kDexMemAccessObject },
    268       { 2u, 1u, 2u, false, kDexMemAccessWord },
    269   };
    270   static const MIRDef mirs[] = {
    271       DEF_IGET(Instruction::IGET_OBJECT, 0u, 10u, 0u),
    272       DEF_IPUT(Instruction::IPUT_OBJECT, 1u, 11u, 0u),  // May alias.
    273       DEF_IGET(Instruction::IGET_OBJECT, 2u, 10u, 0u),
    274       DEF_IGET(Instruction::IGET, 3u,  0u, 1u),
    275       DEF_IGET(Instruction::IGET, 4u,  2u, 1u),
    276   };
    277 
    278   PrepareIFields(ifields);
    279   PrepareMIRs(mirs);
    280   PerformLVN();
    281   ASSERT_EQ(value_names_.size(), 5u);
    282   EXPECT_NE(value_names_[0], value_names_[2]);
    283   EXPECT_NE(value_names_[3], value_names_[4]);
    284   for (size_t i = 0; i != arraysize(mirs); ++i) {
    285     EXPECT_EQ((i == 2u) ? MIR_IGNORE_NULL_CHECK : 0,
    286               mirs_[i].optimization_flags) << i;
    287   }
    288 }
    289 
    290 TEST_F(LocalValueNumberingTest, UniquePreserve1) {
    291   static const IFieldDef ifields[] = {
    292       { 1u, 1u, 1u, false, kDexMemAccessWord },
    293   };
    294   static const MIRDef mirs[] = {
    295       DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 10u),
    296       DEF_IGET(Instruction::IGET, 0u, 10u, 0u),
    297       DEF_IPUT(Instruction::IPUT, 1u, 11u, 0u),  // No aliasing since 10u is unique.
    298       DEF_IGET(Instruction::IGET, 2u, 10u, 0u),
    299   };
    300 
    301   PrepareIFields(ifields);
    302   PrepareMIRs(mirs);
    303   PerformLVN();
    304   ASSERT_EQ(value_names_.size(), 4u);
    305   EXPECT_EQ(value_names_[1], value_names_[3]);
    306   for (size_t i = 0; i != arraysize(mirs); ++i) {
    307     EXPECT_EQ((i == 1u || i == 3u) ? MIR_IGNORE_NULL_CHECK : 0,
    308               mirs_[i].optimization_flags) << i;
    309   }
    310 }
    311 
    312 TEST_F(LocalValueNumberingTest, UniquePreserve2) {
    313   static const IFieldDef ifields[] = {
    314       { 1u, 1u, 1u, false, kDexMemAccessWord },
    315   };
    316   static const MIRDef mirs[] = {
    317       DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 11u),
    318       DEF_IGET(Instruction::IGET, 0u, 10u, 0u),
    319       DEF_IPUT(Instruction::IPUT, 1u, 11u, 0u),  // No aliasing since 11u is unique.
    320       DEF_IGET(Instruction::IGET, 2u, 10u, 0u),
    321   };
    322 
    323   PrepareIFields(ifields);
    324   PrepareMIRs(mirs);
    325   PerformLVN();
    326   ASSERT_EQ(value_names_.size(), 4u);
    327   EXPECT_EQ(value_names_[1], value_names_[3]);
    328   for (size_t i = 0; i != arraysize(mirs); ++i) {
    329     EXPECT_EQ((i == 2u || i == 3u) ? MIR_IGNORE_NULL_CHECK : 0,
    330               mirs_[i].optimization_flags) << i;
    331   }
    332 }
    333 
    334 TEST_F(LocalValueNumberingTest, UniquePreserveAndEscape) {
    335   static const IFieldDef ifields[] = {
    336       { 1u, 1u, 1u, false, kDexMemAccessWord },
    337   };
    338   static const MIRDef mirs[] = {
    339       DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 10u),
    340       DEF_IGET(Instruction::IGET, 0u, 10u, 0u),
    341       DEF_INVOKE1(Instruction::INVOKE_VIRTUAL, 11u),  // 10u still unique.
    342       DEF_IGET(Instruction::IGET, 2u, 10u, 0u),
    343       DEF_INVOKE1(Instruction::INVOKE_VIRTUAL, 10u),  // 10u not unique anymore.
    344       DEF_IGET(Instruction::IGET, 3u, 10u, 0u),
    345   };
    346 
    347   PrepareIFields(ifields);
    348   PrepareMIRs(mirs);
    349   PerformLVN();
    350   ASSERT_EQ(value_names_.size(), 6u);
    351   EXPECT_EQ(value_names_[1], value_names_[3]);
    352   EXPECT_NE(value_names_[1], value_names_[5]);
    353   for (size_t i = 0; i != arraysize(mirs); ++i) {
    354     EXPECT_EQ((i == 1u || i == 3u || i == 4u || i == 5u) ? MIR_IGNORE_NULL_CHECK : 0,
    355               mirs_[i].optimization_flags) << i;
    356   }
    357 }
    358 
    359 TEST_F(LocalValueNumberingTest, Volatile) {
    360   static const IFieldDef ifields[] = {
    361       { 1u, 1u, 1u, false, kDexMemAccessWord },
    362       { 2u, 1u, 2u, true, kDexMemAccessWord },
    363   };
    364   static const MIRDef mirs[] = {
    365       DEF_IGET(Instruction::IGET, 0u, 10u, 1u),  // Volatile.
    366       DEF_IGET(Instruction::IGET, 1u,  0u, 0u),  // Non-volatile.
    367       DEF_IGET(Instruction::IGET, 2u, 10u, 1u),  // Volatile.
    368       DEF_IGET(Instruction::IGET, 3u,  2u, 1u),  // Non-volatile.
    369       DEF_IGET(Instruction::IGET, 4u,  0u, 0u),  // Non-volatile.
    370   };
    371 
    372   PrepareIFields(ifields);
    373   PrepareMIRs(mirs);
    374   PerformLVN();
    375   ASSERT_EQ(value_names_.size(), 5u);
    376   EXPECT_NE(value_names_[0], value_names_[2]);  // Volatile has always different value name.
    377   EXPECT_NE(value_names_[1], value_names_[3]);  // Used different base because of volatile.
    378   EXPECT_NE(value_names_[1], value_names_[4]);  // Not guaranteed to be the same after "acquire".
    379 
    380   for (size_t i = 0; i != arraysize(mirs); ++i) {
    381     EXPECT_EQ((i == 2u || i == 4u) ? MIR_IGNORE_NULL_CHECK : 0,
    382               mirs_[i].optimization_flags) << i;
    383   }
    384 }
    385 
    386 TEST_F(LocalValueNumberingTest, UnresolvedIField) {
    387   static const IFieldDef ifields[] = {
    388       { 1u, 1u, 1u, false, kDexMemAccessWord },  // Resolved field #1.
    389       { 2u, 1u, 2u, false, kDexMemAccessWide },  // Resolved field #2.
    390       { 3u, 0u, 0u, false, kDexMemAccessWord },  // Unresolved field.
    391   };
    392   static const MIRDef mirs[] = {
    393       DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 30u),
    394       DEF_IGET(Instruction::IGET, 1u, 30u, 0u),             // Resolved field #1, unique object.
    395       DEF_IGET(Instruction::IGET, 2u, 31u, 0u),             // Resolved field #1.
    396       DEF_IGET_WIDE(Instruction::IGET_WIDE, 3u, 31u, 1u),   // Resolved field #2.
    397       DEF_IGET(Instruction::IGET, 5u, 32u, 2u),             // Unresolved IGET can be "acquire".
    398       DEF_IGET(Instruction::IGET, 6u, 30u, 0u),             // Resolved field #1, unique object.
    399       DEF_IGET(Instruction::IGET, 7u, 31u, 0u),             // Resolved field #1.
    400       DEF_IGET_WIDE(Instruction::IGET_WIDE, 8u, 31u, 1u),   // Resolved field #2.
    401       DEF_IPUT(Instruction::IPUT, 10u, 32u, 2u),            // IPUT clobbers field #1 (#2 is wide).
    402       DEF_IGET(Instruction::IGET, 11u, 30u, 0u),            // Resolved field #1, unique object.
    403       DEF_IGET(Instruction::IGET, 12u, 31u, 0u),            // Resolved field #1, new value name.
    404       DEF_IGET_WIDE(Instruction::IGET_WIDE, 13u, 31u, 1u),  // Resolved field #2.
    405       DEF_IGET_WIDE(Instruction::IGET_WIDE, 15u, 30u, 1u),  // Resolved field #2, unique object.
    406       DEF_IPUT(Instruction::IPUT, 17u, 30u, 2u),            // IPUT clobbers field #1 (#2 is wide).
    407       DEF_IGET(Instruction::IGET, 18u, 30u, 0u),            // Resolved field #1, unique object.
    408       DEF_IGET_WIDE(Instruction::IGET_WIDE, 19u, 30u, 1u),  // Resolved field #2, unique object.
    409   };
    410 
    411   PrepareIFields(ifields);
    412   PrepareMIRs(mirs);
    413   static const int32_t wide_sregs[] = { 3, 8, 13, 15, 19 };
    414   MarkAsWideSRegs(wide_sregs);
    415   PerformLVN();
    416   ASSERT_EQ(value_names_.size(), 16u);
    417   // Unresolved field is potentially volatile, so we need to adhere to the volatile semantics.
    418   EXPECT_EQ(value_names_[1], value_names_[5]);    // Unique object.
    419   EXPECT_NE(value_names_[2], value_names_[6]);    // Not guaranteed to be the same after "acquire".
    420   EXPECT_NE(value_names_[3], value_names_[7]);    // Not guaranteed to be the same after "acquire".
    421   EXPECT_EQ(value_names_[1], value_names_[9]);    // Unique object.
    422   EXPECT_NE(value_names_[6], value_names_[10]);   // This aliased with unresolved IPUT.
    423   EXPECT_EQ(value_names_[7], value_names_[11]);   // Still the same after "release".
    424   EXPECT_EQ(value_names_[12], value_names_[15]);  // Still the same after "release".
    425   EXPECT_NE(value_names_[1], value_names_[14]);   // This aliased with unresolved IPUT.
    426   EXPECT_EQ(mirs_[0].optimization_flags, 0u);
    427   EXPECT_EQ(mirs_[1].optimization_flags, MIR_IGNORE_NULL_CHECK);
    428   EXPECT_EQ(mirs_[2].optimization_flags, 0u);
    429   EXPECT_EQ(mirs_[3].optimization_flags, MIR_IGNORE_NULL_CHECK);
    430   EXPECT_EQ(mirs_[4].optimization_flags, 0u);
    431   for (size_t i = 5u; i != mir_count_; ++i) {
    432     EXPECT_EQ((i == 1u || i == 3u || i >=5u) ? MIR_IGNORE_NULL_CHECK : 0,
    433               mirs_[i].optimization_flags) << i;
    434   }
    435 }
    436 
    437 TEST_F(LocalValueNumberingTest, UnresolvedSField) {
    438   static const SFieldDef sfields[] = {
    439       { 1u, 1u, 1u, false, kDexMemAccessWord },  // Resolved field #1.
    440       { 2u, 1u, 2u, false, kDexMemAccessWide },  // Resolved field #2.
    441       { 3u, 0u, 0u, false, kDexMemAccessWord },  // Unresolved field.
    442   };
    443   static const MIRDef mirs[] = {
    444       DEF_SGET(Instruction::SGET, 0u, 0u),            // Resolved field #1.
    445       DEF_SGET_WIDE(Instruction::SGET_WIDE, 1u, 1u),  // Resolved field #2.
    446       DEF_SGET(Instruction::SGET, 3u, 2u),            // Unresolved SGET can be "acquire".
    447       DEF_SGET(Instruction::SGET, 4u, 0u),            // Resolved field #1.
    448       DEF_SGET_WIDE(Instruction::SGET_WIDE, 5u, 1u),  // Resolved field #2.
    449       DEF_SPUT(Instruction::SPUT, 7u, 2u),            // SPUT clobbers field #1 (#2 is wide).
    450       DEF_SGET(Instruction::SGET, 8u, 0u),            // Resolved field #1.
    451       DEF_SGET_WIDE(Instruction::SGET_WIDE, 9u, 1u),  // Resolved field #2.
    452   };
    453 
    454   PrepareSFields(sfields);
    455   PrepareMIRs(mirs);
    456   static const int32_t wide_sregs[] = { 1, 5, 9 };
    457   MarkAsWideSRegs(wide_sregs);
    458   PerformLVN();
    459   ASSERT_EQ(value_names_.size(), 8u);
    460   // Unresolved field is potentially volatile, so we need to adhere to the volatile semantics.
    461   EXPECT_NE(value_names_[0], value_names_[3]);  // Not guaranteed to be the same after "acquire".
    462   EXPECT_NE(value_names_[1], value_names_[4]);  // Not guaranteed to be the same after "acquire".
    463   EXPECT_NE(value_names_[3], value_names_[6]);  // This aliased with unresolved IPUT.
    464   EXPECT_EQ(value_names_[4], value_names_[7]);  // Still the same after "release".
    465   for (size_t i = 0u; i != mir_count_; ++i) {
    466     EXPECT_EQ(0, mirs_[i].optimization_flags) << i;
    467   }
    468 }
    469 
    470 TEST_F(LocalValueNumberingTest, UninitializedSField) {
    471   static const IFieldDef ifields[] = {
    472       { 1u, 1u, 1u, false, kDexMemAccessWord },  // Resolved field #1.
    473   };
    474   static const SFieldDef sfields[] = {
    475       { 1u, 1u, 1u, false, kDexMemAccessWord },  // Resolved field #1.
    476       { 2u, 1u, 2u, false, kDexMemAccessWord },  // Resolved field #2; uninitialized.
    477   };
    478   static const MIRDef mirs[] = {
    479       DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 200u),
    480       DEF_IGET(Instruction::IGET, 1u, 100u, 0u),
    481       DEF_IGET(Instruction::IGET, 2u, 200u, 0u),
    482       DEF_SGET(Instruction::SGET, 3u, 0u),
    483       DEF_SGET(Instruction::SGET, 4u, 1u),            // Can call <clinit>().
    484       DEF_IGET(Instruction::IGET, 5u, 100u, 0u),      // Differs from 1u.
    485       DEF_IGET(Instruction::IGET, 6u, 200u, 0u),      // Same as 2u.
    486       DEF_SGET(Instruction::SGET, 7u, 0u),            // Differs from 3u.
    487   };
    488 
    489   PrepareIFields(ifields);
    490   PrepareSFields(sfields);
    491   MakeSFieldUninitialized(1u);
    492   PrepareMIRs(mirs);
    493   PerformLVN();
    494   ASSERT_EQ(value_names_.size(), 8u);
    495   EXPECT_NE(value_names_[1], value_names_[5]);
    496   EXPECT_EQ(value_names_[2], value_names_[6]);
    497   EXPECT_NE(value_names_[3], value_names_[7]);
    498 }
    499 
    500 TEST_F(LocalValueNumberingTest, ConstString) {
    501   static const MIRDef mirs[] = {
    502       DEF_CONST_STRING(Instruction::CONST_STRING, 0u, 0u),
    503       DEF_CONST_STRING(Instruction::CONST_STRING, 1u, 0u),
    504       DEF_CONST_STRING(Instruction::CONST_STRING, 2u, 2u),
    505       DEF_CONST_STRING(Instruction::CONST_STRING, 3u, 0u),
    506       DEF_INVOKE1(Instruction::INVOKE_DIRECT, 2u),
    507       DEF_CONST_STRING(Instruction::CONST_STRING, 4u, 2u),
    508   };
    509 
    510   PrepareMIRs(mirs);
    511   PerformLVN();
    512   ASSERT_EQ(value_names_.size(), 6u);
    513   EXPECT_EQ(value_names_[1], value_names_[0]);
    514   EXPECT_NE(value_names_[2], value_names_[0]);
    515   EXPECT_EQ(value_names_[3], value_names_[0]);
    516   EXPECT_EQ(value_names_[5], value_names_[2]);
    517 }
    518 
    519 TEST_F(LocalValueNumberingTest, SameValueInDifferentMemoryLocations) {
    520   static const IFieldDef ifields[] = {
    521       { 1u, 1u, 1u, false, kDexMemAccessWord },
    522       { 2u, 1u, 2u, false, kDexMemAccessWord },
    523   };
    524   static const SFieldDef sfields[] = {
    525       { 3u, 1u, 3u, false, kDexMemAccessWord },
    526   };
    527   static const MIRDef mirs[] = {
    528       DEF_UNIQUE_REF(Instruction::NEW_ARRAY, 201u),
    529       DEF_IGET(Instruction::IGET, 0u, 100u, 0u),
    530       DEF_IPUT(Instruction::IPUT, 0u, 100u, 1u),
    531       DEF_IPUT(Instruction::IPUT, 0u, 101u, 1u),
    532       DEF_APUT(Instruction::APUT, 0u, 200u, 300u),
    533       DEF_APUT(Instruction::APUT, 0u, 200u, 301u),
    534       DEF_APUT(Instruction::APUT, 0u, 201u, 300u),
    535       DEF_APUT(Instruction::APUT, 0u, 201u, 301u),
    536       DEF_SPUT(Instruction::SPUT, 0u, 0u),
    537       DEF_IGET(Instruction::IGET, 9u, 100u, 0u),
    538       DEF_IGET(Instruction::IGET, 10u, 100u, 1u),
    539       DEF_IGET(Instruction::IGET, 11u, 101u, 1u),
    540       DEF_AGET(Instruction::AGET, 12u, 200u, 300u),
    541       DEF_AGET(Instruction::AGET, 13u, 200u, 301u),
    542       DEF_AGET(Instruction::AGET, 14u, 201u, 300u),
    543       DEF_AGET(Instruction::AGET, 15u, 201u, 301u),
    544       DEF_SGET(Instruction::SGET, 16u, 0u),
    545   };
    546 
    547   PrepareIFields(ifields);
    548   PrepareSFields(sfields);
    549   PrepareMIRs(mirs);
    550   PerformLVN();
    551   ASSERT_EQ(value_names_.size(), 17u);
    552   for (size_t i = 9; i != arraysize(mirs); ++i) {
    553     EXPECT_EQ(value_names_[1], value_names_[i]) << i;
    554   }
    555   for (size_t i = 0; i != arraysize(mirs); ++i) {
    556     int expected_flags =
    557         ((i == 2u || (i >= 5u && i <= 7u) || (i >= 9u && i <= 15u)) ? MIR_IGNORE_NULL_CHECK : 0) |
    558         ((i >= 12u && i <= 15u) ? MIR_IGNORE_RANGE_CHECK : 0);
    559     EXPECT_EQ(expected_flags, mirs_[i].optimization_flags) << i;
    560   }
    561 }
    562 
    563 TEST_F(LocalValueNumberingTest, UniqueArrayAliasing) {
    564   static const MIRDef mirs[] = {
    565       DEF_UNIQUE_REF(Instruction::NEW_ARRAY, 20u),
    566       DEF_AGET(Instruction::AGET, 1u, 20u, 40u),
    567       DEF_APUT(Instruction::APUT, 2u, 20u, 41u),  // May alias with index for sreg 40u.
    568       DEF_AGET(Instruction::AGET, 3u, 20u, 40u),
    569   };
    570 
    571   PrepareMIRs(mirs);
    572   PerformLVN();
    573   ASSERT_EQ(value_names_.size(), 4u);
    574   EXPECT_NE(value_names_[1], value_names_[3]);
    575   for (size_t i = 0; i != arraysize(mirs); ++i) {
    576     int expected_flags =
    577         ((i >= 1u) ? MIR_IGNORE_NULL_CHECK : 0) |
    578         ((i == 3u) ? MIR_IGNORE_RANGE_CHECK : 0);
    579     EXPECT_EQ(expected_flags, mirs_[i].optimization_flags) << i;
    580   }
    581 }
    582 
    583 TEST_F(LocalValueNumberingTest, EscapingRefs) {
    584   static const IFieldDef ifields[] = {
    585       { 1u, 1u, 1u, false, kDexMemAccessWord },    // Field #1.
    586       { 2u, 1u, 2u, false, kDexMemAccessWord },    // Field #2.
    587       { 3u, 1u, 3u, false, kDexMemAccessObject },  // For storing escaping refs.
    588       { 4u, 1u, 4u, false, kDexMemAccessWide },    // Wide.
    589       { 5u, 0u, 0u, false, kDexMemAccessWord },    // Unresolved field, int.
    590       { 6u, 0u, 0u, false, kDexMemAccessWide },    // Unresolved field, wide.
    591   };
    592   static const MIRDef mirs[] = {
    593       DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 20u),
    594       DEF_IGET(Instruction::IGET, 1u, 20u, 0u),
    595       DEF_IGET(Instruction::IGET, 2u, 20u, 1u),
    596       DEF_IPUT(Instruction::IPUT_OBJECT, 20u, 30u, 2u),      // Ref escapes.
    597       DEF_IGET(Instruction::IGET, 4u, 20u, 0u),
    598       DEF_IGET(Instruction::IGET, 5u, 20u, 1u),
    599       DEF_IPUT(Instruction::IPUT, 6u, 31u, 0u),              // May alias with field #1.
    600       DEF_IGET(Instruction::IGET, 7u, 20u, 0u),              // New value.
    601       DEF_IGET(Instruction::IGET, 8u, 20u, 1u),              // Still the same.
    602       DEF_IPUT_WIDE(Instruction::IPUT_WIDE, 9u, 31u, 3u),    // No aliasing, different type.
    603       DEF_IGET(Instruction::IGET, 11u, 20u, 0u),
    604       DEF_IGET(Instruction::IGET, 12u, 20u, 1u),
    605       DEF_IPUT_WIDE(Instruction::IPUT_WIDE, 13u, 31u, 5u),   // No aliasing, different type.
    606       DEF_IGET(Instruction::IGET, 15u, 20u, 0u),
    607       DEF_IGET(Instruction::IGET, 16u, 20u, 1u),
    608       DEF_IPUT(Instruction::IPUT, 17u, 31u, 4u),             // Aliasing, same type.
    609       DEF_IGET(Instruction::IGET, 18u, 20u, 0u),
    610       DEF_IGET(Instruction::IGET, 19u, 20u, 1u),
    611   };
    612 
    613   PrepareIFields(ifields);
    614   PrepareMIRs(mirs);
    615   static const int32_t wide_sregs[] = { 9, 13 };
    616   MarkAsWideSRegs(wide_sregs);
    617   PerformLVN();
    618   ASSERT_EQ(value_names_.size(), 18u);
    619   EXPECT_EQ(value_names_[1], value_names_[4]);
    620   EXPECT_EQ(value_names_[2], value_names_[5]);
    621   EXPECT_NE(value_names_[4], value_names_[7]);  // New value.
    622   EXPECT_EQ(value_names_[5], value_names_[8]);
    623   EXPECT_EQ(value_names_[7], value_names_[10]);
    624   EXPECT_EQ(value_names_[8], value_names_[11]);
    625   EXPECT_EQ(value_names_[10], value_names_[13]);
    626   EXPECT_EQ(value_names_[11], value_names_[14]);
    627   EXPECT_NE(value_names_[13], value_names_[16]);  // New value.
    628   EXPECT_NE(value_names_[14], value_names_[17]);  // New value.
    629   for (size_t i = 0u; i != mir_count_; ++i) {
    630     int expected =
    631         ((i != 0u && i != 3u && i != 6u) ? MIR_IGNORE_NULL_CHECK : 0) |
    632         ((i == 3u) ? MIR_STORE_NON_NULL_VALUE: 0);
    633     EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
    634   }
    635 }
    636 
    637 TEST_F(LocalValueNumberingTest, EscapingArrayRefs) {
    638   static const MIRDef mirs[] = {
    639       DEF_UNIQUE_REF(Instruction::NEW_ARRAY, 20u),
    640       DEF_AGET(Instruction::AGET, 1u, 20u, 40u),
    641       DEF_AGET(Instruction::AGET, 2u, 20u, 41u),
    642       DEF_APUT(Instruction::APUT_OBJECT, 20u, 30u, 42u),    // Array ref escapes.
    643       DEF_AGET(Instruction::AGET, 4u, 20u, 40u),
    644       DEF_AGET(Instruction::AGET, 5u, 20u, 41u),
    645       DEF_APUT_WIDE(Instruction::APUT_WIDE, 6u, 31u, 43u),  // No aliasing, different type.
    646       DEF_AGET(Instruction::AGET, 8u, 20u, 40u),
    647       DEF_AGET(Instruction::AGET, 9u, 20u, 41u),
    648       DEF_APUT(Instruction::APUT, 10u, 32u, 40u),           // May alias with all elements.
    649       DEF_AGET(Instruction::AGET, 11u, 20u, 40u),           // New value (same index name).
    650       DEF_AGET(Instruction::AGET, 12u, 20u, 41u),           // New value (different index name).
    651   };
    652 
    653   PrepareMIRs(mirs);
    654   static const int32_t wide_sregs[] = { 6 };
    655   MarkAsWideSRegs(wide_sregs);
    656   PerformLVN();
    657   ASSERT_EQ(value_names_.size(), 12u);
    658   EXPECT_EQ(value_names_[1], value_names_[4]);
    659   EXPECT_EQ(value_names_[2], value_names_[5]);
    660   EXPECT_EQ(value_names_[4], value_names_[7]);
    661   EXPECT_EQ(value_names_[5], value_names_[8]);
    662   EXPECT_NE(value_names_[7], value_names_[10]);  // New value.
    663   EXPECT_NE(value_names_[8], value_names_[11]);  // New value.
    664   for (size_t i = 0u; i != mir_count_; ++i) {
    665     int expected =
    666         ((i != 0u && i != 3u && i != 6u && i != 9u) ? MIR_IGNORE_NULL_CHECK : 0u) |
    667         ((i >= 4 && i != 6u && i != 9u) ? MIR_IGNORE_RANGE_CHECK : 0u) |
    668         ((i == 3u) ? MIR_STORE_NON_NULL_VALUE: 0);
    669     EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
    670   }
    671 }
    672 
    673 TEST_F(LocalValueNumberingTest, StoringSameValueKeepsMemoryVersion) {
    674   static const IFieldDef ifields[] = {
    675       { 1u, 1u, 1u, false, kDexMemAccessWord },
    676       { 2u, 1u, 2u, false, kDexMemAccessWord },
    677   };
    678   static const SFieldDef sfields[] = {
    679       { 2u, 1u, 2u, false, kDexMemAccessWord },
    680   };
    681   static const MIRDef mirs[] = {
    682       DEF_IGET(Instruction::IGET, 0u, 30u, 0u),
    683       DEF_IGET(Instruction::IGET, 1u, 31u, 0u),
    684       DEF_IPUT(Instruction::IPUT, 1u, 31u, 0u),            // Store the same value.
    685       DEF_IGET(Instruction::IGET, 3u, 30u, 0u),
    686       DEF_AGET(Instruction::AGET, 4u, 32u, 40u),
    687       DEF_AGET(Instruction::AGET, 5u, 33u, 40u),
    688       DEF_APUT(Instruction::APUT, 5u, 33u, 40u),           // Store the same value.
    689       DEF_AGET(Instruction::AGET, 7u, 32u, 40u),
    690       DEF_SGET(Instruction::SGET, 8u, 0u),
    691       DEF_SPUT(Instruction::SPUT, 8u, 0u),                 // Store the same value.
    692       DEF_SGET(Instruction::SGET, 10u, 0u),
    693       DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 50u),      // Test with unique references.
    694       { Instruction::FILLED_NEW_ARRAY, 0, 0u, 2, { 12u, 13u }, 0, { } },
    695       DEF_UNIQUE_REF(Instruction::MOVE_RESULT_OBJECT, 51u),
    696       DEF_IGET(Instruction::IGET, 14u, 50u, 0u),
    697       DEF_IGET(Instruction::IGET, 15u, 50u, 1u),
    698       DEF_IPUT(Instruction::IPUT, 15u, 50u, 1u),           // Store the same value.
    699       DEF_IGET(Instruction::IGET, 17u, 50u, 0u),
    700       DEF_AGET(Instruction::AGET, 18u, 51u, 40u),
    701       DEF_AGET(Instruction::AGET, 19u, 51u, 41u),
    702       DEF_APUT(Instruction::APUT, 19u, 51u, 41u),          // Store the same value.
    703       DEF_AGET(Instruction::AGET, 21u, 51u, 40u),
    704   };
    705 
    706   PrepareIFields(ifields);
    707   PrepareSFields(sfields);
    708   PrepareMIRs(mirs);
    709   PerformLVN();
    710   ASSERT_EQ(value_names_.size(), 22u);
    711   EXPECT_NE(value_names_[0], value_names_[1]);
    712   EXPECT_EQ(value_names_[0], value_names_[3]);
    713   EXPECT_NE(value_names_[4], value_names_[5]);
    714   EXPECT_EQ(value_names_[4], value_names_[7]);
    715   EXPECT_EQ(value_names_[8], value_names_[10]);
    716   EXPECT_NE(value_names_[14], value_names_[15]);
    717   EXPECT_EQ(value_names_[14], value_names_[17]);
    718   EXPECT_NE(value_names_[18], value_names_[19]);
    719   EXPECT_EQ(value_names_[18], value_names_[21]);
    720   for (size_t i = 0u; i != mir_count_; ++i) {
    721     int expected =
    722         ((i == 2u || i == 3u || i == 6u || i == 7u || (i >= 14u)) ? MIR_IGNORE_NULL_CHECK : 0u) |
    723         ((i == 6u || i == 7u || i >= 20u) ? MIR_IGNORE_RANGE_CHECK : 0u);
    724     EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
    725   }
    726 }
    727 
    728 TEST_F(LocalValueNumberingTest, FilledNewArrayTracking) {
    729   if (!kLocalValueNumberingEnableFilledNewArrayTracking) {
    730     // Feature disabled.
    731     return;
    732   }
    733   static const MIRDef mirs[] = {
    734       DEF_CONST(Instruction::CONST, 0u, 100),
    735       DEF_CONST(Instruction::CONST, 1u, 200),
    736       { Instruction::FILLED_NEW_ARRAY, 0, 0u, 2, { 0u, 1u }, 0, { } },
    737       DEF_UNIQUE_REF(Instruction::MOVE_RESULT_OBJECT, 10u),
    738       DEF_CONST(Instruction::CONST, 20u, 0),
    739       DEF_CONST(Instruction::CONST, 21u, 1),
    740       DEF_AGET(Instruction::AGET, 6u, 10u, 20u),
    741       DEF_AGET(Instruction::AGET, 7u, 10u, 21u),
    742   };
    743 
    744   PrepareMIRs(mirs);
    745   PerformLVN();
    746   ASSERT_EQ(value_names_.size(), 8u);
    747   EXPECT_EQ(value_names_[0], value_names_[6]);
    748   EXPECT_EQ(value_names_[1], value_names_[7]);
    749   for (size_t i = 0u; i != mir_count_; ++i) {
    750     int expected = (i == 6u || i == 7u) ? (MIR_IGNORE_NULL_CHECK | MIR_IGNORE_RANGE_CHECK) : 0u;
    751     EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
    752   }
    753 }
    754 
    755 TEST_F(LocalValueNumberingTest, ClInitOnSget) {
    756   static const SFieldDef sfields[] = {
    757       { 0u, 1u, 0u, false, kDexMemAccessObject },
    758       { 1u, 2u, 1u, false, kDexMemAccessObject },
    759   };
    760   static const MIRDef mirs[] = {
    761       DEF_SGET(Instruction::SGET_OBJECT, 0u, 0u),
    762       DEF_AGET(Instruction::AGET, 1u, 0u, 100u),
    763       DEF_SGET(Instruction::SGET_OBJECT, 2u, 1u),
    764       DEF_SGET(Instruction::SGET_OBJECT, 3u, 0u),
    765       DEF_AGET(Instruction::AGET, 4u, 3u, 100u),
    766   };
    767 
    768   PrepareSFields(sfields);
    769   MakeSFieldUninitialized(1u);
    770   PrepareMIRs(mirs);
    771   PerformLVN();
    772   ASSERT_EQ(value_names_.size(), 5u);
    773   EXPECT_NE(value_names_[0], value_names_[3]);
    774 }
    775 
    776 TEST_F(LocalValueNumberingTest, DivZeroCheck) {
    777   static const MIRDef mirs[] = {
    778       DEF_DIV_REM(Instruction::DIV_INT, 1u, 10u, 20u),
    779       DEF_DIV_REM(Instruction::DIV_INT, 2u, 20u, 20u),
    780       DEF_DIV_REM(Instruction::DIV_INT_2ADDR, 3u, 10u, 1u),
    781       DEF_DIV_REM(Instruction::REM_INT, 4u, 30u, 20u),
    782       DEF_DIV_REM_WIDE(Instruction::REM_LONG, 5u, 12u, 14u),
    783       DEF_DIV_REM_WIDE(Instruction::DIV_LONG_2ADDR, 7u, 16u, 14u),
    784   };
    785 
    786   static const bool expected_ignore_div_zero_check[] = {
    787       false, true, false, true, false, true,
    788   };
    789 
    790   PrepareMIRs(mirs);
    791   static const int32_t wide_sregs[] = { 5, 7, 12, 14, 16 };
    792   MarkAsWideSRegs(wide_sregs);
    793   PerformLVN();
    794   for (size_t i = 0u; i != mir_count_; ++i) {
    795     int expected = expected_ignore_div_zero_check[i] ? MIR_IGNORE_DIV_ZERO_CHECK : 0u;
    796     EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
    797   }
    798 }
    799 
    800 TEST_F(LocalValueNumberingTest, ConstWide) {
    801   static const MIRDef mirs[] = {
    802       // Core reg constants.
    803       DEF_CONST(Instruction::CONST_WIDE_16, 0u, 0),
    804       DEF_CONST(Instruction::CONST_WIDE_16, 2u, 1),
    805       DEF_CONST(Instruction::CONST_WIDE_16, 4u, -1),
    806       DEF_CONST(Instruction::CONST_WIDE_32, 6u, 1 << 16),
    807       DEF_CONST(Instruction::CONST_WIDE_32, 8u, -1 << 16),
    808       DEF_CONST(Instruction::CONST_WIDE_32, 10u, (1 << 16) + 1),
    809       DEF_CONST(Instruction::CONST_WIDE_32, 12u, (1 << 16) - 1),
    810       DEF_CONST(Instruction::CONST_WIDE_32, 14u, -(1 << 16) + 1),
    811       DEF_CONST(Instruction::CONST_WIDE_32, 16u, -(1 << 16) - 1),
    812       DEF_CONST(Instruction::CONST_WIDE, 18u, INT64_C(1) << 32),
    813       DEF_CONST(Instruction::CONST_WIDE, 20u, INT64_C(-1) << 32),
    814       DEF_CONST(Instruction::CONST_WIDE, 22u, (INT64_C(1) << 32) + 1),
    815       DEF_CONST(Instruction::CONST_WIDE, 24u, (INT64_C(1) << 32) - 1),
    816       DEF_CONST(Instruction::CONST_WIDE, 26u, (INT64_C(-1) << 32) + 1),
    817       DEF_CONST(Instruction::CONST_WIDE, 28u, (INT64_C(-1) << 32) - 1),
    818       DEF_CONST(Instruction::CONST_WIDE_HIGH16, 30u, 1),       // Effectively 1 << 48.
    819       DEF_CONST(Instruction::CONST_WIDE_HIGH16, 32u, 0xffff),  // Effectively -1 << 48.
    820       DEF_CONST(Instruction::CONST_WIDE, 34u, (INT64_C(1) << 48) + 1),
    821       DEF_CONST(Instruction::CONST_WIDE, 36u, (INT64_C(1) << 48) - 1),
    822       DEF_CONST(Instruction::CONST_WIDE, 38u, (INT64_C(-1) << 48) + 1),
    823       DEF_CONST(Instruction::CONST_WIDE, 40u, (INT64_C(-1) << 48) - 1),
    824       // FP reg constants.
    825       DEF_CONST(Instruction::CONST_WIDE_16, 42u, 0),
    826       DEF_CONST(Instruction::CONST_WIDE_16, 44u, 1),
    827       DEF_CONST(Instruction::CONST_WIDE_16, 46u, -1),
    828       DEF_CONST(Instruction::CONST_WIDE_32, 48u, 1 << 16),
    829       DEF_CONST(Instruction::CONST_WIDE_32, 50u, -1 << 16),
    830       DEF_CONST(Instruction::CONST_WIDE_32, 52u, (1 << 16) + 1),
    831       DEF_CONST(Instruction::CONST_WIDE_32, 54u, (1 << 16) - 1),
    832       DEF_CONST(Instruction::CONST_WIDE_32, 56u, -(1 << 16) + 1),
    833       DEF_CONST(Instruction::CONST_WIDE_32, 58u, -(1 << 16) - 1),
    834       DEF_CONST(Instruction::CONST_WIDE, 60u, INT64_C(1) << 32),
    835       DEF_CONST(Instruction::CONST_WIDE, 62u, INT64_C(-1) << 32),
    836       DEF_CONST(Instruction::CONST_WIDE, 64u, (INT64_C(1) << 32) + 1),
    837       DEF_CONST(Instruction::CONST_WIDE, 66u, (INT64_C(1) << 32) - 1),
    838       DEF_CONST(Instruction::CONST_WIDE, 68u, (INT64_C(-1) << 32) + 1),
    839       DEF_CONST(Instruction::CONST_WIDE, 70u, (INT64_C(-1) << 32) - 1),
    840       DEF_CONST(Instruction::CONST_WIDE_HIGH16, 72u, 1),       // Effectively 1 << 48.
    841       DEF_CONST(Instruction::CONST_WIDE_HIGH16, 74u, 0xffff),  // Effectively -1 << 48.
    842       DEF_CONST(Instruction::CONST_WIDE, 76u, (INT64_C(1) << 48) + 1),
    843       DEF_CONST(Instruction::CONST_WIDE, 78u, (INT64_C(1) << 48) - 1),
    844       DEF_CONST(Instruction::CONST_WIDE, 80u, (INT64_C(-1) << 48) + 1),
    845       DEF_CONST(Instruction::CONST_WIDE, 82u, (INT64_C(-1) << 48) - 1),
    846   };
    847 
    848   PrepareMIRs(mirs);
    849   for (size_t i = 0; i != arraysize(mirs); ++i) {
    850     const int32_t wide_sregs[] = { mirs_[i].ssa_rep->defs[0] };
    851     MarkAsWideSRegs(wide_sregs);
    852   }
    853   for (size_t i = arraysize(mirs) / 2u; i != arraysize(mirs); ++i) {
    854     cu_.mir_graph->reg_location_[mirs_[i].ssa_rep->defs[0]].fp = true;
    855   }
    856   PerformLVN();
    857   for (size_t i = 0u; i != mir_count_; ++i) {
    858     for (size_t j = i + 1u; j != mir_count_; ++j) {
    859       EXPECT_NE(value_names_[i], value_names_[j]) << i << " " << j;
    860     }
    861   }
    862 }
    863 
    864 TEST_F(LocalValueNumberingTest, Const) {
    865   static const MIRDef mirs[] = {
    866       // Core reg constants.
    867       DEF_CONST(Instruction::CONST_4, 0u, 0),
    868       DEF_CONST(Instruction::CONST_4, 1u, 1),
    869       DEF_CONST(Instruction::CONST_4, 2u, -1),
    870       DEF_CONST(Instruction::CONST_16, 3u, 1 << 4),
    871       DEF_CONST(Instruction::CONST_16, 4u, -1 << 4),
    872       DEF_CONST(Instruction::CONST_16, 5u, (1 << 4) + 1),
    873       DEF_CONST(Instruction::CONST_16, 6u, (1 << 4) - 1),
    874       DEF_CONST(Instruction::CONST_16, 7u, -(1 << 4) + 1),
    875       DEF_CONST(Instruction::CONST_16, 8u, -(1 << 4) - 1),
    876       DEF_CONST(Instruction::CONST_HIGH16, 9u, 1),       // Effectively 1 << 16.
    877       DEF_CONST(Instruction::CONST_HIGH16, 10u, 0xffff),  // Effectively -1 << 16.
    878       DEF_CONST(Instruction::CONST, 11u, (1 << 16) + 1),
    879       DEF_CONST(Instruction::CONST, 12u, (1 << 16) - 1),
    880       DEF_CONST(Instruction::CONST, 13u, (-1 << 16) + 1),
    881       DEF_CONST(Instruction::CONST, 14u, (-1 << 16) - 1),
    882       // FP reg constants.
    883       DEF_CONST(Instruction::CONST_4, 15u, 0),
    884       DEF_CONST(Instruction::CONST_4, 16u, 1),
    885       DEF_CONST(Instruction::CONST_4, 17u, -1),
    886       DEF_CONST(Instruction::CONST_16, 18u, 1 << 4),
    887       DEF_CONST(Instruction::CONST_16, 19u, -1 << 4),
    888       DEF_CONST(Instruction::CONST_16, 20u, (1 << 4) + 1),
    889       DEF_CONST(Instruction::CONST_16, 21u, (1 << 4) - 1),
    890       DEF_CONST(Instruction::CONST_16, 22u, -(1 << 4) + 1),
    891       DEF_CONST(Instruction::CONST_16, 23u, -(1 << 4) - 1),
    892       DEF_CONST(Instruction::CONST_HIGH16, 24u, 1),       // Effectively 1 << 16.
    893       DEF_CONST(Instruction::CONST_HIGH16, 25u, 0xffff),  // Effectively -1 << 16.
    894       DEF_CONST(Instruction::CONST, 26u, (1 << 16) + 1),
    895       DEF_CONST(Instruction::CONST, 27u, (1 << 16) - 1),
    896       DEF_CONST(Instruction::CONST, 28u, (-1 << 16) + 1),
    897       DEF_CONST(Instruction::CONST, 29u, (-1 << 16) - 1),
    898       // null reference constant.
    899       DEF_CONST(Instruction::CONST_4, 30u, 0),
    900   };
    901 
    902   PrepareMIRs(mirs);
    903   static_assert((arraysize(mirs) & 1) != 0, "missing null or unmatched fp/core");
    904   cu_.mir_graph->reg_location_[arraysize(mirs) - 1].ref = true;
    905   for (size_t i = arraysize(mirs) / 2u; i != arraysize(mirs) - 1; ++i) {
    906     cu_.mir_graph->reg_location_[mirs_[i].ssa_rep->defs[0]].fp = true;
    907   }
    908   PerformLVN();
    909   for (size_t i = 0u; i != mir_count_; ++i) {
    910     for (size_t j = i + 1u; j != mir_count_; ++j) {
    911       EXPECT_NE(value_names_[i], value_names_[j]) << i << " " << j;
    912     }
    913   }
    914 }
    915 
    916 }  // namespace art
    917