local_value_numbering_test.cc revision 07206af370746e6d7cf528e655b4854e7a865cfa
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
22namespace art {
23
24class 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
214TEST_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
237TEST_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
262TEST_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
284TEST_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
306TEST_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
331TEST_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
355TEST_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
403TEST_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
433TEST_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
463TEST_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
482TEST_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
526TEST_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
546TEST_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
596TEST_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
629TEST_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
684TEST_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
711TEST_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