blob: f98969effd0866b517aa753230591c132fee5fe4 [file] [log] [blame]
Vladimir Markof59f18b2014-02-17 15:53:57 +00001/*
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
Vladimir Markoaf6925b2014-10-31 16:37:32 +000017#include "dex/mir_field_info.h"
Vladimir Marko95a05972014-05-30 10:01:32 +010018#include "global_value_numbering.h"
19#include "local_value_numbering.h"
Vladimir Markof59f18b2014-02-17 15:53:57 +000020#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;
Vladimir Markoaf6925b2014-10-31 16:37:32 +000031 DexMemAccessType type;
Vladimir Markof59f18b2014-02-17 15:53:57 +000032 };
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;
Vladimir Markoaf6925b2014-10-31 16:37:32 +000039 DexMemAccessType type;
Vladimir Markof59f18b2014-02-17 15:53:57 +000040 };
41
42 struct MIRDef {
43 static constexpr size_t kMaxSsaDefs = 2;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010044 static constexpr size_t kMaxSsaUses = 4;
Vladimir Markof59f18b2014-02-17 15:53:57 +000045
46 Instruction::Code opcode;
47 int64_t value;
Vladimir Markobe0e5462014-02-26 11:24:15 +000048 uint32_t field_info;
Vladimir Markof59f18b2014-02-17 15:53:57 +000049 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 } }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010059#define DEF_CONST_STRING(opcode, reg, index) \
60 { opcode, index, 0u, 0, { }, 1, { reg } }
Vladimir Markobe0e5462014-02-26 11:24:15 +000061#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, { } }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010077#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, { } }
Vladimir Markof59f18b2014-02-17 15:53:57 +000085#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, ...
Razvan A Lupusorue0951142014-11-14 14:36:55 -080089#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 } }
Vladimir Markof59f18b2014-02-17 15:53:57 +000093
94 void DoPrepareIFields(const IFieldDef* defs, size_t count) {
Vladimir Markoe39c54e2014-09-22 14:50:02 +010095 cu_.mir_graph->ifield_lowering_infos_.clear();
96 cu_.mir_graph->ifield_lowering_infos_.reserve(count);
Vladimir Markobe0e5462014-02-26 11:24:15 +000097 for (size_t i = 0u; i != count; ++i) {
98 const IFieldDef* def = &defs[i];
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080099 MirIFieldLoweringInfo field_info(def->field_idx, def->type, false);
Vladimir Markobe0e5462014-02-26 11:24:15 +0000100 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;
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000103 field_info.flags_ &= ~(def->is_volatile ? 0u : MirSFieldLoweringInfo::kFlagIsVolatile);
Vladimir Markobe0e5462014-02-26 11:24:15 +0000104 }
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100105 cu_.mir_graph->ifield_lowering_infos_.push_back(field_info);
Vladimir Markobe0e5462014-02-26 11:24:15 +0000106 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000107 }
108
109 template <size_t count>
110 void PrepareIFields(const IFieldDef (&defs)[count]) {
111 DoPrepareIFields(defs, count);
112 }
113
114 void DoPrepareSFields(const SFieldDef* defs, size_t count) {
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100115 cu_.mir_graph->sfield_lowering_infos_.clear();
116 cu_.mir_graph->sfield_lowering_infos_.reserve(count);
Vladimir Markobe0e5462014-02-26 11:24:15 +0000117 for (size_t i = 0u; i != count; ++i) {
118 const SFieldDef* def = &defs[i];
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000119 MirSFieldLoweringInfo field_info(def->field_idx, def->type);
Vladimir Markof418f322014-07-09 14:45:36 +0100120 // Mark even unresolved fields as initialized.
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000121 field_info.flags_ |= MirSFieldLoweringInfo::kFlagClassIsInitialized;
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100122 // NOTE: MirSFieldLoweringInfo::kFlagClassIsInDexCache isn't used by LVN.
Vladimir Markobe0e5462014-02-26 11:24:15 +0000123 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;
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000126 field_info.flags_ &= ~(def->is_volatile ? 0u : MirSFieldLoweringInfo::kFlagIsVolatile);
Vladimir Markobe0e5462014-02-26 11:24:15 +0000127 }
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100128 cu_.mir_graph->sfield_lowering_infos_.push_back(field_info);
Vladimir Markobe0e5462014-02-26 11:24:15 +0000129 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000130 }
131
132 template <size_t count>
133 void PrepareSFields(const SFieldDef (&defs)[count]) {
134 DoPrepareSFields(defs, count);
135 }
136
137 void DoPrepareMIRs(const MIRDef* defs, size_t count) {
138 mir_count_ = count;
Vladimir Markoe4fcc5b2015-02-13 10:28:29 +0000139 mirs_ = cu_.arena.AllocArray<MIR>(count, kArenaAllocMIR);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000140 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;
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000147 if (IsInstructionIGetOrIPut(def->opcode)) {
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100148 ASSERT_LT(def->field_info, cu_.mir_graph->ifield_lowering_infos_.size());
Vladimir Markobe0e5462014-02-26 11:24:15 +0000149 mir->meta.ifield_lowering_info = def->field_info;
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000150 ASSERT_EQ(cu_.mir_graph->ifield_lowering_infos_[def->field_info].MemAccessType(),
151 IGetOrIPutMemAccessType(def->opcode));
152 } else if (IsInstructionSGetOrSPut(def->opcode)) {
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100153 ASSERT_LT(def->field_info, cu_.mir_graph->sfield_lowering_infos_.size());
Vladimir Markobe0e5462014-02-26 11:24:15 +0000154 mir->meta.sfield_lowering_info = def->field_info;
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000155 ASSERT_EQ(cu_.mir_graph->sfield_lowering_infos_[def->field_info].MemAccessType(),
156 SGetOrSPutMemAccessType(def->opcode));
Vladimir Markobe0e5462014-02-26 11:24:15 +0000157 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000158 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.
Vladimir Markof59f18b2014-02-17 15:53:57 +0000161 mir->ssa_rep->num_defs = def->num_defs;
162 mir->ssa_rep->defs = const_cast<int32_t*>(def->defs); // Not modified by LVN.
Vladimir Markof59f18b2014-02-17 15:53:57 +0000163 mir->dalvikInsn.opcode = def->opcode;
164 mir->offset = i; // LVN uses offset only for debug output
Vladimir Markof59f18b2014-02-17 15:53:57 +0000165 mir->optimization_flags = 0u;
166
167 if (i != 0u) {
168 mirs_[i - 1u].next = mir;
169 }
170 }
171 mirs_[count - 1u].next = nullptr;
172 }
173
174 template <size_t count>
175 void PrepareMIRs(const MIRDef (&defs)[count]) {
176 DoPrepareMIRs(defs, count);
177 }
178
Vladimir Markof418f322014-07-09 14:45:36 +0100179 void MakeSFieldUninitialized(uint32_t sfield_index) {
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100180 CHECK_LT(sfield_index, cu_.mir_graph->sfield_lowering_infos_.size());
181 cu_.mir_graph->sfield_lowering_infos_[sfield_index].flags_ &=
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100182 ~MirSFieldLoweringInfo::kFlagClassIsInitialized;
Vladimir Markof418f322014-07-09 14:45:36 +0100183 }
184
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100185 template <size_t count>
186 void MarkAsWideSRegs(const int32_t (&sregs)[count]) {
187 for (int32_t sreg : sregs) {
188 cu_.mir_graph->reg_location_[sreg].wide = true;
189 cu_.mir_graph->reg_location_[sreg + 1].wide = true;
190 cu_.mir_graph->reg_location_[sreg + 1].high_word = true;
191 }
192 }
193
Vladimir Markof59f18b2014-02-17 15:53:57 +0000194 void PerformLVN() {
Vladimir Marko7a01dc22015-01-02 17:00:44 +0000195 cu_.mir_graph->temp_.gvn.ifield_ids = GlobalValueNumbering::PrepareGvnFieldIds(
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000196 allocator_.get(), cu_.mir_graph->ifield_lowering_infos_);
Vladimir Marko7a01dc22015-01-02 17:00:44 +0000197 cu_.mir_graph->temp_.gvn.sfield_ids = GlobalValueNumbering::PrepareGvnFieldIds(
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000198 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()));
Vladimir Markof59f18b2014-02-17 15:53:57 +0000202 value_names_.resize(mir_count_);
203 for (size_t i = 0; i != mir_count_; ++i) {
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000204 value_names_[i] = lvn_->GetValueNumber(&mirs_[i]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000205 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100206 EXPECT_TRUE(gvn_->Good());
Vladimir Markof59f18b2014-02-17 15:53:57 +0000207 }
208
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000209 LocalValueNumberingTest()
210 : pool_(),
Andreas Gampe0b9203e2015-01-22 20:39:27 -0800211 cu_(&pool_, kRuntimeISA, nullptr, nullptr),
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000212 mir_count_(0u),
213 mirs_(nullptr),
Vladimir Marko95a05972014-05-30 10:01:32 +0100214 ssa_reps_(),
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100215 allocator_(),
Vladimir Marko95a05972014-05-30 10:01:32 +0100216 gvn_(),
217 lvn_(),
218 value_names_() {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000219 cu_.mir_graph.reset(new MIRGraph(&cu_, &cu_.arena));
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100220 allocator_.reset(ScopedArenaAllocator::Create(&cu_.arena_stack));
Vladimir Marko7a01dc22015-01-02 17:00:44 +0000221 // By default, the zero-initialized reg_location_[.] with ref == false tells LVN that
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100222 // 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.
Vladimir Marko7a01dc22015-01-02 17:00:44 +0000224 cu_.mir_graph->reg_location_ = static_cast<RegLocation*>(cu_.arena.Alloc(
225 kMaxSsaRegs * sizeof(cu_.mir_graph->reg_location_[0]), kArenaAllocRegAlloc));
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100226 cu_.mir_graph->num_ssa_regs_ = kMaxSsaRegs;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000227 }
228
Vladimir Marko7a01dc22015-01-02 17:00:44 +0000229 static constexpr size_t kMaxSsaRegs = 16384u;
230
Vladimir Markof59f18b2014-02-17 15:53:57 +0000231 ArenaPool pool_;
232 CompilationUnit cu_;
233 size_t mir_count_;
234 MIR* mirs_;
235 std::vector<SSARepresentation> ssa_reps_;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100236 std::unique_ptr<ScopedArenaAllocator> allocator_;
Vladimir Marko95a05972014-05-30 10:01:32 +0100237 std::unique_ptr<GlobalValueNumbering> gvn_;
Ian Rogers700a4022014-05-19 16:49:03 -0700238 std::unique_ptr<LocalValueNumbering> lvn_;
Vladimir Marko95a05972014-05-30 10:01:32 +0100239 std::vector<uint16_t> value_names_;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000240};
241
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100242TEST_F(LocalValueNumberingTest, IGetIGetInvokeIGet) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000243 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000244 { 1u, 1u, 1u, false, kDexMemAccessWord },
Vladimir Markof59f18b2014-02-17 15:53:57 +0000245 };
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
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100265TEST_F(LocalValueNumberingTest, IGetIPutIGetIGetIGet) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000266 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000267 { 1u, 1u, 1u, false, kDexMemAccessObject },
268 { 2u, 1u, 2u, false, kDexMemAccessWord },
Vladimir Markof59f18b2014-02-17 15:53:57 +0000269 };
270 static const MIRDef mirs[] = {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100271 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),
Vladimir Markof59f18b2014-02-17 15:53:57 +0000274 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]);
Vladimir Marko95a05972014-05-30 10:01:32 +0100284 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 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000288}
289
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100290TEST_F(LocalValueNumberingTest, UniquePreserve1) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000291 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000292 { 1u, 1u, 1u, false, kDexMemAccessWord },
Vladimir Markof59f18b2014-02-17 15:53:57 +0000293 };
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]);
Vladimir Marko95a05972014-05-30 10:01:32 +0100306 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 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000310}
311
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100312TEST_F(LocalValueNumberingTest, UniquePreserve2) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000313 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000314 { 1u, 1u, 1u, false, kDexMemAccessWord },
Vladimir Markof59f18b2014-02-17 15:53:57 +0000315 };
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]);
Vladimir Marko95a05972014-05-30 10:01:32 +0100328 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 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000332}
333
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100334TEST_F(LocalValueNumberingTest, UniquePreserveAndEscape) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000335 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000336 { 1u, 1u, 1u, false, kDexMemAccessWord },
Vladimir Markof59f18b2014-02-17 15:53:57 +0000337 };
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]);
Vladimir Marko95a05972014-05-30 10:01:32 +0100353 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 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000357}
Vladimir Markof59f18b2014-02-17 15:53:57 +0000358
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100359TEST_F(LocalValueNumberingTest, Volatile) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000360 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000361 { 1u, 1u, 1u, false, kDexMemAccessWord },
362 { 2u, 1u, 2u, true, kDexMemAccessWord },
Vladimir Markof59f18b2014-02-17 15:53:57 +0000363 };
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.
Vladimir Markofa236452014-09-29 17:58:10 +0100369 DEF_IGET(Instruction::IGET, 4u, 0u, 0u), // Non-volatile.
Vladimir Markof59f18b2014-02-17 15:53:57 +0000370 };
371
372 PrepareIFields(ifields);
373 PrepareMIRs(mirs);
374 PerformLVN();
Vladimir Markofa236452014-09-29 17:58:10 +0100375 ASSERT_EQ(value_names_.size(), 5u);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000376 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.
Vladimir Markofa236452014-09-29 17:58:10 +0100378 EXPECT_NE(value_names_[1], value_names_[4]); // Not guaranteed to be the same after "acquire".
379
Vladimir Marko95a05972014-05-30 10:01:32 +0100380 for (size_t i = 0; i != arraysize(mirs); ++i) {
Vladimir Markofa236452014-09-29 17:58:10 +0100381 EXPECT_EQ((i == 2u || i == 4u) ? MIR_IGNORE_NULL_CHECK : 0,
Vladimir Marko95a05972014-05-30 10:01:32 +0100382 mirs_[i].optimization_flags) << i;
383 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000384}
385
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100386TEST_F(LocalValueNumberingTest, UnresolvedIField) {
387 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000388 { 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.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100391 };
392 static const MIRDef mirs[] = {
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100393 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.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100409 };
410
411 PrepareIFields(ifields);
412 PrepareMIRs(mirs);
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100413 static const int32_t wide_sregs[] = { 3, 8, 13, 15, 19 };
414 MarkAsWideSRegs(wide_sregs);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100415 PerformLVN();
Vladimir Marko95a05972014-05-30 10:01:32 +0100416 ASSERT_EQ(value_names_.size(), 16u);
Vladimir Markofa236452014-09-29 17:58:10 +0100417 // 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.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100426 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) {
Vladimir Marko95a05972014-05-30 10:01:32 +0100432 EXPECT_EQ((i == 1u || i == 3u || i >=5u) ? MIR_IGNORE_NULL_CHECK : 0,
433 mirs_[i].optimization_flags) << i;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100434 }
435}
436
437TEST_F(LocalValueNumberingTest, UnresolvedSField) {
438 static const SFieldDef sfields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000439 { 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.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100442 };
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.
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100446 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.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100452 };
453
454 PrepareSFields(sfields);
455 PrepareMIRs(mirs);
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100456 static const int32_t wide_sregs[] = { 1, 5, 9 };
457 MarkAsWideSRegs(wide_sregs);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100458 PerformLVN();
459 ASSERT_EQ(value_names_.size(), 8u);
Vladimir Markofa236452014-09-29 17:58:10 +0100460 // 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".
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100465 for (size_t i = 0u; i != mir_count_; ++i) {
Vladimir Marko95a05972014-05-30 10:01:32 +0100466 EXPECT_EQ(0, mirs_[i].optimization_flags) << i;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100467 }
468}
469
Vladimir Marko95a05972014-05-30 10:01:32 +0100470TEST_F(LocalValueNumberingTest, UninitializedSField) {
471 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000472 { 1u, 1u, 1u, false, kDexMemAccessWord }, // Resolved field #1.
Vladimir Marko95a05972014-05-30 10:01:32 +0100473 };
474 static const SFieldDef sfields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000475 { 1u, 1u, 1u, false, kDexMemAccessWord }, // Resolved field #1.
476 { 2u, 1u, 2u, false, kDexMemAccessWord }, // Resolved field #2; uninitialized.
Vladimir Marko95a05972014-05-30 10:01:32 +0100477 };
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
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100500TEST_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
519TEST_F(LocalValueNumberingTest, SameValueInDifferentMemoryLocations) {
520 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000521 { 1u, 1u, 1u, false, kDexMemAccessWord },
522 { 2u, 1u, 2u, false, kDexMemAccessWord },
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100523 };
524 static const SFieldDef sfields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000525 { 3u, 1u, 3u, false, kDexMemAccessWord },
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100526 };
527 static const MIRDef mirs[] = {
Vladimir Marko95a05972014-05-30 10:01:32 +0100528 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),
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100536 DEF_SPUT(Instruction::SPUT, 0u, 0u),
Vladimir Marko95a05972014-05-30 10:01:32 +0100537 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),
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100545 };
546
547 PrepareIFields(ifields);
548 PrepareSFields(sfields);
549 PrepareMIRs(mirs);
550 PerformLVN();
Vladimir Marko95a05972014-05-30 10:01:32 +0100551 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 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100561}
562
563TEST_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]);
Vladimir Marko95a05972014-05-30 10:01:32 +0100575 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 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100581}
582
583TEST_F(LocalValueNumberingTest, EscapingRefs) {
584 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000585 { 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.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100591 };
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.
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100603 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),
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100611 };
612
613 PrepareIFields(ifields);
614 PrepareMIRs(mirs);
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100615 static const int32_t wide_sregs[] = { 9, 13 };
616 MarkAsWideSRegs(wide_sregs);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100617 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) {
Vladimir Marko743b98c2014-11-24 19:45:41 +0000630 int expected =
631 ((i != 0u && i != 3u && i != 6u) ? MIR_IGNORE_NULL_CHECK : 0) |
632 ((i == 3u) ? MIR_STORE_NON_NULL_VALUE: 0);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100633 EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
634 }
635}
636
637TEST_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.
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100646 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).
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100651 };
652
653 PrepareMIRs(mirs);
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100654 static const int32_t wide_sregs[] = { 6 };
655 MarkAsWideSRegs(wide_sregs);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100656 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) |
Vladimir Marko743b98c2014-11-24 19:45:41 +0000667 ((i >= 4 && i != 6u && i != 9u) ? MIR_IGNORE_RANGE_CHECK : 0u) |
668 ((i == 3u) ? MIR_STORE_NON_NULL_VALUE: 0);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100669 EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
670 }
671}
672
673TEST_F(LocalValueNumberingTest, StoringSameValueKeepsMemoryVersion) {
674 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000675 { 1u, 1u, 1u, false, kDexMemAccessWord },
676 { 2u, 1u, 2u, false, kDexMemAccessWord },
Vladimir Marko95a05972014-05-30 10:01:32 +0100677 };
678 static const SFieldDef sfields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000679 { 2u, 1u, 2u, false, kDexMemAccessWord },
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100680 };
681 static const MIRDef mirs[] = {
Vladimir Marko95a05972014-05-30 10:01:32 +0100682 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),
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100704 };
705
706 PrepareIFields(ifields);
Vladimir Marko95a05972014-05-30 10:01:32 +0100707 PrepareSFields(sfields);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100708 PrepareMIRs(mirs);
709 PerformLVN();
Vladimir Marko95a05972014-05-30 10:01:32 +0100710 ASSERT_EQ(value_names_.size(), 22u);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100711 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]);
Vladimir Marko95a05972014-05-30 10:01:32 +0100715 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]);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100720 for (size_t i = 0u; i != mir_count_; ++i) {
721 int expected =
Vladimir Marko95a05972014-05-30 10:01:32 +0100722 ((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
728TEST_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;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100751 EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
752 }
753}
754
Vladimir Markof418f322014-07-09 14:45:36 +0100755TEST_F(LocalValueNumberingTest, ClInitOnSget) {
756 static const SFieldDef sfields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000757 { 0u, 1u, 0u, false, kDexMemAccessObject },
758 { 1u, 2u, 1u, false, kDexMemAccessObject },
Vladimir Markof418f322014-07-09 14:45:36 +0100759 };
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
Razvan A Lupusorue0951142014-11-14 14:36:55 -0800776TEST_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);
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100791 static const int32_t wide_sregs[] = { 5, 7, 12, 14, 16 };
792 MarkAsWideSRegs(wide_sregs);
Razvan A Lupusorue0951142014-11-14 14:36:55 -0800793 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
Andreas Gampe58554b72015-10-20 21:08:52 -0700800static constexpr int64_t shift_minus_1(size_t by) {
801 return static_cast<int64_t>(static_cast<uint64_t>(INT64_C(-1)) << by);
802}
803
Vladimir Markod532f002015-02-13 19:47:13 +0000804TEST_F(LocalValueNumberingTest, ConstWide) {
805 static const MIRDef mirs[] = {
Vladimir Marko22c7f5b2015-02-18 17:52:39 +0000806 // Core reg constants.
Vladimir Markod532f002015-02-13 19:47:13 +0000807 DEF_CONST(Instruction::CONST_WIDE_16, 0u, 0),
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100808 DEF_CONST(Instruction::CONST_WIDE_16, 2u, 1),
809 DEF_CONST(Instruction::CONST_WIDE_16, 4u, -1),
810 DEF_CONST(Instruction::CONST_WIDE_32, 6u, 1 << 16),
Andreas Gampe58554b72015-10-20 21:08:52 -0700811 DEF_CONST(Instruction::CONST_WIDE_32, 8u, shift_minus_1(16)),
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100812 DEF_CONST(Instruction::CONST_WIDE_32, 10u, (1 << 16) + 1),
813 DEF_CONST(Instruction::CONST_WIDE_32, 12u, (1 << 16) - 1),
814 DEF_CONST(Instruction::CONST_WIDE_32, 14u, -(1 << 16) + 1),
815 DEF_CONST(Instruction::CONST_WIDE_32, 16u, -(1 << 16) - 1),
816 DEF_CONST(Instruction::CONST_WIDE, 18u, INT64_C(1) << 32),
Andreas Gampe58554b72015-10-20 21:08:52 -0700817 DEF_CONST(Instruction::CONST_WIDE, 20u, shift_minus_1(32)),
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100818 DEF_CONST(Instruction::CONST_WIDE, 22u, (INT64_C(1) << 32) + 1),
819 DEF_CONST(Instruction::CONST_WIDE, 24u, (INT64_C(1) << 32) - 1),
Andreas Gampe58554b72015-10-20 21:08:52 -0700820 DEF_CONST(Instruction::CONST_WIDE, 26u, shift_minus_1(32) + 1),
821 DEF_CONST(Instruction::CONST_WIDE, 28u, shift_minus_1(32) - 1),
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100822 DEF_CONST(Instruction::CONST_WIDE_HIGH16, 30u, 1), // Effectively 1 << 48.
823 DEF_CONST(Instruction::CONST_WIDE_HIGH16, 32u, 0xffff), // Effectively -1 << 48.
824 DEF_CONST(Instruction::CONST_WIDE, 34u, (INT64_C(1) << 48) + 1),
825 DEF_CONST(Instruction::CONST_WIDE, 36u, (INT64_C(1) << 48) - 1),
Andreas Gampe58554b72015-10-20 21:08:52 -0700826 DEF_CONST(Instruction::CONST_WIDE, 38u, shift_minus_1(48) + 1),
827 DEF_CONST(Instruction::CONST_WIDE, 40u, shift_minus_1(48) - 1),
Vladimir Marko22c7f5b2015-02-18 17:52:39 +0000828 // FP reg constants.
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100829 DEF_CONST(Instruction::CONST_WIDE_16, 42u, 0),
830 DEF_CONST(Instruction::CONST_WIDE_16, 44u, 1),
831 DEF_CONST(Instruction::CONST_WIDE_16, 46u, -1),
832 DEF_CONST(Instruction::CONST_WIDE_32, 48u, 1 << 16),
Andreas Gampe58554b72015-10-20 21:08:52 -0700833 DEF_CONST(Instruction::CONST_WIDE_32, 50u, shift_minus_1(16)),
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100834 DEF_CONST(Instruction::CONST_WIDE_32, 52u, (1 << 16) + 1),
835 DEF_CONST(Instruction::CONST_WIDE_32, 54u, (1 << 16) - 1),
836 DEF_CONST(Instruction::CONST_WIDE_32, 56u, -(1 << 16) + 1),
837 DEF_CONST(Instruction::CONST_WIDE_32, 58u, -(1 << 16) - 1),
838 DEF_CONST(Instruction::CONST_WIDE, 60u, INT64_C(1) << 32),
Andreas Gampe58554b72015-10-20 21:08:52 -0700839 DEF_CONST(Instruction::CONST_WIDE, 62u, shift_minus_1(32)),
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100840 DEF_CONST(Instruction::CONST_WIDE, 64u, (INT64_C(1) << 32) + 1),
841 DEF_CONST(Instruction::CONST_WIDE, 66u, (INT64_C(1) << 32) - 1),
Andreas Gampe58554b72015-10-20 21:08:52 -0700842 DEF_CONST(Instruction::CONST_WIDE, 68u, shift_minus_1(32) + 1),
843 DEF_CONST(Instruction::CONST_WIDE, 70u, shift_minus_1(32) - 1),
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100844 DEF_CONST(Instruction::CONST_WIDE_HIGH16, 72u, 1), // Effectively 1 << 48.
845 DEF_CONST(Instruction::CONST_WIDE_HIGH16, 74u, 0xffff), // Effectively -1 << 48.
846 DEF_CONST(Instruction::CONST_WIDE, 76u, (INT64_C(1) << 48) + 1),
847 DEF_CONST(Instruction::CONST_WIDE, 78u, (INT64_C(1) << 48) - 1),
Andreas Gampe58554b72015-10-20 21:08:52 -0700848 DEF_CONST(Instruction::CONST_WIDE, 80u, shift_minus_1(48) + 1),
849 DEF_CONST(Instruction::CONST_WIDE, 82u, shift_minus_1(48) - 1),
Vladimir Markod532f002015-02-13 19:47:13 +0000850 };
851
852 PrepareMIRs(mirs);
Vladimir Markoa5e69e82015-04-24 19:03:51 +0100853 for (size_t i = 0; i != arraysize(mirs); ++i) {
854 const int32_t wide_sregs[] = { mirs_[i].ssa_rep->defs[0] };
855 MarkAsWideSRegs(wide_sregs);
856 }
Vladimir Marko22c7f5b2015-02-18 17:52:39 +0000857 for (size_t i = arraysize(mirs) / 2u; i != arraysize(mirs); ++i) {
858 cu_.mir_graph->reg_location_[mirs_[i].ssa_rep->defs[0]].fp = true;
859 }
860 PerformLVN();
861 for (size_t i = 0u; i != mir_count_; ++i) {
862 for (size_t j = i + 1u; j != mir_count_; ++j) {
863 EXPECT_NE(value_names_[i], value_names_[j]) << i << " " << j;
864 }
865 }
866}
867
868TEST_F(LocalValueNumberingTest, Const) {
869 static const MIRDef mirs[] = {
870 // Core reg constants.
871 DEF_CONST(Instruction::CONST_4, 0u, 0),
872 DEF_CONST(Instruction::CONST_4, 1u, 1),
873 DEF_CONST(Instruction::CONST_4, 2u, -1),
874 DEF_CONST(Instruction::CONST_16, 3u, 1 << 4),
Andreas Gampe58554b72015-10-20 21:08:52 -0700875 DEF_CONST(Instruction::CONST_16, 4u, shift_minus_1(4)),
Vladimir Marko22c7f5b2015-02-18 17:52:39 +0000876 DEF_CONST(Instruction::CONST_16, 5u, (1 << 4) + 1),
877 DEF_CONST(Instruction::CONST_16, 6u, (1 << 4) - 1),
878 DEF_CONST(Instruction::CONST_16, 7u, -(1 << 4) + 1),
879 DEF_CONST(Instruction::CONST_16, 8u, -(1 << 4) - 1),
880 DEF_CONST(Instruction::CONST_HIGH16, 9u, 1), // Effectively 1 << 16.
881 DEF_CONST(Instruction::CONST_HIGH16, 10u, 0xffff), // Effectively -1 << 16.
882 DEF_CONST(Instruction::CONST, 11u, (1 << 16) + 1),
883 DEF_CONST(Instruction::CONST, 12u, (1 << 16) - 1),
Andreas Gampe58554b72015-10-20 21:08:52 -0700884 DEF_CONST(Instruction::CONST, 13u, shift_minus_1(16) + 1),
885 DEF_CONST(Instruction::CONST, 14u, shift_minus_1(16) - 1),
Vladimir Marko22c7f5b2015-02-18 17:52:39 +0000886 // FP reg constants.
887 DEF_CONST(Instruction::CONST_4, 15u, 0),
888 DEF_CONST(Instruction::CONST_4, 16u, 1),
889 DEF_CONST(Instruction::CONST_4, 17u, -1),
890 DEF_CONST(Instruction::CONST_16, 18u, 1 << 4),
Andreas Gampe58554b72015-10-20 21:08:52 -0700891 DEF_CONST(Instruction::CONST_16, 19u, shift_minus_1(4)),
Vladimir Marko22c7f5b2015-02-18 17:52:39 +0000892 DEF_CONST(Instruction::CONST_16, 20u, (1 << 4) + 1),
893 DEF_CONST(Instruction::CONST_16, 21u, (1 << 4) - 1),
894 DEF_CONST(Instruction::CONST_16, 22u, -(1 << 4) + 1),
895 DEF_CONST(Instruction::CONST_16, 23u, -(1 << 4) - 1),
896 DEF_CONST(Instruction::CONST_HIGH16, 24u, 1), // Effectively 1 << 16.
897 DEF_CONST(Instruction::CONST_HIGH16, 25u, 0xffff), // Effectively -1 << 16.
898 DEF_CONST(Instruction::CONST, 26u, (1 << 16) + 1),
899 DEF_CONST(Instruction::CONST, 27u, (1 << 16) - 1),
Andreas Gampe58554b72015-10-20 21:08:52 -0700900 DEF_CONST(Instruction::CONST, 28u, shift_minus_1(16) + 1),
901 DEF_CONST(Instruction::CONST, 29u, shift_minus_1(16) - 1),
Vladimir Marko22c7f5b2015-02-18 17:52:39 +0000902 // null reference constant.
903 DEF_CONST(Instruction::CONST_4, 30u, 0),
904 };
905
906 PrepareMIRs(mirs);
907 static_assert((arraysize(mirs) & 1) != 0, "missing null or unmatched fp/core");
908 cu_.mir_graph->reg_location_[arraysize(mirs) - 1].ref = true;
909 for (size_t i = arraysize(mirs) / 2u; i != arraysize(mirs) - 1; ++i) {
910 cu_.mir_graph->reg_location_[mirs_[i].ssa_rep->defs[0]].fp = true;
911 }
Vladimir Markod532f002015-02-13 19:47:13 +0000912 PerformLVN();
913 for (size_t i = 0u; i != mir_count_; ++i) {
914 for (size_t j = i + 1u; j != mir_count_; ++j) {
915 EXPECT_NE(value_names_[i], value_names_[j]) << i << " " << j;
916 }
917 }
918}
919
Vladimir Markof59f18b2014-02-17 15:53:57 +0000920} // namespace art