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 "compiler_internals.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   };
     32 
     33   struct SFieldDef {
     34     uint16_t field_idx;
     35     uintptr_t declaring_dex_file;
     36     uint16_t declaring_field_idx;
     37     bool is_volatile;
     38   };
     39 
     40   struct MIRDef {
     41     static constexpr size_t kMaxSsaDefs = 2;
     42     static constexpr size_t kMaxSsaUses = 4;
     43 
     44     Instruction::Code opcode;
     45     int64_t value;
     46     uint32_t field_info;
     47     size_t num_uses;
     48     int32_t uses[kMaxSsaUses];
     49     size_t num_defs;
     50     int32_t defs[kMaxSsaDefs];
     51   };
     52 
     53 #define DEF_CONST(opcode, reg, value) \
     54     { opcode, value, 0u, 0, { }, 1, { reg } }
     55 #define DEF_CONST_WIDE(opcode, reg, value) \
     56     { opcode, value, 0u, 0, { }, 2, { reg, reg + 1 } }
     57 #define DEF_CONST_STRING(opcode, reg, index) \
     58     { opcode, index, 0u, 0, { }, 1, { reg } }
     59 #define DEF_IGET(opcode, reg, obj, field_info) \
     60     { opcode, 0u, field_info, 1, { obj }, 1, { reg } }
     61 #define DEF_IGET_WIDE(opcode, reg, obj, field_info) \
     62     { opcode, 0u, field_info, 1, { obj }, 2, { reg, reg + 1 } }
     63 #define DEF_IPUT(opcode, reg, obj, field_info) \
     64     { opcode, 0u, field_info, 2, { reg, obj }, 0, { } }
     65 #define DEF_IPUT_WIDE(opcode, reg, obj, field_info) \
     66     { opcode, 0u, field_info, 3, { reg, reg + 1, obj }, 0, { } }
     67 #define DEF_SGET(opcode, reg, field_info) \
     68     { opcode, 0u, field_info, 0, { }, 1, { reg } }
     69 #define DEF_SGET_WIDE(opcode, reg, field_info) \
     70     { opcode, 0u, field_info, 0, { }, 2, { reg, reg + 1 } }
     71 #define DEF_SPUT(opcode, reg, field_info) \
     72     { opcode, 0u, field_info, 1, { reg }, 0, { } }
     73 #define DEF_SPUT_WIDE(opcode, reg, field_info) \
     74     { opcode, 0u, field_info, 2, { reg, reg + 1 }, 0, { } }
     75 #define DEF_AGET(opcode, reg, obj, idx) \
     76     { opcode, 0u, 0u, 2, { obj, idx }, 1, { reg } }
     77 #define DEF_AGET_WIDE(opcode, reg, obj, idx) \
     78     { opcode, 0u, 0u, 2, { obj, idx }, 2, { reg, reg + 1 } }
     79 #define DEF_APUT(opcode, reg, obj, idx) \
     80     { opcode, 0u, 0u, 3, { reg, obj, idx }, 0, { } }
     81 #define DEF_APUT_WIDE(opcode, reg, obj, idx) \
     82     { opcode, 0u, 0u, 4, { reg, reg + 1, obj, idx }, 0, { } }
     83 #define DEF_INVOKE1(opcode, reg) \
     84     { opcode, 0u, 0u, 1, { reg }, 0, { } }
     85 #define DEF_UNIQUE_REF(opcode, reg) \
     86     { opcode, 0u, 0u, 0, { }, 1, { reg } }  // CONST_CLASS, CONST_STRING, NEW_ARRAY, ...
     87 
     88   void DoPrepareIFields(const IFieldDef* defs, size_t count) {
     89     cu_.mir_graph->ifield_lowering_infos_.Reset();
     90     cu_.mir_graph->ifield_lowering_infos_.Resize(count);
     91     for (size_t i = 0u; i != count; ++i) {
     92       const IFieldDef* def = &defs[i];
     93       MirIFieldLoweringInfo field_info(def->field_idx);
     94       if (def->declaring_dex_file != 0u) {
     95         field_info.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file);
     96         field_info.declaring_field_idx_ = def->declaring_field_idx;
     97         field_info.flags_ = 0u |  // Without kFlagIsStatic.
     98             (def->is_volatile ? MirIFieldLoweringInfo::kFlagIsVolatile : 0u);
     99       }
    100       cu_.mir_graph->ifield_lowering_infos_.Insert(field_info);
    101     }
    102   }
    103 
    104   template <size_t count>
    105   void PrepareIFields(const IFieldDef (&defs)[count]) {
    106     DoPrepareIFields(defs, count);
    107   }
    108 
    109   void DoPrepareSFields(const SFieldDef* defs, size_t count) {
    110     cu_.mir_graph->sfield_lowering_infos_.Reset();
    111     cu_.mir_graph->sfield_lowering_infos_.Resize(count);
    112     for (size_t i = 0u; i != count; ++i) {
    113       const SFieldDef* def = &defs[i];
    114       MirSFieldLoweringInfo field_info(def->field_idx);
    115       // Mark even unresolved fields as initialized.
    116       field_info.flags_ = MirSFieldLoweringInfo::kFlagIsStatic |
    117           MirSFieldLoweringInfo::kFlagIsInitialized;
    118       if (def->declaring_dex_file != 0u) {
    119         field_info.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file);
    120         field_info.declaring_field_idx_ = def->declaring_field_idx;
    121         field_info.flags_ |= (def->is_volatile ? MirSFieldLoweringInfo::kFlagIsVolatile : 0u);
    122       }
    123       cu_.mir_graph->sfield_lowering_infos_.Insert(field_info);
    124     }
    125   }
    126 
    127   template <size_t count>
    128   void PrepareSFields(const SFieldDef (&defs)[count]) {
    129     DoPrepareSFields(defs, count);
    130   }
    131 
    132   void DoPrepareMIRs(const MIRDef* defs, size_t count) {
    133     mir_count_ = count;
    134     mirs_ = reinterpret_cast<MIR*>(cu_.arena.Alloc(sizeof(MIR) * count, kArenaAllocMIR));
    135     ssa_reps_.resize(count);
    136     for (size_t i = 0u; i != count; ++i) {
    137       const MIRDef* def = &defs[i];
    138       MIR* mir = &mirs_[i];
    139       mir->dalvikInsn.opcode = def->opcode;
    140       mir->dalvikInsn.vB = static_cast<int32_t>(def->value);
    141       mir->dalvikInsn.vB_wide = def->value;
    142       if (def->opcode >= Instruction::IGET && def->opcode <= Instruction::IPUT_SHORT) {
    143         ASSERT_LT(def->field_info, cu_.mir_graph->ifield_lowering_infos_.Size());
    144         mir->meta.ifield_lowering_info = def->field_info;
    145       } else if (def->opcode >= Instruction::SGET && def->opcode <= Instruction::SPUT_SHORT) {
    146         ASSERT_LT(def->field_info, cu_.mir_graph->sfield_lowering_infos_.Size());
    147         mir->meta.sfield_lowering_info = def->field_info;
    148       }
    149       mir->ssa_rep = &ssa_reps_[i];
    150       mir->ssa_rep->num_uses = def->num_uses;
    151       mir->ssa_rep->uses = const_cast<int32_t*>(def->uses);  // Not modified by LVN.
    152       mir->ssa_rep->fp_use = nullptr;  // Not used by LVN.
    153       mir->ssa_rep->num_defs = def->num_defs;
    154       mir->ssa_rep->defs = const_cast<int32_t*>(def->defs);  // Not modified by LVN.
    155       mir->ssa_rep->fp_def = nullptr;  // Not used by LVN.
    156       mir->dalvikInsn.opcode = def->opcode;
    157       mir->offset = i;  // LVN uses offset only for debug output
    158       mir->optimization_flags = 0u;
    159 
    160       if (i != 0u) {
    161         mirs_[i - 1u].next = mir;
    162       }
    163     }
    164     mirs_[count - 1u].next = nullptr;
    165   }
    166 
    167   template <size_t count>
    168   void PrepareMIRs(const MIRDef (&defs)[count]) {
    169     DoPrepareMIRs(defs, count);
    170   }
    171 
    172   void MakeSFieldUninitialized(uint32_t sfield_index) {
    173     CHECK_LT(sfield_index, cu_.mir_graph->sfield_lowering_infos_.Size());
    174     cu_.mir_graph->sfield_lowering_infos_.GetRawStorage()[sfield_index].flags_ &=
    175         ~MirSFieldLoweringInfo::kFlagIsInitialized;
    176   }
    177 
    178   void PerformLVN() {
    179     value_names_.resize(mir_count_);
    180     for (size_t i = 0; i != mir_count_; ++i) {
    181       value_names_[i] =  lvn_->GetValueNumber(&mirs_[i]);
    182     }
    183     EXPECT_TRUE(gvn_->Good());
    184   }
    185 
    186   LocalValueNumberingTest()
    187       : pool_(),
    188         cu_(&pool_),
    189         mir_count_(0u),
    190         mirs_(nullptr),
    191         ssa_reps_(),
    192         allocator_(),
    193         gvn_(),
    194         lvn_(),
    195         value_names_() {
    196     cu_.mir_graph.reset(new MIRGraph(&cu_, &cu_.arena));
    197     allocator_.reset(ScopedArenaAllocator::Create(&cu_.arena_stack));
    198     gvn_.reset(new (allocator_.get()) GlobalValueNumbering(&cu_, allocator_.get()));
    199     lvn_.reset(new (allocator_.get()) LocalValueNumbering(gvn_.get(), 0u, allocator_.get()));
    200     gvn_->AllowModifications();
    201   }
    202 
    203   ArenaPool pool_;
    204   CompilationUnit cu_;
    205   size_t mir_count_;
    206   MIR* mirs_;
    207   std::vector<SSARepresentation> ssa_reps_;
    208   std::unique_ptr<ScopedArenaAllocator> allocator_;
    209   std::unique_ptr<GlobalValueNumbering> gvn_;
    210   std::unique_ptr<LocalValueNumbering> lvn_;
    211   std::vector<uint16_t> value_names_;
    212 };
    213 
    214 TEST_F(LocalValueNumberingTest, IGetIGetInvokeIGet) {
    215   static const IFieldDef ifields[] = {
    216       { 1u, 1u, 1u, false },
    217   };
    218   static const MIRDef mirs[] = {
    219       DEF_IGET(Instruction::IGET, 0u, 10u, 0u),
    220       DEF_IGET(Instruction::IGET, 1u, 10u, 0u),
    221       DEF_INVOKE1(Instruction::INVOKE_VIRTUAL, 11u),
    222       DEF_IGET(Instruction::IGET, 2u, 10u, 0u),
    223   };
    224 
    225   PrepareIFields(ifields);
    226   PrepareMIRs(mirs);
    227   PerformLVN();
    228   ASSERT_EQ(value_names_.size(), 4u);
    229   EXPECT_EQ(value_names_[0], value_names_[1]);
    230   EXPECT_NE(value_names_[0], value_names_[3]);
    231   EXPECT_EQ(mirs_[0].optimization_flags, 0u);
    232   EXPECT_EQ(mirs_[1].optimization_flags, MIR_IGNORE_NULL_CHECK);
    233   EXPECT_EQ(mirs_[2].optimization_flags, 0u);
    234   EXPECT_EQ(mirs_[3].optimization_flags, MIR_IGNORE_NULL_CHECK);
    235 }
    236 
    237 TEST_F(LocalValueNumberingTest, IGetIPutIGetIGetIGet) {
    238   static const IFieldDef ifields[] = {
    239       { 1u, 1u, 1u, false },
    240       { 2u, 1u, 2u, false },
    241   };
    242   static const MIRDef mirs[] = {
    243       DEF_IGET(Instruction::IGET_OBJECT, 0u, 10u, 0u),
    244       DEF_IPUT(Instruction::IPUT_OBJECT, 1u, 11u, 0u),  // May alias.
    245       DEF_IGET(Instruction::IGET_OBJECT, 2u, 10u, 0u),
    246       DEF_IGET(Instruction::IGET, 3u,  0u, 1u),
    247       DEF_IGET(Instruction::IGET, 4u,  2u, 1u),
    248   };
    249 
    250   PrepareIFields(ifields);
    251   PrepareMIRs(mirs);
    252   PerformLVN();
    253   ASSERT_EQ(value_names_.size(), 5u);
    254   EXPECT_NE(value_names_[0], value_names_[2]);
    255   EXPECT_NE(value_names_[3], value_names_[4]);
    256   for (size_t i = 0; i != arraysize(mirs); ++i) {
    257     EXPECT_EQ((i == 2u) ? MIR_IGNORE_NULL_CHECK : 0,
    258               mirs_[i].optimization_flags) << i;
    259   }
    260 }
    261 
    262 TEST_F(LocalValueNumberingTest, UniquePreserve1) {
    263   static const IFieldDef ifields[] = {
    264       { 1u, 1u, 1u, false },
    265   };
    266   static const MIRDef mirs[] = {
    267       DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 10u),
    268       DEF_IGET(Instruction::IGET, 0u, 10u, 0u),
    269       DEF_IPUT(Instruction::IPUT, 1u, 11u, 0u),  // No aliasing since 10u is unique.
    270       DEF_IGET(Instruction::IGET, 2u, 10u, 0u),
    271   };
    272 
    273   PrepareIFields(ifields);
    274   PrepareMIRs(mirs);
    275   PerformLVN();
    276   ASSERT_EQ(value_names_.size(), 4u);
    277   EXPECT_EQ(value_names_[1], value_names_[3]);
    278   for (size_t i = 0; i != arraysize(mirs); ++i) {
    279     EXPECT_EQ((i == 1u || i == 3u) ? MIR_IGNORE_NULL_CHECK : 0,
    280               mirs_[i].optimization_flags) << i;
    281   }
    282 }
    283 
    284 TEST_F(LocalValueNumberingTest, UniquePreserve2) {
    285   static const IFieldDef ifields[] = {
    286       { 1u, 1u, 1u, false },
    287   };
    288   static const MIRDef mirs[] = {
    289       DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 11u),
    290       DEF_IGET(Instruction::IGET, 0u, 10u, 0u),
    291       DEF_IPUT(Instruction::IPUT, 1u, 11u, 0u),  // No aliasing since 11u is unique.
    292       DEF_IGET(Instruction::IGET, 2u, 10u, 0u),
    293   };
    294 
    295   PrepareIFields(ifields);
    296   PrepareMIRs(mirs);
    297   PerformLVN();
    298   ASSERT_EQ(value_names_.size(), 4u);
    299   EXPECT_EQ(value_names_[1], value_names_[3]);
    300   for (size_t i = 0; i != arraysize(mirs); ++i) {
    301     EXPECT_EQ((i == 2u || i == 3u) ? MIR_IGNORE_NULL_CHECK : 0,
    302               mirs_[i].optimization_flags) << i;
    303   }
    304 }
    305 
    306 TEST_F(LocalValueNumberingTest, UniquePreserveAndEscape) {
    307   static const IFieldDef ifields[] = {
    308       { 1u, 1u, 1u, false },
    309   };
    310   static const MIRDef mirs[] = {
    311       DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 10u),
    312       DEF_IGET(Instruction::IGET, 0u, 10u, 0u),
    313       DEF_INVOKE1(Instruction::INVOKE_VIRTUAL, 11u),  // 10u still unique.
    314       DEF_IGET(Instruction::IGET, 2u, 10u, 0u),
    315       DEF_INVOKE1(Instruction::INVOKE_VIRTUAL, 10u),  // 10u not unique anymore.
    316       DEF_IGET(Instruction::IGET, 3u, 10u, 0u),
    317   };
    318 
    319   PrepareIFields(ifields);
    320   PrepareMIRs(mirs);
    321   PerformLVN();
    322   ASSERT_EQ(value_names_.size(), 6u);
    323   EXPECT_EQ(value_names_[1], value_names_[3]);
    324   EXPECT_NE(value_names_[1], value_names_[5]);
    325   for (size_t i = 0; i != arraysize(mirs); ++i) {
    326     EXPECT_EQ((i == 1u || i == 3u || i == 4u || i == 5u) ? MIR_IGNORE_NULL_CHECK : 0,
    327               mirs_[i].optimization_flags) << i;
    328   }
    329 }
    330 
    331 TEST_F(LocalValueNumberingTest, Volatile) {
    332   static const IFieldDef ifields[] = {
    333       { 1u, 1u, 1u, false },
    334       { 2u, 1u, 2u, true },
    335   };
    336   static const MIRDef mirs[] = {
    337       DEF_IGET(Instruction::IGET, 0u, 10u, 1u),  // Volatile.
    338       DEF_IGET(Instruction::IGET, 1u,  0u, 0u),  // Non-volatile.
    339       DEF_IGET(Instruction::IGET, 2u, 10u, 1u),  // Volatile.
    340       DEF_IGET(Instruction::IGET, 3u,  2u, 1u),  // Non-volatile.
    341   };
    342 
    343   PrepareIFields(ifields);
    344   PrepareMIRs(mirs);
    345   PerformLVN();
    346   ASSERT_EQ(value_names_.size(), 4u);
    347   EXPECT_NE(value_names_[0], value_names_[2]);  // Volatile has always different value name.
    348   EXPECT_NE(value_names_[1], value_names_[3]);  // Used different base because of volatile.
    349   for (size_t i = 0; i != arraysize(mirs); ++i) {
    350     EXPECT_EQ((i == 2u) ? MIR_IGNORE_NULL_CHECK : 0,
    351               mirs_[i].optimization_flags) << i;
    352   }
    353 }
    354 
    355 TEST_F(LocalValueNumberingTest, UnresolvedIField) {
    356   static const IFieldDef ifields[] = {
    357       { 1u, 1u, 1u, false },  // Resolved field #1.
    358       { 2u, 1u, 2u, false },  // Resolved field #2.
    359       { 3u, 0u, 0u, false },  // Unresolved field.
    360   };
    361   static const MIRDef mirs[] = {
    362       DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 20u),
    363       DEF_IGET(Instruction::IGET, 1u, 20u, 0u),             // Resolved field #1, unique object.
    364       DEF_IGET(Instruction::IGET, 2u, 21u, 0u),             // Resolved field #1.
    365       DEF_IGET_WIDE(Instruction::IGET_WIDE, 3u, 21u, 1u),   // Resolved field #2.
    366       DEF_IGET(Instruction::IGET, 4u, 22u, 2u),             // IGET doesn't clobber anything.
    367       DEF_IGET(Instruction::IGET, 5u, 20u, 0u),             // Resolved field #1, unique object.
    368       DEF_IGET(Instruction::IGET, 6u, 21u, 0u),             // Resolved field #1.
    369       DEF_IGET_WIDE(Instruction::IGET_WIDE, 7u, 21u, 1u),   // Resolved field #2.
    370       DEF_IPUT(Instruction::IPUT, 8u, 22u, 2u),             // IPUT clobbers field #1 (#2 is wide).
    371       DEF_IGET(Instruction::IGET, 9u, 20u, 0u),             // Resolved field #1, unique object.
    372       DEF_IGET(Instruction::IGET, 10u, 21u, 0u),            // Resolved field #1, new value name.
    373       DEF_IGET_WIDE(Instruction::IGET_WIDE, 11u, 21u, 1u),  // Resolved field #2.
    374       DEF_IGET_WIDE(Instruction::IGET_WIDE, 12u, 20u, 1u),  // Resolved field #2, unique object.
    375       DEF_IPUT(Instruction::IPUT, 13u, 20u, 2u),            // IPUT clobbers field #1 (#2 is wide).
    376       DEF_IGET(Instruction::IGET, 14u, 20u, 0u),            // Resolved field #1, unique object.
    377       DEF_IGET_WIDE(Instruction::IGET_WIDE, 15u, 20u, 1u),  // Resolved field #2, unique object.
    378   };
    379 
    380   PrepareIFields(ifields);
    381   PrepareMIRs(mirs);
    382   PerformLVN();
    383   ASSERT_EQ(value_names_.size(), 16u);
    384   EXPECT_EQ(value_names_[1], value_names_[5]);
    385   EXPECT_EQ(value_names_[2], value_names_[6]);
    386   EXPECT_EQ(value_names_[3], value_names_[7]);
    387   EXPECT_EQ(value_names_[1], value_names_[9]);
    388   EXPECT_NE(value_names_[2], value_names_[10]);  // This aliased with unresolved IPUT.
    389   EXPECT_EQ(value_names_[3], value_names_[11]);
    390   EXPECT_EQ(value_names_[12], value_names_[15]);
    391   EXPECT_NE(value_names_[1], value_names_[14]);  // This aliased with unresolved IPUT.
    392   EXPECT_EQ(mirs_[0].optimization_flags, 0u);
    393   EXPECT_EQ(mirs_[1].optimization_flags, MIR_IGNORE_NULL_CHECK);
    394   EXPECT_EQ(mirs_[2].optimization_flags, 0u);
    395   EXPECT_EQ(mirs_[3].optimization_flags, MIR_IGNORE_NULL_CHECK);
    396   EXPECT_EQ(mirs_[4].optimization_flags, 0u);
    397   for (size_t i = 5u; i != mir_count_; ++i) {
    398     EXPECT_EQ((i == 1u || i == 3u || i >=5u) ? MIR_IGNORE_NULL_CHECK : 0,
    399               mirs_[i].optimization_flags) << i;
    400   }
    401 }
    402 
    403 TEST_F(LocalValueNumberingTest, UnresolvedSField) {
    404   static const SFieldDef sfields[] = {
    405       { 1u, 1u, 1u, false },  // Resolved field #1.
    406       { 2u, 1u, 2u, false },  // Resolved field #2.
    407       { 3u, 0u, 0u, false },  // Unresolved field.
    408   };
    409   static const MIRDef mirs[] = {
    410       DEF_SGET(Instruction::SGET, 0u, 0u),            // Resolved field #1.
    411       DEF_SGET_WIDE(Instruction::SGET_WIDE, 1u, 1u),  // Resolved field #2.
    412       DEF_SGET(Instruction::SGET, 2u, 2u),            // SGET doesn't clobber anything.
    413       DEF_SGET(Instruction::SGET, 3u, 0u),            // Resolved field #1.
    414       DEF_SGET_WIDE(Instruction::SGET_WIDE, 4u, 1u),  // Resolved field #2.
    415       DEF_SPUT(Instruction::SPUT, 5u, 2u),            // SPUT clobbers field #1 (#2 is wide).
    416       DEF_SGET(Instruction::SGET, 6u, 0u),            // Resolved field #1.
    417       DEF_SGET_WIDE(Instruction::SGET_WIDE, 7u, 1u),  // Resolved field #2.
    418   };
    419 
    420   PrepareSFields(sfields);
    421   PrepareMIRs(mirs);
    422   PerformLVN();
    423   ASSERT_EQ(value_names_.size(), 8u);
    424   EXPECT_EQ(value_names_[0], value_names_[3]);
    425   EXPECT_EQ(value_names_[1], value_names_[4]);
    426   EXPECT_NE(value_names_[0], value_names_[6]);  // This aliased with unresolved IPUT.
    427   EXPECT_EQ(value_names_[1], value_names_[7]);
    428   for (size_t i = 0u; i != mir_count_; ++i) {
    429     EXPECT_EQ(0, mirs_[i].optimization_flags) << i;
    430   }
    431 }
    432 
    433 TEST_F(LocalValueNumberingTest, UninitializedSField) {
    434   static const IFieldDef ifields[] = {
    435       { 1u, 1u, 1u, false },  // Resolved field #1.
    436   };
    437   static const SFieldDef sfields[] = {
    438       { 1u, 1u, 1u, false },  // Resolved field #1.
    439       { 2u, 1u, 2u, false },  // Resolved field #2; uninitialized.
    440   };
    441   static const MIRDef mirs[] = {
    442       DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 200u),
    443       DEF_IGET(Instruction::IGET, 1u, 100u, 0u),
    444       DEF_IGET(Instruction::IGET, 2u, 200u, 0u),
    445       DEF_SGET(Instruction::SGET, 3u, 0u),
    446       DEF_SGET(Instruction::SGET, 4u, 1u),            // Can call <clinit>().
    447       DEF_IGET(Instruction::IGET, 5u, 100u, 0u),      // Differs from 1u.
    448       DEF_IGET(Instruction::IGET, 6u, 200u, 0u),      // Same as 2u.
    449       DEF_SGET(Instruction::SGET, 7u, 0u),            // Differs from 3u.
    450   };
    451 
    452   PrepareIFields(ifields);
    453   PrepareSFields(sfields);
    454   MakeSFieldUninitialized(1u);
    455   PrepareMIRs(mirs);
    456   PerformLVN();
    457   ASSERT_EQ(value_names_.size(), 8u);
    458   EXPECT_NE(value_names_[1], value_names_[5]);
    459   EXPECT_EQ(value_names_[2], value_names_[6]);
    460   EXPECT_NE(value_names_[3], value_names_[7]);
    461 }
    462 
    463 TEST_F(LocalValueNumberingTest, ConstString) {
    464   static const MIRDef mirs[] = {
    465       DEF_CONST_STRING(Instruction::CONST_STRING, 0u, 0u),
    466       DEF_CONST_STRING(Instruction::CONST_STRING, 1u, 0u),
    467       DEF_CONST_STRING(Instruction::CONST_STRING, 2u, 2u),
    468       DEF_CONST_STRING(Instruction::CONST_STRING, 3u, 0u),
    469       DEF_INVOKE1(Instruction::INVOKE_DIRECT, 2u),
    470       DEF_CONST_STRING(Instruction::CONST_STRING, 4u, 2u),
    471   };
    472 
    473   PrepareMIRs(mirs);
    474   PerformLVN();
    475   ASSERT_EQ(value_names_.size(), 6u);
    476   EXPECT_EQ(value_names_[1], value_names_[0]);
    477   EXPECT_NE(value_names_[2], value_names_[0]);
    478   EXPECT_EQ(value_names_[3], value_names_[0]);
    479   EXPECT_EQ(value_names_[5], value_names_[2]);
    480 }
    481 
    482 TEST_F(LocalValueNumberingTest, SameValueInDifferentMemoryLocations) {
    483   static const IFieldDef ifields[] = {
    484       { 1u, 1u, 1u, false },
    485       { 2u, 1u, 2u, false },
    486   };
    487   static const SFieldDef sfields[] = {
    488       { 3u, 1u, 3u, false },
    489   };
    490   static const MIRDef mirs[] = {
    491       DEF_UNIQUE_REF(Instruction::NEW_ARRAY, 201u),
    492       DEF_IGET(Instruction::IGET, 0u, 100u, 0u),
    493       DEF_IPUT(Instruction::IPUT, 0u, 100u, 1u),
    494       DEF_IPUT(Instruction::IPUT, 0u, 101u, 1u),
    495       DEF_APUT(Instruction::APUT, 0u, 200u, 300u),
    496       DEF_APUT(Instruction::APUT, 0u, 200u, 301u),
    497       DEF_APUT(Instruction::APUT, 0u, 201u, 300u),
    498       DEF_APUT(Instruction::APUT, 0u, 201u, 301u),
    499       DEF_SPUT(Instruction::SPUT, 0u, 0u),
    500       DEF_IGET(Instruction::IGET, 9u, 100u, 0u),
    501       DEF_IGET(Instruction::IGET, 10u, 100u, 1u),
    502       DEF_IGET(Instruction::IGET, 11u, 101u, 1u),
    503       DEF_AGET(Instruction::AGET, 12u, 200u, 300u),
    504       DEF_AGET(Instruction::AGET, 13u, 200u, 301u),
    505       DEF_AGET(Instruction::AGET, 14u, 201u, 300u),
    506       DEF_AGET(Instruction::AGET, 15u, 201u, 301u),
    507       DEF_SGET(Instruction::SGET, 16u, 0u),
    508   };
    509 
    510   PrepareIFields(ifields);
    511   PrepareSFields(sfields);
    512   PrepareMIRs(mirs);
    513   PerformLVN();
    514   ASSERT_EQ(value_names_.size(), 17u);
    515   for (size_t i = 9; i != arraysize(mirs); ++i) {
    516     EXPECT_EQ(value_names_[1], value_names_[i]) << i;
    517   }
    518   for (size_t i = 0; i != arraysize(mirs); ++i) {
    519     int expected_flags =
    520         ((i == 2u || (i >= 5u && i <= 7u) || (i >= 9u && i <= 15u)) ? MIR_IGNORE_NULL_CHECK : 0) |
    521         ((i >= 12u && i <= 15u) ? MIR_IGNORE_RANGE_CHECK : 0);
    522     EXPECT_EQ(expected_flags, mirs_[i].optimization_flags) << i;
    523   }
    524 }
    525 
    526 TEST_F(LocalValueNumberingTest, UniqueArrayAliasing) {
    527   static const MIRDef mirs[] = {
    528       DEF_UNIQUE_REF(Instruction::NEW_ARRAY, 20u),
    529       DEF_AGET(Instruction::AGET, 1u, 20u, 40u),
    530       DEF_APUT(Instruction::APUT, 2u, 20u, 41u),  // May alias with index for sreg 40u.
    531       DEF_AGET(Instruction::AGET, 3u, 20u, 40u),
    532   };
    533 
    534   PrepareMIRs(mirs);
    535   PerformLVN();
    536   ASSERT_EQ(value_names_.size(), 4u);
    537   EXPECT_NE(value_names_[1], value_names_[3]);
    538   for (size_t i = 0; i != arraysize(mirs); ++i) {
    539     int expected_flags =
    540         ((i >= 1u) ? MIR_IGNORE_NULL_CHECK : 0) |
    541         ((i == 3u) ? MIR_IGNORE_RANGE_CHECK : 0);
    542     EXPECT_EQ(expected_flags, mirs_[i].optimization_flags) << i;
    543   }
    544 }
    545 
    546 TEST_F(LocalValueNumberingTest, EscapingRefs) {
    547   static const IFieldDef ifields[] = {
    548       { 1u, 1u, 1u, false },  // Field #1.
    549       { 2u, 1u, 2u, false },  // Field #2.
    550       { 3u, 1u, 3u, false },  // Reference field for storing escaping refs.
    551       { 4u, 1u, 4u, false },  // Wide.
    552       { 5u, 0u, 0u, false },  // Unresolved field, int.
    553       { 6u, 0u, 0u, false },  // Unresolved field, wide.
    554   };
    555   static const MIRDef mirs[] = {
    556       DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 20u),
    557       DEF_IGET(Instruction::IGET, 1u, 20u, 0u),
    558       DEF_IGET(Instruction::IGET, 2u, 20u, 1u),
    559       DEF_IPUT(Instruction::IPUT_OBJECT, 20u, 30u, 2u),      // Ref escapes.
    560       DEF_IGET(Instruction::IGET, 4u, 20u, 0u),
    561       DEF_IGET(Instruction::IGET, 5u, 20u, 1u),
    562       DEF_IPUT(Instruction::IPUT, 6u, 31u, 0u),              // May alias with field #1.
    563       DEF_IGET(Instruction::IGET, 7u, 20u, 0u),              // New value.
    564       DEF_IGET(Instruction::IGET, 8u, 20u, 1u),              // Still the same.
    565       DEF_IPUT_WIDE(Instruction::IPUT_WIDE, 9u, 31u, 3u),    // No aliasing, different type.
    566       DEF_IGET(Instruction::IGET, 10u, 20u, 0u),
    567       DEF_IGET(Instruction::IGET, 11u, 20u, 1u),
    568       DEF_IPUT_WIDE(Instruction::IPUT_WIDE, 12u, 31u, 5u),   // No aliasing, different type.
    569       DEF_IGET(Instruction::IGET, 13u, 20u, 0u),
    570       DEF_IGET(Instruction::IGET, 14u, 20u, 1u),
    571       DEF_IPUT(Instruction::IPUT, 15u, 31u, 4u),             // Aliasing, same type.
    572       DEF_IGET(Instruction::IGET, 16u, 20u, 0u),
    573       DEF_IGET(Instruction::IGET, 17u, 20u, 1u),
    574   };
    575 
    576   PrepareIFields(ifields);
    577   PrepareMIRs(mirs);
    578   PerformLVN();
    579   ASSERT_EQ(value_names_.size(), 18u);
    580   EXPECT_EQ(value_names_[1], value_names_[4]);
    581   EXPECT_EQ(value_names_[2], value_names_[5]);
    582   EXPECT_NE(value_names_[4], value_names_[7]);  // New value.
    583   EXPECT_EQ(value_names_[5], value_names_[8]);
    584   EXPECT_EQ(value_names_[7], value_names_[10]);
    585   EXPECT_EQ(value_names_[8], value_names_[11]);
    586   EXPECT_EQ(value_names_[10], value_names_[13]);
    587   EXPECT_EQ(value_names_[11], value_names_[14]);
    588   EXPECT_NE(value_names_[13], value_names_[16]);  // New value.
    589   EXPECT_NE(value_names_[14], value_names_[17]);  // New value.
    590   for (size_t i = 0u; i != mir_count_; ++i) {
    591     int expected = (i != 0u && i != 3u && i != 6u) ? MIR_IGNORE_NULL_CHECK : 0;
    592     EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
    593   }
    594 }
    595 
    596 TEST_F(LocalValueNumberingTest, EscapingArrayRefs) {
    597   static const MIRDef mirs[] = {
    598       DEF_UNIQUE_REF(Instruction::NEW_ARRAY, 20u),
    599       DEF_AGET(Instruction::AGET, 1u, 20u, 40u),
    600       DEF_AGET(Instruction::AGET, 2u, 20u, 41u),
    601       DEF_APUT(Instruction::APUT_OBJECT, 20u, 30u, 42u),    // Array ref escapes.
    602       DEF_AGET(Instruction::AGET, 4u, 20u, 40u),
    603       DEF_AGET(Instruction::AGET, 5u, 20u, 41u),
    604       DEF_APUT_WIDE(Instruction::APUT_WIDE, 6u, 31u, 43u),  // No aliasing, different type.
    605       DEF_AGET(Instruction::AGET, 7u, 20u, 40u),
    606       DEF_AGET(Instruction::AGET, 8u, 20u, 41u),
    607       DEF_APUT(Instruction::APUT, 9u, 32u, 40u),            // May alias with all elements.
    608       DEF_AGET(Instruction::AGET, 10u, 20u, 40u),           // New value (same index name).
    609       DEF_AGET(Instruction::AGET, 11u, 20u, 41u),           // New value (different index name).
    610   };
    611 
    612   PrepareMIRs(mirs);
    613   PerformLVN();
    614   ASSERT_EQ(value_names_.size(), 12u);
    615   EXPECT_EQ(value_names_[1], value_names_[4]);
    616   EXPECT_EQ(value_names_[2], value_names_[5]);
    617   EXPECT_EQ(value_names_[4], value_names_[7]);
    618   EXPECT_EQ(value_names_[5], value_names_[8]);
    619   EXPECT_NE(value_names_[7], value_names_[10]);  // New value.
    620   EXPECT_NE(value_names_[8], value_names_[11]);  // New value.
    621   for (size_t i = 0u; i != mir_count_; ++i) {
    622     int expected =
    623         ((i != 0u && i != 3u && i != 6u && i != 9u) ? MIR_IGNORE_NULL_CHECK : 0u) |
    624         ((i >= 4 && i != 6u && i != 9u) ? MIR_IGNORE_RANGE_CHECK : 0u);
    625     EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
    626   }
    627 }
    628 
    629 TEST_F(LocalValueNumberingTest, StoringSameValueKeepsMemoryVersion) {
    630   static const IFieldDef ifields[] = {
    631       { 1u, 1u, 1u, false },
    632       { 2u, 1u, 2u, false },
    633   };
    634   static const SFieldDef sfields[] = {
    635       { 2u, 1u, 2u, false },
    636   };
    637   static const MIRDef mirs[] = {
    638       DEF_IGET(Instruction::IGET, 0u, 30u, 0u),
    639       DEF_IGET(Instruction::IGET, 1u, 31u, 0u),
    640       DEF_IPUT(Instruction::IPUT, 1u, 31u, 0u),            // Store the same value.
    641       DEF_IGET(Instruction::IGET, 3u, 30u, 0u),
    642       DEF_AGET(Instruction::AGET, 4u, 32u, 40u),
    643       DEF_AGET(Instruction::AGET, 5u, 33u, 40u),
    644       DEF_APUT(Instruction::APUT, 5u, 33u, 40u),           // Store the same value.
    645       DEF_AGET(Instruction::AGET, 7u, 32u, 40u),
    646       DEF_SGET(Instruction::SGET, 8u, 0u),
    647       DEF_SPUT(Instruction::SPUT, 8u, 0u),                 // Store the same value.
    648       DEF_SGET(Instruction::SGET, 10u, 0u),
    649       DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 50u),      // Test with unique references.
    650       { Instruction::FILLED_NEW_ARRAY, 0, 0u, 2, { 12u, 13u }, 0, { } },
    651       DEF_UNIQUE_REF(Instruction::MOVE_RESULT_OBJECT, 51u),
    652       DEF_IGET(Instruction::IGET, 14u, 50u, 0u),
    653       DEF_IGET(Instruction::IGET, 15u, 50u, 1u),
    654       DEF_IPUT(Instruction::IPUT, 15u, 50u, 1u),           // Store the same value.
    655       DEF_IGET(Instruction::IGET, 17u, 50u, 0u),
    656       DEF_AGET(Instruction::AGET, 18u, 51u, 40u),
    657       DEF_AGET(Instruction::AGET, 19u, 51u, 41u),
    658       DEF_APUT(Instruction::APUT, 19u, 51u, 41u),          // Store the same value.
    659       DEF_AGET(Instruction::AGET, 21u, 51u, 40u),
    660   };
    661 
    662   PrepareIFields(ifields);
    663   PrepareSFields(sfields);
    664   PrepareMIRs(mirs);
    665   PerformLVN();
    666   ASSERT_EQ(value_names_.size(), 22u);
    667   EXPECT_NE(value_names_[0], value_names_[1]);
    668   EXPECT_EQ(value_names_[0], value_names_[3]);
    669   EXPECT_NE(value_names_[4], value_names_[5]);
    670   EXPECT_EQ(value_names_[4], value_names_[7]);
    671   EXPECT_EQ(value_names_[8], value_names_[10]);
    672   EXPECT_NE(value_names_[14], value_names_[15]);
    673   EXPECT_EQ(value_names_[14], value_names_[17]);
    674   EXPECT_NE(value_names_[18], value_names_[19]);
    675   EXPECT_EQ(value_names_[18], value_names_[21]);
    676   for (size_t i = 0u; i != mir_count_; ++i) {
    677     int expected =
    678         ((i == 2u || i == 3u || i == 6u || i == 7u || (i >= 14u)) ? MIR_IGNORE_NULL_CHECK : 0u) |
    679         ((i == 6u || i == 7u || i >= 20u) ? MIR_IGNORE_RANGE_CHECK : 0u);
    680     EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
    681   }
    682 }
    683 
    684 TEST_F(LocalValueNumberingTest, FilledNewArrayTracking) {
    685   if (!kLocalValueNumberingEnableFilledNewArrayTracking) {
    686     // Feature disabled.
    687     return;
    688   }
    689   static const MIRDef mirs[] = {
    690       DEF_CONST(Instruction::CONST, 0u, 100),
    691       DEF_CONST(Instruction::CONST, 1u, 200),
    692       { Instruction::FILLED_NEW_ARRAY, 0, 0u, 2, { 0u, 1u }, 0, { } },
    693       DEF_UNIQUE_REF(Instruction::MOVE_RESULT_OBJECT, 10u),
    694       DEF_CONST(Instruction::CONST, 20u, 0),
    695       DEF_CONST(Instruction::CONST, 21u, 1),
    696       DEF_AGET(Instruction::AGET, 6u, 10u, 20u),
    697       DEF_AGET(Instruction::AGET, 7u, 10u, 21u),
    698   };
    699 
    700   PrepareMIRs(mirs);
    701   PerformLVN();
    702   ASSERT_EQ(value_names_.size(), 8u);
    703   EXPECT_EQ(value_names_[0], value_names_[6]);
    704   EXPECT_EQ(value_names_[1], value_names_[7]);
    705   for (size_t i = 0u; i != mir_count_; ++i) {
    706     int expected = (i == 6u || i == 7u) ? (MIR_IGNORE_NULL_CHECK | MIR_IGNORE_RANGE_CHECK) : 0u;
    707     EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
    708   }
    709 }
    710 
    711 TEST_F(LocalValueNumberingTest, ClInitOnSget) {
    712   static const SFieldDef sfields[] = {
    713       { 0u, 1u, 0u, false },
    714       { 1u, 2u, 1u, false },
    715   };
    716   static const MIRDef mirs[] = {
    717       DEF_SGET(Instruction::SGET_OBJECT, 0u, 0u),
    718       DEF_AGET(Instruction::AGET, 1u, 0u, 100u),
    719       DEF_SGET(Instruction::SGET_OBJECT, 2u, 1u),
    720       DEF_SGET(Instruction::SGET_OBJECT, 3u, 0u),
    721       DEF_AGET(Instruction::AGET, 4u, 3u, 100u),
    722   };
    723 
    724   PrepareSFields(sfields);
    725   MakeSFieldUninitialized(1u);
    726   PrepareMIRs(mirs);
    727   PerformLVN();
    728   ASSERT_EQ(value_names_.size(), 5u);
    729   EXPECT_NE(value_names_[0], value_names_[3]);
    730 }
    731 
    732 }  // namespace art
    733