blob: 0fcb5843cf303f7995be7fdcf011cb43c3ab1486 [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 Markof59f18b2014-02-17 15:53:57 +000017#include "compiler_internals.h"
Vladimir Markoaf6925b2014-10-31 16:37:32 +000018#include "dex/mir_field_info.h"
Vladimir Marko95a05972014-05-30 10:01:32 +010019#include "global_value_numbering.h"
20#include "local_value_numbering.h"
Vladimir Markof59f18b2014-02-17 15:53:57 +000021#include "gtest/gtest.h"
22
23namespace art {
24
25class LocalValueNumberingTest : public testing::Test {
26 protected:
27 struct IFieldDef {
28 uint16_t field_idx;
29 uintptr_t declaring_dex_file;
30 uint16_t declaring_field_idx;
31 bool is_volatile;
Vladimir Markoaf6925b2014-10-31 16:37:32 +000032 DexMemAccessType type;
Vladimir Markof59f18b2014-02-17 15:53:57 +000033 };
34
35 struct SFieldDef {
36 uint16_t field_idx;
37 uintptr_t declaring_dex_file;
38 uint16_t declaring_field_idx;
39 bool is_volatile;
Vladimir Markoaf6925b2014-10-31 16:37:32 +000040 DexMemAccessType type;
Vladimir Markof59f18b2014-02-17 15:53:57 +000041 };
42
43 struct MIRDef {
44 static constexpr size_t kMaxSsaDefs = 2;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010045 static constexpr size_t kMaxSsaUses = 4;
Vladimir Markof59f18b2014-02-17 15:53:57 +000046
47 Instruction::Code opcode;
48 int64_t value;
Vladimir Markobe0e5462014-02-26 11:24:15 +000049 uint32_t field_info;
Vladimir Markof59f18b2014-02-17 15:53:57 +000050 size_t num_uses;
51 int32_t uses[kMaxSsaUses];
52 size_t num_defs;
53 int32_t defs[kMaxSsaDefs];
54 };
55
56#define DEF_CONST(opcode, reg, value) \
57 { opcode, value, 0u, 0, { }, 1, { reg } }
58#define DEF_CONST_WIDE(opcode, reg, value) \
59 { opcode, value, 0u, 0, { }, 2, { reg, reg + 1 } }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010060#define DEF_CONST_STRING(opcode, reg, index) \
61 { opcode, index, 0u, 0, { }, 1, { reg } }
Vladimir Markobe0e5462014-02-26 11:24:15 +000062#define DEF_IGET(opcode, reg, obj, field_info) \
63 { opcode, 0u, field_info, 1, { obj }, 1, { reg } }
64#define DEF_IGET_WIDE(opcode, reg, obj, field_info) \
65 { opcode, 0u, field_info, 1, { obj }, 2, { reg, reg + 1 } }
66#define DEF_IPUT(opcode, reg, obj, field_info) \
67 { opcode, 0u, field_info, 2, { reg, obj }, 0, { } }
68#define DEF_IPUT_WIDE(opcode, reg, obj, field_info) \
69 { opcode, 0u, field_info, 3, { reg, reg + 1, obj }, 0, { } }
70#define DEF_SGET(opcode, reg, field_info) \
71 { opcode, 0u, field_info, 0, { }, 1, { reg } }
72#define DEF_SGET_WIDE(opcode, reg, field_info) \
73 { opcode, 0u, field_info, 0, { }, 2, { reg, reg + 1 } }
74#define DEF_SPUT(opcode, reg, field_info) \
75 { opcode, 0u, field_info, 1, { reg }, 0, { } }
76#define DEF_SPUT_WIDE(opcode, reg, field_info) \
77 { opcode, 0u, field_info, 2, { reg, reg + 1 }, 0, { } }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010078#define DEF_AGET(opcode, reg, obj, idx) \
79 { opcode, 0u, 0u, 2, { obj, idx }, 1, { reg } }
80#define DEF_AGET_WIDE(opcode, reg, obj, idx) \
81 { opcode, 0u, 0u, 2, { obj, idx }, 2, { reg, reg + 1 } }
82#define DEF_APUT(opcode, reg, obj, idx) \
83 { opcode, 0u, 0u, 3, { reg, obj, idx }, 0, { } }
84#define DEF_APUT_WIDE(opcode, reg, obj, idx) \
85 { opcode, 0u, 0u, 4, { reg, reg + 1, obj, idx }, 0, { } }
Vladimir Markof59f18b2014-02-17 15:53:57 +000086#define DEF_INVOKE1(opcode, reg) \
87 { opcode, 0u, 0u, 1, { reg }, 0, { } }
88#define DEF_UNIQUE_REF(opcode, reg) \
89 { opcode, 0u, 0u, 0, { }, 1, { reg } } // CONST_CLASS, CONST_STRING, NEW_ARRAY, ...
Razvan A Lupusorue0951142014-11-14 14:36:55 -080090#define DEF_DIV_REM(opcode, result, dividend, divisor) \
91 { opcode, 0u, 0u, 2, { dividend, divisor }, 1, { result } }
92#define DEF_DIV_REM_WIDE(opcode, result, dividend, divisor) \
93 { opcode, 0u, 0u, 4, { dividend, dividend + 1, divisor, divisor + 1 }, 2, { result, result + 1 } }
Vladimir Markof59f18b2014-02-17 15:53:57 +000094
95 void DoPrepareIFields(const IFieldDef* defs, size_t count) {
Vladimir Markoe39c54e2014-09-22 14:50:02 +010096 cu_.mir_graph->ifield_lowering_infos_.clear();
97 cu_.mir_graph->ifield_lowering_infos_.reserve(count);
Vladimir Markobe0e5462014-02-26 11:24:15 +000098 for (size_t i = 0u; i != count; ++i) {
99 const IFieldDef* def = &defs[i];
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000100 MirIFieldLoweringInfo field_info(def->field_idx, def->type);
Vladimir Markobe0e5462014-02-26 11:24:15 +0000101 if (def->declaring_dex_file != 0u) {
102 field_info.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file);
103 field_info.declaring_field_idx_ = def->declaring_field_idx;
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000104 field_info.flags_ &= ~(def->is_volatile ? 0u : MirSFieldLoweringInfo::kFlagIsVolatile);
Vladimir Markobe0e5462014-02-26 11:24:15 +0000105 }
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100106 cu_.mir_graph->ifield_lowering_infos_.push_back(field_info);
Vladimir Markobe0e5462014-02-26 11:24:15 +0000107 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000108 }
109
110 template <size_t count>
111 void PrepareIFields(const IFieldDef (&defs)[count]) {
112 DoPrepareIFields(defs, count);
113 }
114
115 void DoPrepareSFields(const SFieldDef* defs, size_t count) {
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100116 cu_.mir_graph->sfield_lowering_infos_.clear();
117 cu_.mir_graph->sfield_lowering_infos_.reserve(count);
Vladimir Markobe0e5462014-02-26 11:24:15 +0000118 for (size_t i = 0u; i != count; ++i) {
119 const SFieldDef* def = &defs[i];
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000120 MirSFieldLoweringInfo field_info(def->field_idx, def->type);
Vladimir Markof418f322014-07-09 14:45:36 +0100121 // Mark even unresolved fields as initialized.
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000122 field_info.flags_ |= MirSFieldLoweringInfo::kFlagClassIsInitialized;
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100123 // NOTE: MirSFieldLoweringInfo::kFlagClassIsInDexCache isn't used by LVN.
Vladimir Markobe0e5462014-02-26 11:24:15 +0000124 if (def->declaring_dex_file != 0u) {
125 field_info.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file);
126 field_info.declaring_field_idx_ = def->declaring_field_idx;
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000127 field_info.flags_ &= ~(def->is_volatile ? 0u : MirSFieldLoweringInfo::kFlagIsVolatile);
Vladimir Markobe0e5462014-02-26 11:24:15 +0000128 }
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100129 cu_.mir_graph->sfield_lowering_infos_.push_back(field_info);
Vladimir Markobe0e5462014-02-26 11:24:15 +0000130 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000131 }
132
133 template <size_t count>
134 void PrepareSFields(const SFieldDef (&defs)[count]) {
135 DoPrepareSFields(defs, count);
136 }
137
138 void DoPrepareMIRs(const MIRDef* defs, size_t count) {
139 mir_count_ = count;
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000140 mirs_ = reinterpret_cast<MIR*>(cu_.arena.Alloc(sizeof(MIR) * count, kArenaAllocMIR));
Vladimir Markof59f18b2014-02-17 15:53:57 +0000141 ssa_reps_.resize(count);
142 for (size_t i = 0u; i != count; ++i) {
143 const MIRDef* def = &defs[i];
144 MIR* mir = &mirs_[i];
145 mir->dalvikInsn.opcode = def->opcode;
146 mir->dalvikInsn.vB = static_cast<int32_t>(def->value);
147 mir->dalvikInsn.vB_wide = def->value;
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000148 if (IsInstructionIGetOrIPut(def->opcode)) {
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100149 ASSERT_LT(def->field_info, cu_.mir_graph->ifield_lowering_infos_.size());
Vladimir Markobe0e5462014-02-26 11:24:15 +0000150 mir->meta.ifield_lowering_info = def->field_info;
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000151 ASSERT_EQ(cu_.mir_graph->ifield_lowering_infos_[def->field_info].MemAccessType(),
152 IGetOrIPutMemAccessType(def->opcode));
153 } else if (IsInstructionSGetOrSPut(def->opcode)) {
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100154 ASSERT_LT(def->field_info, cu_.mir_graph->sfield_lowering_infos_.size());
Vladimir Markobe0e5462014-02-26 11:24:15 +0000155 mir->meta.sfield_lowering_info = def->field_info;
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000156 ASSERT_EQ(cu_.mir_graph->sfield_lowering_infos_[def->field_info].MemAccessType(),
157 SGetOrSPutMemAccessType(def->opcode));
Vladimir Markobe0e5462014-02-26 11:24:15 +0000158 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000159 mir->ssa_rep = &ssa_reps_[i];
160 mir->ssa_rep->num_uses = def->num_uses;
161 mir->ssa_rep->uses = const_cast<int32_t*>(def->uses); // Not modified by LVN.
162 mir->ssa_rep->fp_use = nullptr; // Not used by LVN.
163 mir->ssa_rep->num_defs = def->num_defs;
164 mir->ssa_rep->defs = const_cast<int32_t*>(def->defs); // Not modified by LVN.
165 mir->ssa_rep->fp_def = nullptr; // Not used by LVN.
166 mir->dalvikInsn.opcode = def->opcode;
167 mir->offset = i; // LVN uses offset only for debug output
Vladimir Markof59f18b2014-02-17 15:53:57 +0000168 mir->optimization_flags = 0u;
169
170 if (i != 0u) {
171 mirs_[i - 1u].next = mir;
172 }
173 }
174 mirs_[count - 1u].next = nullptr;
175 }
176
177 template <size_t count>
178 void PrepareMIRs(const MIRDef (&defs)[count]) {
179 DoPrepareMIRs(defs, count);
180 }
181
Vladimir Markof418f322014-07-09 14:45:36 +0100182 void MakeSFieldUninitialized(uint32_t sfield_index) {
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100183 CHECK_LT(sfield_index, cu_.mir_graph->sfield_lowering_infos_.size());
184 cu_.mir_graph->sfield_lowering_infos_[sfield_index].flags_ &=
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100185 ~MirSFieldLoweringInfo::kFlagClassIsInitialized;
Vladimir Markof418f322014-07-09 14:45:36 +0100186 }
187
Vladimir Markof59f18b2014-02-17 15:53:57 +0000188 void PerformLVN() {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000189 cu_.mir_graph->temp_.gvn.ifield_ids_ = GlobalValueNumbering::PrepareGvnFieldIds(
190 allocator_.get(), cu_.mir_graph->ifield_lowering_infos_);
191 cu_.mir_graph->temp_.gvn.sfield_ids_ = GlobalValueNumbering::PrepareGvnFieldIds(
192 allocator_.get(), cu_.mir_graph->sfield_lowering_infos_);
193 gvn_.reset(new (allocator_.get()) GlobalValueNumbering(&cu_, allocator_.get(),
194 GlobalValueNumbering::kModeLvn));
195 lvn_.reset(new (allocator_.get()) LocalValueNumbering(gvn_.get(), 0u, allocator_.get()));
Vladimir Markof59f18b2014-02-17 15:53:57 +0000196 value_names_.resize(mir_count_);
197 for (size_t i = 0; i != mir_count_; ++i) {
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000198 value_names_[i] = lvn_->GetValueNumber(&mirs_[i]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000199 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100200 EXPECT_TRUE(gvn_->Good());
Vladimir Markof59f18b2014-02-17 15:53:57 +0000201 }
202
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000203 LocalValueNumberingTest()
204 : pool_(),
205 cu_(&pool_),
206 mir_count_(0u),
207 mirs_(nullptr),
Vladimir Marko95a05972014-05-30 10:01:32 +0100208 ssa_reps_(),
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100209 allocator_(),
Vladimir Marko95a05972014-05-30 10:01:32 +0100210 gvn_(),
211 lvn_(),
212 value_names_() {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000213 cu_.mir_graph.reset(new MIRGraph(&cu_, &cu_.arena));
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100214 allocator_.reset(ScopedArenaAllocator::Create(&cu_.arena_stack));
Vladimir Markof59f18b2014-02-17 15:53:57 +0000215 }
216
217 ArenaPool pool_;
218 CompilationUnit cu_;
219 size_t mir_count_;
220 MIR* mirs_;
221 std::vector<SSARepresentation> ssa_reps_;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100222 std::unique_ptr<ScopedArenaAllocator> allocator_;
Vladimir Marko95a05972014-05-30 10:01:32 +0100223 std::unique_ptr<GlobalValueNumbering> gvn_;
Ian Rogers700a4022014-05-19 16:49:03 -0700224 std::unique_ptr<LocalValueNumbering> lvn_;
Vladimir Marko95a05972014-05-30 10:01:32 +0100225 std::vector<uint16_t> value_names_;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000226};
227
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100228TEST_F(LocalValueNumberingTest, IGetIGetInvokeIGet) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000229 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000230 { 1u, 1u, 1u, false, kDexMemAccessWord },
Vladimir Markof59f18b2014-02-17 15:53:57 +0000231 };
232 static const MIRDef mirs[] = {
233 DEF_IGET(Instruction::IGET, 0u, 10u, 0u),
234 DEF_IGET(Instruction::IGET, 1u, 10u, 0u),
235 DEF_INVOKE1(Instruction::INVOKE_VIRTUAL, 11u),
236 DEF_IGET(Instruction::IGET, 2u, 10u, 0u),
237 };
238
239 PrepareIFields(ifields);
240 PrepareMIRs(mirs);
241 PerformLVN();
242 ASSERT_EQ(value_names_.size(), 4u);
243 EXPECT_EQ(value_names_[0], value_names_[1]);
244 EXPECT_NE(value_names_[0], value_names_[3]);
245 EXPECT_EQ(mirs_[0].optimization_flags, 0u);
246 EXPECT_EQ(mirs_[1].optimization_flags, MIR_IGNORE_NULL_CHECK);
247 EXPECT_EQ(mirs_[2].optimization_flags, 0u);
248 EXPECT_EQ(mirs_[3].optimization_flags, MIR_IGNORE_NULL_CHECK);
249}
250
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100251TEST_F(LocalValueNumberingTest, IGetIPutIGetIGetIGet) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000252 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000253 { 1u, 1u, 1u, false, kDexMemAccessObject },
254 { 2u, 1u, 2u, false, kDexMemAccessWord },
Vladimir Markof59f18b2014-02-17 15:53:57 +0000255 };
256 static const MIRDef mirs[] = {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100257 DEF_IGET(Instruction::IGET_OBJECT, 0u, 10u, 0u),
258 DEF_IPUT(Instruction::IPUT_OBJECT, 1u, 11u, 0u), // May alias.
259 DEF_IGET(Instruction::IGET_OBJECT, 2u, 10u, 0u),
Vladimir Markof59f18b2014-02-17 15:53:57 +0000260 DEF_IGET(Instruction::IGET, 3u, 0u, 1u),
261 DEF_IGET(Instruction::IGET, 4u, 2u, 1u),
262 };
263
264 PrepareIFields(ifields);
265 PrepareMIRs(mirs);
266 PerformLVN();
267 ASSERT_EQ(value_names_.size(), 5u);
268 EXPECT_NE(value_names_[0], value_names_[2]);
269 EXPECT_NE(value_names_[3], value_names_[4]);
Vladimir Marko95a05972014-05-30 10:01:32 +0100270 for (size_t i = 0; i != arraysize(mirs); ++i) {
271 EXPECT_EQ((i == 2u) ? MIR_IGNORE_NULL_CHECK : 0,
272 mirs_[i].optimization_flags) << i;
273 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000274}
275
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100276TEST_F(LocalValueNumberingTest, UniquePreserve1) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000277 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000278 { 1u, 1u, 1u, false, kDexMemAccessWord },
Vladimir Markof59f18b2014-02-17 15:53:57 +0000279 };
280 static const MIRDef mirs[] = {
281 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 10u),
282 DEF_IGET(Instruction::IGET, 0u, 10u, 0u),
283 DEF_IPUT(Instruction::IPUT, 1u, 11u, 0u), // No aliasing since 10u is unique.
284 DEF_IGET(Instruction::IGET, 2u, 10u, 0u),
285 };
286
287 PrepareIFields(ifields);
288 PrepareMIRs(mirs);
289 PerformLVN();
290 ASSERT_EQ(value_names_.size(), 4u);
291 EXPECT_EQ(value_names_[1], value_names_[3]);
Vladimir Marko95a05972014-05-30 10:01:32 +0100292 for (size_t i = 0; i != arraysize(mirs); ++i) {
293 EXPECT_EQ((i == 1u || i == 3u) ? MIR_IGNORE_NULL_CHECK : 0,
294 mirs_[i].optimization_flags) << i;
295 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000296}
297
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100298TEST_F(LocalValueNumberingTest, UniquePreserve2) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000299 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000300 { 1u, 1u, 1u, false, kDexMemAccessWord },
Vladimir Markof59f18b2014-02-17 15:53:57 +0000301 };
302 static const MIRDef mirs[] = {
303 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 11u),
304 DEF_IGET(Instruction::IGET, 0u, 10u, 0u),
305 DEF_IPUT(Instruction::IPUT, 1u, 11u, 0u), // No aliasing since 11u is unique.
306 DEF_IGET(Instruction::IGET, 2u, 10u, 0u),
307 };
308
309 PrepareIFields(ifields);
310 PrepareMIRs(mirs);
311 PerformLVN();
312 ASSERT_EQ(value_names_.size(), 4u);
313 EXPECT_EQ(value_names_[1], value_names_[3]);
Vladimir Marko95a05972014-05-30 10:01:32 +0100314 for (size_t i = 0; i != arraysize(mirs); ++i) {
315 EXPECT_EQ((i == 2u || i == 3u) ? MIR_IGNORE_NULL_CHECK : 0,
316 mirs_[i].optimization_flags) << i;
317 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000318}
319
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100320TEST_F(LocalValueNumberingTest, UniquePreserveAndEscape) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000321 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000322 { 1u, 1u, 1u, false, kDexMemAccessWord },
Vladimir Markof59f18b2014-02-17 15:53:57 +0000323 };
324 static const MIRDef mirs[] = {
325 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 10u),
326 DEF_IGET(Instruction::IGET, 0u, 10u, 0u),
327 DEF_INVOKE1(Instruction::INVOKE_VIRTUAL, 11u), // 10u still unique.
328 DEF_IGET(Instruction::IGET, 2u, 10u, 0u),
329 DEF_INVOKE1(Instruction::INVOKE_VIRTUAL, 10u), // 10u not unique anymore.
330 DEF_IGET(Instruction::IGET, 3u, 10u, 0u),
331 };
332
333 PrepareIFields(ifields);
334 PrepareMIRs(mirs);
335 PerformLVN();
336 ASSERT_EQ(value_names_.size(), 6u);
337 EXPECT_EQ(value_names_[1], value_names_[3]);
338 EXPECT_NE(value_names_[1], value_names_[5]);
Vladimir Marko95a05972014-05-30 10:01:32 +0100339 for (size_t i = 0; i != arraysize(mirs); ++i) {
340 EXPECT_EQ((i == 1u || i == 3u || i == 4u || i == 5u) ? MIR_IGNORE_NULL_CHECK : 0,
341 mirs_[i].optimization_flags) << i;
342 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000343}
Vladimir Markof59f18b2014-02-17 15:53:57 +0000344
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100345TEST_F(LocalValueNumberingTest, Volatile) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000346 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000347 { 1u, 1u, 1u, false, kDexMemAccessWord },
348 { 2u, 1u, 2u, true, kDexMemAccessWord },
Vladimir Markof59f18b2014-02-17 15:53:57 +0000349 };
350 static const MIRDef mirs[] = {
351 DEF_IGET(Instruction::IGET, 0u, 10u, 1u), // Volatile.
352 DEF_IGET(Instruction::IGET, 1u, 0u, 0u), // Non-volatile.
353 DEF_IGET(Instruction::IGET, 2u, 10u, 1u), // Volatile.
354 DEF_IGET(Instruction::IGET, 3u, 2u, 1u), // Non-volatile.
Vladimir Markofa236452014-09-29 17:58:10 +0100355 DEF_IGET(Instruction::IGET, 4u, 0u, 0u), // Non-volatile.
Vladimir Markof59f18b2014-02-17 15:53:57 +0000356 };
357
358 PrepareIFields(ifields);
359 PrepareMIRs(mirs);
360 PerformLVN();
Vladimir Markofa236452014-09-29 17:58:10 +0100361 ASSERT_EQ(value_names_.size(), 5u);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000362 EXPECT_NE(value_names_[0], value_names_[2]); // Volatile has always different value name.
363 EXPECT_NE(value_names_[1], value_names_[3]); // Used different base because of volatile.
Vladimir Markofa236452014-09-29 17:58:10 +0100364 EXPECT_NE(value_names_[1], value_names_[4]); // Not guaranteed to be the same after "acquire".
365
Vladimir Marko95a05972014-05-30 10:01:32 +0100366 for (size_t i = 0; i != arraysize(mirs); ++i) {
Vladimir Markofa236452014-09-29 17:58:10 +0100367 EXPECT_EQ((i == 2u || i == 4u) ? MIR_IGNORE_NULL_CHECK : 0,
Vladimir Marko95a05972014-05-30 10:01:32 +0100368 mirs_[i].optimization_flags) << i;
369 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000370}
371
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100372TEST_F(LocalValueNumberingTest, UnresolvedIField) {
373 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000374 { 1u, 1u, 1u, false, kDexMemAccessWord }, // Resolved field #1.
375 { 2u, 1u, 2u, false, kDexMemAccessWide }, // Resolved field #2.
376 { 3u, 0u, 0u, false, kDexMemAccessWord }, // Unresolved field.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100377 };
378 static const MIRDef mirs[] = {
379 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 20u),
380 DEF_IGET(Instruction::IGET, 1u, 20u, 0u), // Resolved field #1, unique object.
381 DEF_IGET(Instruction::IGET, 2u, 21u, 0u), // Resolved field #1.
382 DEF_IGET_WIDE(Instruction::IGET_WIDE, 3u, 21u, 1u), // Resolved field #2.
Vladimir Markofa236452014-09-29 17:58:10 +0100383 DEF_IGET(Instruction::IGET, 4u, 22u, 2u), // Unresolved IGET can be "acquire".
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100384 DEF_IGET(Instruction::IGET, 5u, 20u, 0u), // Resolved field #1, unique object.
385 DEF_IGET(Instruction::IGET, 6u, 21u, 0u), // Resolved field #1.
386 DEF_IGET_WIDE(Instruction::IGET_WIDE, 7u, 21u, 1u), // Resolved field #2.
Vladimir Marko95a05972014-05-30 10:01:32 +0100387 DEF_IPUT(Instruction::IPUT, 8u, 22u, 2u), // IPUT clobbers field #1 (#2 is wide).
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100388 DEF_IGET(Instruction::IGET, 9u, 20u, 0u), // Resolved field #1, unique object.
389 DEF_IGET(Instruction::IGET, 10u, 21u, 0u), // Resolved field #1, new value name.
390 DEF_IGET_WIDE(Instruction::IGET_WIDE, 11u, 21u, 1u), // Resolved field #2.
Vladimir Marko95a05972014-05-30 10:01:32 +0100391 DEF_IGET_WIDE(Instruction::IGET_WIDE, 12u, 20u, 1u), // Resolved field #2, unique object.
392 DEF_IPUT(Instruction::IPUT, 13u, 20u, 2u), // IPUT clobbers field #1 (#2 is wide).
393 DEF_IGET(Instruction::IGET, 14u, 20u, 0u), // Resolved field #1, unique object.
394 DEF_IGET_WIDE(Instruction::IGET_WIDE, 15u, 20u, 1u), // Resolved field #2, unique object.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100395 };
396
397 PrepareIFields(ifields);
398 PrepareMIRs(mirs);
399 PerformLVN();
Vladimir Marko95a05972014-05-30 10:01:32 +0100400 ASSERT_EQ(value_names_.size(), 16u);
Vladimir Markofa236452014-09-29 17:58:10 +0100401 // Unresolved field is potentially volatile, so we need to adhere to the volatile semantics.
402 EXPECT_EQ(value_names_[1], value_names_[5]); // Unique object.
403 EXPECT_NE(value_names_[2], value_names_[6]); // Not guaranteed to be the same after "acquire".
404 EXPECT_NE(value_names_[3], value_names_[7]); // Not guaranteed to be the same after "acquire".
405 EXPECT_EQ(value_names_[1], value_names_[9]); // Unique object.
406 EXPECT_NE(value_names_[6], value_names_[10]); // This aliased with unresolved IPUT.
407 EXPECT_EQ(value_names_[7], value_names_[11]); // Still the same after "release".
408 EXPECT_EQ(value_names_[12], value_names_[15]); // Still the same after "release".
409 EXPECT_NE(value_names_[1], value_names_[14]); // This aliased with unresolved IPUT.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100410 EXPECT_EQ(mirs_[0].optimization_flags, 0u);
411 EXPECT_EQ(mirs_[1].optimization_flags, MIR_IGNORE_NULL_CHECK);
412 EXPECT_EQ(mirs_[2].optimization_flags, 0u);
413 EXPECT_EQ(mirs_[3].optimization_flags, MIR_IGNORE_NULL_CHECK);
414 EXPECT_EQ(mirs_[4].optimization_flags, 0u);
415 for (size_t i = 5u; i != mir_count_; ++i) {
Vladimir Marko95a05972014-05-30 10:01:32 +0100416 EXPECT_EQ((i == 1u || i == 3u || i >=5u) ? MIR_IGNORE_NULL_CHECK : 0,
417 mirs_[i].optimization_flags) << i;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100418 }
419}
420
421TEST_F(LocalValueNumberingTest, UnresolvedSField) {
422 static const SFieldDef sfields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000423 { 1u, 1u, 1u, false, kDexMemAccessWord }, // Resolved field #1.
424 { 2u, 1u, 2u, false, kDexMemAccessWide }, // Resolved field #2.
425 { 3u, 0u, 0u, false, kDexMemAccessWord }, // Unresolved field.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100426 };
427 static const MIRDef mirs[] = {
428 DEF_SGET(Instruction::SGET, 0u, 0u), // Resolved field #1.
429 DEF_SGET_WIDE(Instruction::SGET_WIDE, 1u, 1u), // Resolved field #2.
Vladimir Markofa236452014-09-29 17:58:10 +0100430 DEF_SGET(Instruction::SGET, 2u, 2u), // Unresolved SGET can be "acquire".
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100431 DEF_SGET(Instruction::SGET, 3u, 0u), // Resolved field #1.
432 DEF_SGET_WIDE(Instruction::SGET_WIDE, 4u, 1u), // Resolved field #2.
433 DEF_SPUT(Instruction::SPUT, 5u, 2u), // SPUT clobbers field #1 (#2 is wide).
434 DEF_SGET(Instruction::SGET, 6u, 0u), // Resolved field #1.
435 DEF_SGET_WIDE(Instruction::SGET_WIDE, 7u, 1u), // Resolved field #2.
436 };
437
438 PrepareSFields(sfields);
439 PrepareMIRs(mirs);
440 PerformLVN();
441 ASSERT_EQ(value_names_.size(), 8u);
Vladimir Markofa236452014-09-29 17:58:10 +0100442 // Unresolved field is potentially volatile, so we need to adhere to the volatile semantics.
443 EXPECT_NE(value_names_[0], value_names_[3]); // Not guaranteed to be the same after "acquire".
444 EXPECT_NE(value_names_[1], value_names_[4]); // Not guaranteed to be the same after "acquire".
445 EXPECT_NE(value_names_[3], value_names_[6]); // This aliased with unresolved IPUT.
446 EXPECT_EQ(value_names_[4], value_names_[7]); // Still the same after "release".
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100447 for (size_t i = 0u; i != mir_count_; ++i) {
Vladimir Marko95a05972014-05-30 10:01:32 +0100448 EXPECT_EQ(0, mirs_[i].optimization_flags) << i;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100449 }
450}
451
Vladimir Marko95a05972014-05-30 10:01:32 +0100452TEST_F(LocalValueNumberingTest, UninitializedSField) {
453 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000454 { 1u, 1u, 1u, false, kDexMemAccessWord }, // Resolved field #1.
Vladimir Marko95a05972014-05-30 10:01:32 +0100455 };
456 static const SFieldDef sfields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000457 { 1u, 1u, 1u, false, kDexMemAccessWord }, // Resolved field #1.
458 { 2u, 1u, 2u, false, kDexMemAccessWord }, // Resolved field #2; uninitialized.
Vladimir Marko95a05972014-05-30 10:01:32 +0100459 };
460 static const MIRDef mirs[] = {
461 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 200u),
462 DEF_IGET(Instruction::IGET, 1u, 100u, 0u),
463 DEF_IGET(Instruction::IGET, 2u, 200u, 0u),
464 DEF_SGET(Instruction::SGET, 3u, 0u),
465 DEF_SGET(Instruction::SGET, 4u, 1u), // Can call <clinit>().
466 DEF_IGET(Instruction::IGET, 5u, 100u, 0u), // Differs from 1u.
467 DEF_IGET(Instruction::IGET, 6u, 200u, 0u), // Same as 2u.
468 DEF_SGET(Instruction::SGET, 7u, 0u), // Differs from 3u.
469 };
470
471 PrepareIFields(ifields);
472 PrepareSFields(sfields);
473 MakeSFieldUninitialized(1u);
474 PrepareMIRs(mirs);
475 PerformLVN();
476 ASSERT_EQ(value_names_.size(), 8u);
477 EXPECT_NE(value_names_[1], value_names_[5]);
478 EXPECT_EQ(value_names_[2], value_names_[6]);
479 EXPECT_NE(value_names_[3], value_names_[7]);
480}
481
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100482TEST_F(LocalValueNumberingTest, ConstString) {
483 static const MIRDef mirs[] = {
484 DEF_CONST_STRING(Instruction::CONST_STRING, 0u, 0u),
485 DEF_CONST_STRING(Instruction::CONST_STRING, 1u, 0u),
486 DEF_CONST_STRING(Instruction::CONST_STRING, 2u, 2u),
487 DEF_CONST_STRING(Instruction::CONST_STRING, 3u, 0u),
488 DEF_INVOKE1(Instruction::INVOKE_DIRECT, 2u),
489 DEF_CONST_STRING(Instruction::CONST_STRING, 4u, 2u),
490 };
491
492 PrepareMIRs(mirs);
493 PerformLVN();
494 ASSERT_EQ(value_names_.size(), 6u);
495 EXPECT_EQ(value_names_[1], value_names_[0]);
496 EXPECT_NE(value_names_[2], value_names_[0]);
497 EXPECT_EQ(value_names_[3], value_names_[0]);
498 EXPECT_EQ(value_names_[5], value_names_[2]);
499}
500
501TEST_F(LocalValueNumberingTest, SameValueInDifferentMemoryLocations) {
502 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000503 { 1u, 1u, 1u, false, kDexMemAccessWord },
504 { 2u, 1u, 2u, false, kDexMemAccessWord },
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100505 };
506 static const SFieldDef sfields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000507 { 3u, 1u, 3u, false, kDexMemAccessWord },
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100508 };
509 static const MIRDef mirs[] = {
Vladimir Marko95a05972014-05-30 10:01:32 +0100510 DEF_UNIQUE_REF(Instruction::NEW_ARRAY, 201u),
511 DEF_IGET(Instruction::IGET, 0u, 100u, 0u),
512 DEF_IPUT(Instruction::IPUT, 0u, 100u, 1u),
513 DEF_IPUT(Instruction::IPUT, 0u, 101u, 1u),
514 DEF_APUT(Instruction::APUT, 0u, 200u, 300u),
515 DEF_APUT(Instruction::APUT, 0u, 200u, 301u),
516 DEF_APUT(Instruction::APUT, 0u, 201u, 300u),
517 DEF_APUT(Instruction::APUT, 0u, 201u, 301u),
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100518 DEF_SPUT(Instruction::SPUT, 0u, 0u),
Vladimir Marko95a05972014-05-30 10:01:32 +0100519 DEF_IGET(Instruction::IGET, 9u, 100u, 0u),
520 DEF_IGET(Instruction::IGET, 10u, 100u, 1u),
521 DEF_IGET(Instruction::IGET, 11u, 101u, 1u),
522 DEF_AGET(Instruction::AGET, 12u, 200u, 300u),
523 DEF_AGET(Instruction::AGET, 13u, 200u, 301u),
524 DEF_AGET(Instruction::AGET, 14u, 201u, 300u),
525 DEF_AGET(Instruction::AGET, 15u, 201u, 301u),
526 DEF_SGET(Instruction::SGET, 16u, 0u),
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100527 };
528
529 PrepareIFields(ifields);
530 PrepareSFields(sfields);
531 PrepareMIRs(mirs);
532 PerformLVN();
Vladimir Marko95a05972014-05-30 10:01:32 +0100533 ASSERT_EQ(value_names_.size(), 17u);
534 for (size_t i = 9; i != arraysize(mirs); ++i) {
535 EXPECT_EQ(value_names_[1], value_names_[i]) << i;
536 }
537 for (size_t i = 0; i != arraysize(mirs); ++i) {
538 int expected_flags =
539 ((i == 2u || (i >= 5u && i <= 7u) || (i >= 9u && i <= 15u)) ? MIR_IGNORE_NULL_CHECK : 0) |
540 ((i >= 12u && i <= 15u) ? MIR_IGNORE_RANGE_CHECK : 0);
541 EXPECT_EQ(expected_flags, mirs_[i].optimization_flags) << i;
542 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100543}
544
545TEST_F(LocalValueNumberingTest, UniqueArrayAliasing) {
546 static const MIRDef mirs[] = {
547 DEF_UNIQUE_REF(Instruction::NEW_ARRAY, 20u),
548 DEF_AGET(Instruction::AGET, 1u, 20u, 40u),
549 DEF_APUT(Instruction::APUT, 2u, 20u, 41u), // May alias with index for sreg 40u.
550 DEF_AGET(Instruction::AGET, 3u, 20u, 40u),
551 };
552
553 PrepareMIRs(mirs);
554 PerformLVN();
555 ASSERT_EQ(value_names_.size(), 4u);
556 EXPECT_NE(value_names_[1], value_names_[3]);
Vladimir Marko95a05972014-05-30 10:01:32 +0100557 for (size_t i = 0; i != arraysize(mirs); ++i) {
558 int expected_flags =
559 ((i >= 1u) ? MIR_IGNORE_NULL_CHECK : 0) |
560 ((i == 3u) ? MIR_IGNORE_RANGE_CHECK : 0);
561 EXPECT_EQ(expected_flags, mirs_[i].optimization_flags) << i;
562 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100563}
564
565TEST_F(LocalValueNumberingTest, EscapingRefs) {
566 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000567 { 1u, 1u, 1u, false, kDexMemAccessWord }, // Field #1.
568 { 2u, 1u, 2u, false, kDexMemAccessWord }, // Field #2.
569 { 3u, 1u, 3u, false, kDexMemAccessObject }, // For storing escaping refs.
570 { 4u, 1u, 4u, false, kDexMemAccessWide }, // Wide.
571 { 5u, 0u, 0u, false, kDexMemAccessWord }, // Unresolved field, int.
572 { 6u, 0u, 0u, false, kDexMemAccessWide }, // Unresolved field, wide.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100573 };
574 static const MIRDef mirs[] = {
575 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 20u),
576 DEF_IGET(Instruction::IGET, 1u, 20u, 0u),
577 DEF_IGET(Instruction::IGET, 2u, 20u, 1u),
578 DEF_IPUT(Instruction::IPUT_OBJECT, 20u, 30u, 2u), // Ref escapes.
579 DEF_IGET(Instruction::IGET, 4u, 20u, 0u),
580 DEF_IGET(Instruction::IGET, 5u, 20u, 1u),
581 DEF_IPUT(Instruction::IPUT, 6u, 31u, 0u), // May alias with field #1.
582 DEF_IGET(Instruction::IGET, 7u, 20u, 0u), // New value.
583 DEF_IGET(Instruction::IGET, 8u, 20u, 1u), // Still the same.
584 DEF_IPUT_WIDE(Instruction::IPUT_WIDE, 9u, 31u, 3u), // No aliasing, different type.
585 DEF_IGET(Instruction::IGET, 10u, 20u, 0u),
586 DEF_IGET(Instruction::IGET, 11u, 20u, 1u),
587 DEF_IPUT_WIDE(Instruction::IPUT_WIDE, 12u, 31u, 5u), // No aliasing, different type.
588 DEF_IGET(Instruction::IGET, 13u, 20u, 0u),
589 DEF_IGET(Instruction::IGET, 14u, 20u, 1u),
590 DEF_IPUT(Instruction::IPUT, 15u, 31u, 4u), // Aliasing, same type.
591 DEF_IGET(Instruction::IGET, 16u, 20u, 0u),
592 DEF_IGET(Instruction::IGET, 17u, 20u, 1u),
593 };
594
595 PrepareIFields(ifields);
596 PrepareMIRs(mirs);
597 PerformLVN();
598 ASSERT_EQ(value_names_.size(), 18u);
599 EXPECT_EQ(value_names_[1], value_names_[4]);
600 EXPECT_EQ(value_names_[2], value_names_[5]);
601 EXPECT_NE(value_names_[4], value_names_[7]); // New value.
602 EXPECT_EQ(value_names_[5], value_names_[8]);
603 EXPECT_EQ(value_names_[7], value_names_[10]);
604 EXPECT_EQ(value_names_[8], value_names_[11]);
605 EXPECT_EQ(value_names_[10], value_names_[13]);
606 EXPECT_EQ(value_names_[11], value_names_[14]);
607 EXPECT_NE(value_names_[13], value_names_[16]); // New value.
608 EXPECT_NE(value_names_[14], value_names_[17]); // New value.
609 for (size_t i = 0u; i != mir_count_; ++i) {
Vladimir Marko743b98c2014-11-24 19:45:41 +0000610 int expected =
611 ((i != 0u && i != 3u && i != 6u) ? MIR_IGNORE_NULL_CHECK : 0) |
612 ((i == 3u) ? MIR_STORE_NON_NULL_VALUE: 0);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100613 EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
614 }
615}
616
617TEST_F(LocalValueNumberingTest, EscapingArrayRefs) {
618 static const MIRDef mirs[] = {
619 DEF_UNIQUE_REF(Instruction::NEW_ARRAY, 20u),
620 DEF_AGET(Instruction::AGET, 1u, 20u, 40u),
621 DEF_AGET(Instruction::AGET, 2u, 20u, 41u),
622 DEF_APUT(Instruction::APUT_OBJECT, 20u, 30u, 42u), // Array ref escapes.
623 DEF_AGET(Instruction::AGET, 4u, 20u, 40u),
624 DEF_AGET(Instruction::AGET, 5u, 20u, 41u),
625 DEF_APUT_WIDE(Instruction::APUT_WIDE, 6u, 31u, 43u), // No aliasing, different type.
626 DEF_AGET(Instruction::AGET, 7u, 20u, 40u),
627 DEF_AGET(Instruction::AGET, 8u, 20u, 41u),
628 DEF_APUT(Instruction::APUT, 9u, 32u, 40u), // May alias with all elements.
629 DEF_AGET(Instruction::AGET, 10u, 20u, 40u), // New value (same index name).
630 DEF_AGET(Instruction::AGET, 11u, 20u, 41u), // New value (different index name).
631 };
632
633 PrepareMIRs(mirs);
634 PerformLVN();
635 ASSERT_EQ(value_names_.size(), 12u);
636 EXPECT_EQ(value_names_[1], value_names_[4]);
637 EXPECT_EQ(value_names_[2], value_names_[5]);
638 EXPECT_EQ(value_names_[4], value_names_[7]);
639 EXPECT_EQ(value_names_[5], value_names_[8]);
640 EXPECT_NE(value_names_[7], value_names_[10]); // New value.
641 EXPECT_NE(value_names_[8], value_names_[11]); // New value.
642 for (size_t i = 0u; i != mir_count_; ++i) {
643 int expected =
644 ((i != 0u && i != 3u && i != 6u && i != 9u) ? MIR_IGNORE_NULL_CHECK : 0u) |
Vladimir Marko743b98c2014-11-24 19:45:41 +0000645 ((i >= 4 && i != 6u && i != 9u) ? MIR_IGNORE_RANGE_CHECK : 0u) |
646 ((i == 3u) ? MIR_STORE_NON_NULL_VALUE: 0);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100647 EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
648 }
649}
650
651TEST_F(LocalValueNumberingTest, StoringSameValueKeepsMemoryVersion) {
652 static const IFieldDef ifields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000653 { 1u, 1u, 1u, false, kDexMemAccessWord },
654 { 2u, 1u, 2u, false, kDexMemAccessWord },
Vladimir Marko95a05972014-05-30 10:01:32 +0100655 };
656 static const SFieldDef sfields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000657 { 2u, 1u, 2u, false, kDexMemAccessWord },
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100658 };
659 static const MIRDef mirs[] = {
Vladimir Marko95a05972014-05-30 10:01:32 +0100660 DEF_IGET(Instruction::IGET, 0u, 30u, 0u),
661 DEF_IGET(Instruction::IGET, 1u, 31u, 0u),
662 DEF_IPUT(Instruction::IPUT, 1u, 31u, 0u), // Store the same value.
663 DEF_IGET(Instruction::IGET, 3u, 30u, 0u),
664 DEF_AGET(Instruction::AGET, 4u, 32u, 40u),
665 DEF_AGET(Instruction::AGET, 5u, 33u, 40u),
666 DEF_APUT(Instruction::APUT, 5u, 33u, 40u), // Store the same value.
667 DEF_AGET(Instruction::AGET, 7u, 32u, 40u),
668 DEF_SGET(Instruction::SGET, 8u, 0u),
669 DEF_SPUT(Instruction::SPUT, 8u, 0u), // Store the same value.
670 DEF_SGET(Instruction::SGET, 10u, 0u),
671 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 50u), // Test with unique references.
672 { Instruction::FILLED_NEW_ARRAY, 0, 0u, 2, { 12u, 13u }, 0, { } },
673 DEF_UNIQUE_REF(Instruction::MOVE_RESULT_OBJECT, 51u),
674 DEF_IGET(Instruction::IGET, 14u, 50u, 0u),
675 DEF_IGET(Instruction::IGET, 15u, 50u, 1u),
676 DEF_IPUT(Instruction::IPUT, 15u, 50u, 1u), // Store the same value.
677 DEF_IGET(Instruction::IGET, 17u, 50u, 0u),
678 DEF_AGET(Instruction::AGET, 18u, 51u, 40u),
679 DEF_AGET(Instruction::AGET, 19u, 51u, 41u),
680 DEF_APUT(Instruction::APUT, 19u, 51u, 41u), // Store the same value.
681 DEF_AGET(Instruction::AGET, 21u, 51u, 40u),
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100682 };
683
684 PrepareIFields(ifields);
Vladimir Marko95a05972014-05-30 10:01:32 +0100685 PrepareSFields(sfields);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100686 PrepareMIRs(mirs);
687 PerformLVN();
Vladimir Marko95a05972014-05-30 10:01:32 +0100688 ASSERT_EQ(value_names_.size(), 22u);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100689 EXPECT_NE(value_names_[0], value_names_[1]);
690 EXPECT_EQ(value_names_[0], value_names_[3]);
691 EXPECT_NE(value_names_[4], value_names_[5]);
692 EXPECT_EQ(value_names_[4], value_names_[7]);
Vladimir Marko95a05972014-05-30 10:01:32 +0100693 EXPECT_EQ(value_names_[8], value_names_[10]);
694 EXPECT_NE(value_names_[14], value_names_[15]);
695 EXPECT_EQ(value_names_[14], value_names_[17]);
696 EXPECT_NE(value_names_[18], value_names_[19]);
697 EXPECT_EQ(value_names_[18], value_names_[21]);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100698 for (size_t i = 0u; i != mir_count_; ++i) {
699 int expected =
Vladimir Marko95a05972014-05-30 10:01:32 +0100700 ((i == 2u || i == 3u || i == 6u || i == 7u || (i >= 14u)) ? MIR_IGNORE_NULL_CHECK : 0u) |
701 ((i == 6u || i == 7u || i >= 20u) ? MIR_IGNORE_RANGE_CHECK : 0u);
702 EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
703 }
704}
705
706TEST_F(LocalValueNumberingTest, FilledNewArrayTracking) {
707 if (!kLocalValueNumberingEnableFilledNewArrayTracking) {
708 // Feature disabled.
709 return;
710 }
711 static const MIRDef mirs[] = {
712 DEF_CONST(Instruction::CONST, 0u, 100),
713 DEF_CONST(Instruction::CONST, 1u, 200),
714 { Instruction::FILLED_NEW_ARRAY, 0, 0u, 2, { 0u, 1u }, 0, { } },
715 DEF_UNIQUE_REF(Instruction::MOVE_RESULT_OBJECT, 10u),
716 DEF_CONST(Instruction::CONST, 20u, 0),
717 DEF_CONST(Instruction::CONST, 21u, 1),
718 DEF_AGET(Instruction::AGET, 6u, 10u, 20u),
719 DEF_AGET(Instruction::AGET, 7u, 10u, 21u),
720 };
721
722 PrepareMIRs(mirs);
723 PerformLVN();
724 ASSERT_EQ(value_names_.size(), 8u);
725 EXPECT_EQ(value_names_[0], value_names_[6]);
726 EXPECT_EQ(value_names_[1], value_names_[7]);
727 for (size_t i = 0u; i != mir_count_; ++i) {
728 int expected = (i == 6u || i == 7u) ? (MIR_IGNORE_NULL_CHECK | MIR_IGNORE_RANGE_CHECK) : 0u;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100729 EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
730 }
731}
732
Vladimir Markof418f322014-07-09 14:45:36 +0100733TEST_F(LocalValueNumberingTest, ClInitOnSget) {
734 static const SFieldDef sfields[] = {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000735 { 0u, 1u, 0u, false, kDexMemAccessObject },
736 { 1u, 2u, 1u, false, kDexMemAccessObject },
Vladimir Markof418f322014-07-09 14:45:36 +0100737 };
738 static const MIRDef mirs[] = {
739 DEF_SGET(Instruction::SGET_OBJECT, 0u, 0u),
740 DEF_AGET(Instruction::AGET, 1u, 0u, 100u),
741 DEF_SGET(Instruction::SGET_OBJECT, 2u, 1u),
742 DEF_SGET(Instruction::SGET_OBJECT, 3u, 0u),
743 DEF_AGET(Instruction::AGET, 4u, 3u, 100u),
744 };
745
746 PrepareSFields(sfields);
747 MakeSFieldUninitialized(1u);
748 PrepareMIRs(mirs);
749 PerformLVN();
750 ASSERT_EQ(value_names_.size(), 5u);
751 EXPECT_NE(value_names_[0], value_names_[3]);
752}
753
Razvan A Lupusorue0951142014-11-14 14:36:55 -0800754TEST_F(LocalValueNumberingTest, DivZeroCheck) {
755 static const MIRDef mirs[] = {
756 DEF_DIV_REM(Instruction::DIV_INT, 1u, 10u, 20u),
757 DEF_DIV_REM(Instruction::DIV_INT, 2u, 20u, 20u),
758 DEF_DIV_REM(Instruction::DIV_INT_2ADDR, 3u, 10u, 1u),
759 DEF_DIV_REM(Instruction::REM_INT, 4u, 30u, 20u),
760 DEF_DIV_REM_WIDE(Instruction::REM_LONG, 5u, 12u, 14u),
761 DEF_DIV_REM_WIDE(Instruction::DIV_LONG_2ADDR, 7u, 16u, 14u),
762 };
763
764 static const bool expected_ignore_div_zero_check[] = {
765 false, true, false, true, false, true,
766 };
767
768 PrepareMIRs(mirs);
769 PerformLVN();
770 for (size_t i = 0u; i != mir_count_; ++i) {
771 int expected = expected_ignore_div_zero_check[i] ? MIR_IGNORE_DIV_ZERO_CHECK : 0u;
772 EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
773 }
774}
775
Vladimir Markof59f18b2014-02-17 15:53:57 +0000776} // namespace art