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 
DoPrepareIFields(const IFieldDef * defs,size_t count)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>
PrepareIFields(const IFieldDef (& defs)[count])110   void PrepareIFields(const IFieldDef (&defs)[count]) {
111     DoPrepareIFields(defs, count);
112   }
113 
DoPrepareSFields(const SFieldDef * defs,size_t count)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>
PrepareSFields(const SFieldDef (& defs)[count])133   void PrepareSFields(const SFieldDef (&defs)[count]) {
134     DoPrepareSFields(defs, count);
135   }
136 
DoPrepareMIRs(const MIRDef * defs,size_t count)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>
PrepareMIRs(const MIRDef (& defs)[count])175   void PrepareMIRs(const MIRDef (&defs)[count]) {
176     DoPrepareMIRs(defs, count);
177   }
178 
MakeSFieldUninitialized(uint32_t sfield_index)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>
MarkAsWideSRegs(const int32_t (& sregs)[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 
PerformLVN()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 
LocalValueNumberingTest()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 
TEST_F(LocalValueNumberingTest,IGetIGetInvokeIGet)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 
TEST_F(LocalValueNumberingTest,IGetIPutIGetIGetIGet)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 
TEST_F(LocalValueNumberingTest,UniquePreserve1)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 
TEST_F(LocalValueNumberingTest,UniquePreserve2)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 
TEST_F(LocalValueNumberingTest,UniquePreserveAndEscape)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 
TEST_F(LocalValueNumberingTest,Volatile)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 
TEST_F(LocalValueNumberingTest,UnresolvedIField)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 
TEST_F(LocalValueNumberingTest,UnresolvedSField)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 
TEST_F(LocalValueNumberingTest,UninitializedSField)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 
TEST_F(LocalValueNumberingTest,ConstString)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 
TEST_F(LocalValueNumberingTest,SameValueInDifferentMemoryLocations)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 
TEST_F(LocalValueNumberingTest,UniqueArrayAliasing)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 
TEST_F(LocalValueNumberingTest,EscapingRefs)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 
TEST_F(LocalValueNumberingTest,EscapingArrayRefs)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 
TEST_F(LocalValueNumberingTest,StoringSameValueKeepsMemoryVersion)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 
TEST_F(LocalValueNumberingTest,FilledNewArrayTracking)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 
TEST_F(LocalValueNumberingTest,ClInitOnSget)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 
TEST_F(LocalValueNumberingTest,DivZeroCheck)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 
TEST_F(LocalValueNumberingTest,ConstWide)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 
TEST_F(LocalValueNumberingTest,Const)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