blob: a2e3f3dafc11c12b2b6812c827f0aaa5008ea11e [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
17#include <vector>
18
19#include "local_value_numbering.h"
20#include "compiler_internals.h"
21#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;
32 };
33
34 struct SFieldDef {
35 uint16_t field_idx;
36 uintptr_t declaring_dex_file;
37 uint16_t declaring_field_idx;
38 bool is_volatile;
39 };
40
41 struct MIRDef {
42 static constexpr size_t kMaxSsaDefs = 2;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010043 static constexpr size_t kMaxSsaUses = 4;
Vladimir Markof59f18b2014-02-17 15:53:57 +000044
45 Instruction::Code opcode;
46 int64_t value;
Vladimir Markobe0e5462014-02-26 11:24:15 +000047 uint32_t field_info;
Vladimir Markof59f18b2014-02-17 15:53:57 +000048 size_t num_uses;
49 int32_t uses[kMaxSsaUses];
50 size_t num_defs;
51 int32_t defs[kMaxSsaDefs];
52 };
53
54#define DEF_CONST(opcode, reg, value) \
55 { opcode, value, 0u, 0, { }, 1, { reg } }
56#define DEF_CONST_WIDE(opcode, reg, value) \
57 { opcode, value, 0u, 0, { }, 2, { reg, reg + 1 } }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010058#define DEF_CONST_STRING(opcode, reg, index) \
59 { opcode, index, 0u, 0, { }, 1, { reg } }
Vladimir Markobe0e5462014-02-26 11:24:15 +000060#define DEF_IGET(opcode, reg, obj, field_info) \
61 { opcode, 0u, field_info, 1, { obj }, 1, { reg } }
62#define DEF_IGET_WIDE(opcode, reg, obj, field_info) \
63 { opcode, 0u, field_info, 1, { obj }, 2, { reg, reg + 1 } }
64#define DEF_IPUT(opcode, reg, obj, field_info) \
65 { opcode, 0u, field_info, 2, { reg, obj }, 0, { } }
66#define DEF_IPUT_WIDE(opcode, reg, obj, field_info) \
67 { opcode, 0u, field_info, 3, { reg, reg + 1, obj }, 0, { } }
68#define DEF_SGET(opcode, reg, field_info) \
69 { opcode, 0u, field_info, 0, { }, 1, { reg } }
70#define DEF_SGET_WIDE(opcode, reg, field_info) \
71 { opcode, 0u, field_info, 0, { }, 2, { reg, reg + 1 } }
72#define DEF_SPUT(opcode, reg, field_info) \
73 { opcode, 0u, field_info, 1, { reg }, 0, { } }
74#define DEF_SPUT_WIDE(opcode, reg, field_info) \
75 { opcode, 0u, field_info, 2, { reg, reg + 1 }, 0, { } }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010076#define DEF_AGET(opcode, reg, obj, idx) \
77 { opcode, 0u, 0u, 2, { obj, idx }, 1, { reg } }
78#define DEF_AGET_WIDE(opcode, reg, obj, idx) \
79 { opcode, 0u, 0u, 2, { obj, idx }, 2, { reg, reg + 1 } }
80#define DEF_APUT(opcode, reg, obj, idx) \
81 { opcode, 0u, 0u, 3, { reg, obj, idx }, 0, { } }
82#define DEF_APUT_WIDE(opcode, reg, obj, idx) \
83 { opcode, 0u, 0u, 4, { reg, reg + 1, obj, idx }, 0, { } }
Vladimir Markof59f18b2014-02-17 15:53:57 +000084#define DEF_INVOKE1(opcode, reg) \
85 { opcode, 0u, 0u, 1, { reg }, 0, { } }
86#define DEF_UNIQUE_REF(opcode, reg) \
87 { opcode, 0u, 0u, 0, { }, 1, { reg } } // CONST_CLASS, CONST_STRING, NEW_ARRAY, ...
88
89 void DoPrepareIFields(const IFieldDef* defs, size_t count) {
Vladimir Markobe0e5462014-02-26 11:24:15 +000090 cu_.mir_graph->ifield_lowering_infos_.Reset();
91 cu_.mir_graph->ifield_lowering_infos_.Resize(count);
92 for (size_t i = 0u; i != count; ++i) {
93 const IFieldDef* def = &defs[i];
94 MirIFieldLoweringInfo field_info(def->field_idx);
95 if (def->declaring_dex_file != 0u) {
96 field_info.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file);
97 field_info.declaring_field_idx_ = def->declaring_field_idx;
98 field_info.flags_ = 0u | // Without kFlagIsStatic.
99 (def->is_volatile ? MirIFieldLoweringInfo::kFlagIsVolatile : 0u);
100 }
101 cu_.mir_graph->ifield_lowering_infos_.Insert(field_info);
102 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000103 }
104
105 template <size_t count>
106 void PrepareIFields(const IFieldDef (&defs)[count]) {
107 DoPrepareIFields(defs, count);
108 }
109
110 void DoPrepareSFields(const SFieldDef* defs, size_t count) {
Vladimir Markobe0e5462014-02-26 11:24:15 +0000111 cu_.mir_graph->sfield_lowering_infos_.Reset();
112 cu_.mir_graph->sfield_lowering_infos_.Resize(count);
113 for (size_t i = 0u; i != count; ++i) {
114 const SFieldDef* def = &defs[i];
115 MirSFieldLoweringInfo field_info(def->field_idx);
Vladimir Markof418f322014-07-09 14:45:36 +0100116 // Mark even unresolved fields as initialized.
117 field_info.flags_ = MirSFieldLoweringInfo::kFlagIsStatic |
118 MirSFieldLoweringInfo::kFlagIsInitialized;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000119 if (def->declaring_dex_file != 0u) {
120 field_info.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file);
121 field_info.declaring_field_idx_ = def->declaring_field_idx;
Vladimir Markof418f322014-07-09 14:45:36 +0100122 field_info.flags_ |= (def->is_volatile ? MirSFieldLoweringInfo::kFlagIsVolatile : 0u);
Vladimir Markobe0e5462014-02-26 11:24:15 +0000123 }
124 cu_.mir_graph->sfield_lowering_infos_.Insert(field_info);
125 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000126 }
127
128 template <size_t count>
129 void PrepareSFields(const SFieldDef (&defs)[count]) {
130 DoPrepareSFields(defs, count);
131 }
132
133 void DoPrepareMIRs(const MIRDef* defs, size_t count) {
134 mir_count_ = count;
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000135 mirs_ = reinterpret_cast<MIR*>(cu_.arena.Alloc(sizeof(MIR) * count, kArenaAllocMIR));
Vladimir Markof59f18b2014-02-17 15:53:57 +0000136 ssa_reps_.resize(count);
137 for (size_t i = 0u; i != count; ++i) {
138 const MIRDef* def = &defs[i];
139 MIR* mir = &mirs_[i];
140 mir->dalvikInsn.opcode = def->opcode;
141 mir->dalvikInsn.vB = static_cast<int32_t>(def->value);
142 mir->dalvikInsn.vB_wide = def->value;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000143 if (def->opcode >= Instruction::IGET && def->opcode <= Instruction::IPUT_SHORT) {
144 ASSERT_LT(def->field_info, cu_.mir_graph->ifield_lowering_infos_.Size());
145 mir->meta.ifield_lowering_info = def->field_info;
146 } else if (def->opcode >= Instruction::SGET && def->opcode <= Instruction::SPUT_SHORT) {
147 ASSERT_LT(def->field_info, cu_.mir_graph->sfield_lowering_infos_.Size());
148 mir->meta.sfield_lowering_info = def->field_info;
149 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000150 mir->ssa_rep = &ssa_reps_[i];
151 mir->ssa_rep->num_uses = def->num_uses;
152 mir->ssa_rep->uses = const_cast<int32_t*>(def->uses); // Not modified by LVN.
153 mir->ssa_rep->fp_use = nullptr; // Not used by LVN.
154 mir->ssa_rep->num_defs = def->num_defs;
155 mir->ssa_rep->defs = const_cast<int32_t*>(def->defs); // Not modified by LVN.
156 mir->ssa_rep->fp_def = nullptr; // Not used by LVN.
157 mir->dalvikInsn.opcode = def->opcode;
158 mir->offset = i; // LVN uses offset only for debug output
Vladimir Markof59f18b2014-02-17 15:53:57 +0000159 mir->optimization_flags = 0u;
160
161 if (i != 0u) {
162 mirs_[i - 1u].next = mir;
163 }
164 }
165 mirs_[count - 1u].next = nullptr;
166 }
167
168 template <size_t count>
169 void PrepareMIRs(const MIRDef (&defs)[count]) {
170 DoPrepareMIRs(defs, count);
171 }
172
Vladimir Markof418f322014-07-09 14:45:36 +0100173 void MakeSFieldUninitialized(uint32_t sfield_index) {
174 CHECK_LT(sfield_index, cu_.mir_graph->sfield_lowering_infos_.Size());
175 cu_.mir_graph->sfield_lowering_infos_.GetRawStorage()[sfield_index].flags_ &=
176 ~MirSFieldLoweringInfo::kFlagIsInitialized;
177 }
178
Vladimir Markof59f18b2014-02-17 15:53:57 +0000179 void PerformLVN() {
180 value_names_.resize(mir_count_);
181 for (size_t i = 0; i != mir_count_; ++i) {
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000182 value_names_[i] = lvn_->GetValueNumber(&mirs_[i]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000183 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100184 EXPECT_TRUE(lvn_->Good());
Vladimir Markof59f18b2014-02-17 15:53:57 +0000185 }
186
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000187 LocalValueNumberingTest()
188 : pool_(),
189 cu_(&pool_),
190 mir_count_(0u),
191 mirs_(nullptr),
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100192 allocator_(),
193 lvn_() {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000194 cu_.mir_graph.reset(new MIRGraph(&cu_, &cu_.arena));
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100195 allocator_.reset(ScopedArenaAllocator::Create(&cu_.arena_stack));
196 lvn_.reset(new (allocator_.get()) LocalValueNumbering(&cu_, allocator_.get()));
Vladimir Markof59f18b2014-02-17 15:53:57 +0000197 }
198
199 ArenaPool pool_;
200 CompilationUnit cu_;
201 size_t mir_count_;
202 MIR* mirs_;
203 std::vector<SSARepresentation> ssa_reps_;
204 std::vector<uint16_t> value_names_;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100205 std::unique_ptr<ScopedArenaAllocator> allocator_;
Ian Rogers700a4022014-05-19 16:49:03 -0700206 std::unique_ptr<LocalValueNumbering> lvn_;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000207};
208
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100209TEST_F(LocalValueNumberingTest, IGetIGetInvokeIGet) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000210 static const IFieldDef ifields[] = {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100211 { 1u, 1u, 1u, false },
Vladimir Markof59f18b2014-02-17 15:53:57 +0000212 };
213 static const MIRDef mirs[] = {
214 DEF_IGET(Instruction::IGET, 0u, 10u, 0u),
215 DEF_IGET(Instruction::IGET, 1u, 10u, 0u),
216 DEF_INVOKE1(Instruction::INVOKE_VIRTUAL, 11u),
217 DEF_IGET(Instruction::IGET, 2u, 10u, 0u),
218 };
219
220 PrepareIFields(ifields);
221 PrepareMIRs(mirs);
222 PerformLVN();
223 ASSERT_EQ(value_names_.size(), 4u);
224 EXPECT_EQ(value_names_[0], value_names_[1]);
225 EXPECT_NE(value_names_[0], value_names_[3]);
226 EXPECT_EQ(mirs_[0].optimization_flags, 0u);
227 EXPECT_EQ(mirs_[1].optimization_flags, MIR_IGNORE_NULL_CHECK);
228 EXPECT_EQ(mirs_[2].optimization_flags, 0u);
229 EXPECT_EQ(mirs_[3].optimization_flags, MIR_IGNORE_NULL_CHECK);
230}
231
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100232TEST_F(LocalValueNumberingTest, IGetIPutIGetIGetIGet) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000233 static const IFieldDef ifields[] = {
234 { 1u, 1u, 1u, false },
235 { 2u, 1u, 2u, false },
236 };
237 static const MIRDef mirs[] = {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100238 DEF_IGET(Instruction::IGET_OBJECT, 0u, 10u, 0u),
239 DEF_IPUT(Instruction::IPUT_OBJECT, 1u, 11u, 0u), // May alias.
240 DEF_IGET(Instruction::IGET_OBJECT, 2u, 10u, 0u),
Vladimir Markof59f18b2014-02-17 15:53:57 +0000241 DEF_IGET(Instruction::IGET, 3u, 0u, 1u),
242 DEF_IGET(Instruction::IGET, 4u, 2u, 1u),
243 };
244
245 PrepareIFields(ifields);
246 PrepareMIRs(mirs);
247 PerformLVN();
248 ASSERT_EQ(value_names_.size(), 5u);
249 EXPECT_NE(value_names_[0], value_names_[2]);
250 EXPECT_NE(value_names_[3], value_names_[4]);
251 EXPECT_EQ(mirs_[0].optimization_flags, 0u);
252 EXPECT_EQ(mirs_[1].optimization_flags, 0u);
253 EXPECT_EQ(mirs_[2].optimization_flags, MIR_IGNORE_NULL_CHECK);
254 EXPECT_EQ(mirs_[3].optimization_flags, 0u);
255 EXPECT_EQ(mirs_[4].optimization_flags, 0u);
256}
257
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100258TEST_F(LocalValueNumberingTest, UniquePreserve1) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000259 static const IFieldDef ifields[] = {
260 { 1u, 1u, 1u, false },
261 };
262 static const MIRDef mirs[] = {
263 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 10u),
264 DEF_IGET(Instruction::IGET, 0u, 10u, 0u),
265 DEF_IPUT(Instruction::IPUT, 1u, 11u, 0u), // No aliasing since 10u is unique.
266 DEF_IGET(Instruction::IGET, 2u, 10u, 0u),
267 };
268
269 PrepareIFields(ifields);
270 PrepareMIRs(mirs);
271 PerformLVN();
272 ASSERT_EQ(value_names_.size(), 4u);
273 EXPECT_EQ(value_names_[1], value_names_[3]);
274 EXPECT_EQ(mirs_[1].optimization_flags, MIR_IGNORE_NULL_CHECK);
275 EXPECT_EQ(mirs_[2].optimization_flags, 0u);
276 EXPECT_EQ(mirs_[3].optimization_flags, MIR_IGNORE_NULL_CHECK);
277}
278
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100279TEST_F(LocalValueNumberingTest, UniquePreserve2) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000280 static const IFieldDef ifields[] = {
281 { 1u, 1u, 1u, false },
282 };
283 static const MIRDef mirs[] = {
284 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 11u),
285 DEF_IGET(Instruction::IGET, 0u, 10u, 0u),
286 DEF_IPUT(Instruction::IPUT, 1u, 11u, 0u), // No aliasing since 11u is unique.
287 DEF_IGET(Instruction::IGET, 2u, 10u, 0u),
288 };
289
290 PrepareIFields(ifields);
291 PrepareMIRs(mirs);
292 PerformLVN();
293 ASSERT_EQ(value_names_.size(), 4u);
294 EXPECT_EQ(value_names_[1], value_names_[3]);
295 EXPECT_EQ(mirs_[1].optimization_flags, 0u);
296 EXPECT_EQ(mirs_[2].optimization_flags, MIR_IGNORE_NULL_CHECK);
297 EXPECT_EQ(mirs_[3].optimization_flags, MIR_IGNORE_NULL_CHECK);
298}
299
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100300TEST_F(LocalValueNumberingTest, UniquePreserveAndEscape) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000301 static const IFieldDef ifields[] = {
302 { 1u, 1u, 1u, false },
303 };
304 static const MIRDef mirs[] = {
305 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 10u),
306 DEF_IGET(Instruction::IGET, 0u, 10u, 0u),
307 DEF_INVOKE1(Instruction::INVOKE_VIRTUAL, 11u), // 10u still unique.
308 DEF_IGET(Instruction::IGET, 2u, 10u, 0u),
309 DEF_INVOKE1(Instruction::INVOKE_VIRTUAL, 10u), // 10u not unique anymore.
310 DEF_IGET(Instruction::IGET, 3u, 10u, 0u),
311 };
312
313 PrepareIFields(ifields);
314 PrepareMIRs(mirs);
315 PerformLVN();
316 ASSERT_EQ(value_names_.size(), 6u);
317 EXPECT_EQ(value_names_[1], value_names_[3]);
318 EXPECT_NE(value_names_[1], value_names_[5]);
319 EXPECT_EQ(mirs_[1].optimization_flags, MIR_IGNORE_NULL_CHECK);
320 EXPECT_EQ(mirs_[3].optimization_flags, MIR_IGNORE_NULL_CHECK);
321 EXPECT_EQ(mirs_[5].optimization_flags, MIR_IGNORE_NULL_CHECK);
322}
Vladimir Markof59f18b2014-02-17 15:53:57 +0000323
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100324TEST_F(LocalValueNumberingTest, Volatile) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000325 static const IFieldDef ifields[] = {
326 { 1u, 1u, 1u, false },
327 { 2u, 1u, 2u, true },
328 };
329 static const MIRDef mirs[] = {
330 DEF_IGET(Instruction::IGET, 0u, 10u, 1u), // Volatile.
331 DEF_IGET(Instruction::IGET, 1u, 0u, 0u), // Non-volatile.
332 DEF_IGET(Instruction::IGET, 2u, 10u, 1u), // Volatile.
333 DEF_IGET(Instruction::IGET, 3u, 2u, 1u), // Non-volatile.
334 };
335
336 PrepareIFields(ifields);
337 PrepareMIRs(mirs);
338 PerformLVN();
339 ASSERT_EQ(value_names_.size(), 4u);
340 EXPECT_NE(value_names_[0], value_names_[2]); // Volatile has always different value name.
341 EXPECT_NE(value_names_[1], value_names_[3]); // Used different base because of volatile.
342 EXPECT_EQ(mirs_[0].optimization_flags, 0u);
343 EXPECT_EQ(mirs_[1].optimization_flags, 0u);
344 EXPECT_EQ(mirs_[2].optimization_flags, MIR_IGNORE_NULL_CHECK);
345 EXPECT_EQ(mirs_[3].optimization_flags, 0u);
346}
347
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100348TEST_F(LocalValueNumberingTest, UnresolvedIField) {
349 static const IFieldDef ifields[] = {
350 { 1u, 1u, 1u, false }, // Resolved field #1.
351 { 2u, 1u, 2u, false }, // Resolved field #2.
352 { 3u, 0u, 0u, false }, // Unresolved field.
353 };
354 static const MIRDef mirs[] = {
355 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 20u),
356 DEF_IGET(Instruction::IGET, 1u, 20u, 0u), // Resolved field #1, unique object.
357 DEF_IGET(Instruction::IGET, 2u, 21u, 0u), // Resolved field #1.
358 DEF_IGET_WIDE(Instruction::IGET_WIDE, 3u, 21u, 1u), // Resolved field #2.
359 DEF_IGET(Instruction::IGET, 4u, 22u, 2u), // IGET doesn't clobber anything.
360 DEF_IGET(Instruction::IGET, 5u, 20u, 0u), // Resolved field #1, unique object.
361 DEF_IGET(Instruction::IGET, 6u, 21u, 0u), // Resolved field #1.
362 DEF_IGET_WIDE(Instruction::IGET_WIDE, 7u, 21u, 1u), // Resolved field #2.
363 DEF_IPUT(Instruction::IPUT, 8u, 22u, 2u), // IPUT clobbers field #1 (#2 if wide).
364 DEF_IGET(Instruction::IGET, 9u, 20u, 0u), // Resolved field #1, unique object.
365 DEF_IGET(Instruction::IGET, 10u, 21u, 0u), // Resolved field #1, new value name.
366 DEF_IGET_WIDE(Instruction::IGET_WIDE, 11u, 21u, 1u), // Resolved field #2.
367 };
368
369 PrepareIFields(ifields);
370 PrepareMIRs(mirs);
371 PerformLVN();
372 ASSERT_EQ(value_names_.size(), 12u);
373 EXPECT_EQ(value_names_[1], value_names_[5]);
374 EXPECT_EQ(value_names_[2], value_names_[6]);
375 EXPECT_EQ(value_names_[3], value_names_[7]);
376 EXPECT_EQ(value_names_[1], value_names_[9]);
377 EXPECT_NE(value_names_[2], value_names_[10]); // This aliased with unresolved IPUT.
378 EXPECT_EQ(value_names_[3], value_names_[11]);
379 EXPECT_EQ(mirs_[0].optimization_flags, 0u);
380 EXPECT_EQ(mirs_[1].optimization_flags, MIR_IGNORE_NULL_CHECK);
381 EXPECT_EQ(mirs_[2].optimization_flags, 0u);
382 EXPECT_EQ(mirs_[3].optimization_flags, MIR_IGNORE_NULL_CHECK);
383 EXPECT_EQ(mirs_[4].optimization_flags, 0u);
384 for (size_t i = 5u; i != mir_count_; ++i) {
385 EXPECT_EQ(mirs_[i].optimization_flags, MIR_IGNORE_NULL_CHECK);
386 }
387}
388
389TEST_F(LocalValueNumberingTest, UnresolvedSField) {
390 static const SFieldDef sfields[] = {
391 { 1u, 1u, 1u, false }, // Resolved field #1.
392 { 2u, 1u, 2u, false }, // Resolved field #2.
393 { 3u, 0u, 0u, false }, // Unresolved field.
394 };
395 static const MIRDef mirs[] = {
396 DEF_SGET(Instruction::SGET, 0u, 0u), // Resolved field #1.
397 DEF_SGET_WIDE(Instruction::SGET_WIDE, 1u, 1u), // Resolved field #2.
398 DEF_SGET(Instruction::SGET, 2u, 2u), // SGET doesn't clobber anything.
399 DEF_SGET(Instruction::SGET, 3u, 0u), // Resolved field #1.
400 DEF_SGET_WIDE(Instruction::SGET_WIDE, 4u, 1u), // Resolved field #2.
401 DEF_SPUT(Instruction::SPUT, 5u, 2u), // SPUT clobbers field #1 (#2 is wide).
402 DEF_SGET(Instruction::SGET, 6u, 0u), // Resolved field #1.
403 DEF_SGET_WIDE(Instruction::SGET_WIDE, 7u, 1u), // Resolved field #2.
404 };
405
406 PrepareSFields(sfields);
407 PrepareMIRs(mirs);
408 PerformLVN();
409 ASSERT_EQ(value_names_.size(), 8u);
410 EXPECT_EQ(value_names_[0], value_names_[3]);
411 EXPECT_EQ(value_names_[1], value_names_[4]);
412 EXPECT_NE(value_names_[0], value_names_[6]); // This aliased with unresolved IPUT.
413 EXPECT_EQ(value_names_[1], value_names_[7]);
414 for (size_t i = 0u; i != mir_count_; ++i) {
415 EXPECT_EQ(mirs_[i].optimization_flags, 0u) << i;
416 }
417}
418
419TEST_F(LocalValueNumberingTest, ConstString) {
420 static const MIRDef mirs[] = {
421 DEF_CONST_STRING(Instruction::CONST_STRING, 0u, 0u),
422 DEF_CONST_STRING(Instruction::CONST_STRING, 1u, 0u),
423 DEF_CONST_STRING(Instruction::CONST_STRING, 2u, 2u),
424 DEF_CONST_STRING(Instruction::CONST_STRING, 3u, 0u),
425 DEF_INVOKE1(Instruction::INVOKE_DIRECT, 2u),
426 DEF_CONST_STRING(Instruction::CONST_STRING, 4u, 2u),
427 };
428
429 PrepareMIRs(mirs);
430 PerformLVN();
431 ASSERT_EQ(value_names_.size(), 6u);
432 EXPECT_EQ(value_names_[1], value_names_[0]);
433 EXPECT_NE(value_names_[2], value_names_[0]);
434 EXPECT_EQ(value_names_[3], value_names_[0]);
435 EXPECT_EQ(value_names_[5], value_names_[2]);
436}
437
438TEST_F(LocalValueNumberingTest, SameValueInDifferentMemoryLocations) {
439 static const IFieldDef ifields[] = {
440 { 1u, 1u, 1u, false },
441 { 2u, 1u, 2u, false },
442 };
443 static const SFieldDef sfields[] = {
444 { 3u, 1u, 3u, false },
445 };
446 static const MIRDef mirs[] = {
447 DEF_IGET(Instruction::IGET, 0u, 10u, 0u),
448 DEF_IPUT(Instruction::IPUT, 0u, 10u, 1u),
449 DEF_SPUT(Instruction::SPUT, 0u, 0u),
450 DEF_APUT(Instruction::APUT, 0u, 11u, 12u),
451 DEF_IGET(Instruction::IGET, 1u, 10u, 0u),
452 DEF_IGET(Instruction::IGET, 2u, 10u, 1u),
453 DEF_AGET(Instruction::AGET, 3u, 11u, 12u),
454 DEF_SGET(Instruction::SGET, 4u, 0u),
455 };
456
457 PrepareIFields(ifields);
458 PrepareSFields(sfields);
459 PrepareMIRs(mirs);
460 PerformLVN();
461 ASSERT_EQ(value_names_.size(), 8u);
462 EXPECT_EQ(value_names_[4], value_names_[0]);
463 EXPECT_EQ(value_names_[5], value_names_[0]);
464 EXPECT_EQ(value_names_[6], value_names_[0]);
465 EXPECT_EQ(value_names_[7], value_names_[0]);
466 EXPECT_EQ(mirs_[0].optimization_flags, 0u);
467 EXPECT_EQ(mirs_[1].optimization_flags, MIR_IGNORE_NULL_CHECK);
468 EXPECT_EQ(mirs_[2].optimization_flags, 0u);
469 EXPECT_EQ(mirs_[3].optimization_flags, 0u);
470 EXPECT_EQ(mirs_[4].optimization_flags, MIR_IGNORE_NULL_CHECK);
471 EXPECT_EQ(mirs_[5].optimization_flags, MIR_IGNORE_NULL_CHECK);
472 EXPECT_EQ(mirs_[6].optimization_flags, MIR_IGNORE_NULL_CHECK | MIR_IGNORE_RANGE_CHECK);
473 EXPECT_EQ(mirs_[7].optimization_flags, 0u);
474}
475
476TEST_F(LocalValueNumberingTest, UniqueArrayAliasing) {
477 static const MIRDef mirs[] = {
478 DEF_UNIQUE_REF(Instruction::NEW_ARRAY, 20u),
479 DEF_AGET(Instruction::AGET, 1u, 20u, 40u),
480 DEF_APUT(Instruction::APUT, 2u, 20u, 41u), // May alias with index for sreg 40u.
481 DEF_AGET(Instruction::AGET, 3u, 20u, 40u),
482 };
483
484 PrepareMIRs(mirs);
485 PerformLVN();
486 ASSERT_EQ(value_names_.size(), 4u);
487 EXPECT_NE(value_names_[1], value_names_[3]);
488 EXPECT_EQ(mirs_[0].optimization_flags, 0u);
489 EXPECT_EQ(mirs_[1].optimization_flags, MIR_IGNORE_NULL_CHECK);
490 EXPECT_EQ(mirs_[2].optimization_flags, MIR_IGNORE_NULL_CHECK);
491 EXPECT_EQ(mirs_[3].optimization_flags, MIR_IGNORE_NULL_CHECK | MIR_IGNORE_RANGE_CHECK);
492}
493
494TEST_F(LocalValueNumberingTest, EscapingRefs) {
495 static const IFieldDef ifields[] = {
496 { 1u, 1u, 1u, false }, // Field #1.
497 { 2u, 1u, 2u, false }, // Field #2.
498 { 3u, 1u, 3u, false }, // Reference field for storing escaping refs.
499 { 4u, 1u, 4u, false }, // Wide.
500 { 5u, 0u, 0u, false }, // Unresolved field, int.
501 { 6u, 0u, 0u, false }, // Unresolved field, wide.
502 };
503 static const MIRDef mirs[] = {
504 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 20u),
505 DEF_IGET(Instruction::IGET, 1u, 20u, 0u),
506 DEF_IGET(Instruction::IGET, 2u, 20u, 1u),
507 DEF_IPUT(Instruction::IPUT_OBJECT, 20u, 30u, 2u), // Ref escapes.
508 DEF_IGET(Instruction::IGET, 4u, 20u, 0u),
509 DEF_IGET(Instruction::IGET, 5u, 20u, 1u),
510 DEF_IPUT(Instruction::IPUT, 6u, 31u, 0u), // May alias with field #1.
511 DEF_IGET(Instruction::IGET, 7u, 20u, 0u), // New value.
512 DEF_IGET(Instruction::IGET, 8u, 20u, 1u), // Still the same.
513 DEF_IPUT_WIDE(Instruction::IPUT_WIDE, 9u, 31u, 3u), // No aliasing, different type.
514 DEF_IGET(Instruction::IGET, 10u, 20u, 0u),
515 DEF_IGET(Instruction::IGET, 11u, 20u, 1u),
516 DEF_IPUT_WIDE(Instruction::IPUT_WIDE, 12u, 31u, 5u), // No aliasing, different type.
517 DEF_IGET(Instruction::IGET, 13u, 20u, 0u),
518 DEF_IGET(Instruction::IGET, 14u, 20u, 1u),
519 DEF_IPUT(Instruction::IPUT, 15u, 31u, 4u), // Aliasing, same type.
520 DEF_IGET(Instruction::IGET, 16u, 20u, 0u),
521 DEF_IGET(Instruction::IGET, 17u, 20u, 1u),
522 };
523
524 PrepareIFields(ifields);
525 PrepareMIRs(mirs);
526 PerformLVN();
527 ASSERT_EQ(value_names_.size(), 18u);
528 EXPECT_EQ(value_names_[1], value_names_[4]);
529 EXPECT_EQ(value_names_[2], value_names_[5]);
530 EXPECT_NE(value_names_[4], value_names_[7]); // New value.
531 EXPECT_EQ(value_names_[5], value_names_[8]);
532 EXPECT_EQ(value_names_[7], value_names_[10]);
533 EXPECT_EQ(value_names_[8], value_names_[11]);
534 EXPECT_EQ(value_names_[10], value_names_[13]);
535 EXPECT_EQ(value_names_[11], value_names_[14]);
536 EXPECT_NE(value_names_[13], value_names_[16]); // New value.
537 EXPECT_NE(value_names_[14], value_names_[17]); // New value.
538 for (size_t i = 0u; i != mir_count_; ++i) {
539 int expected = (i != 0u && i != 3u && i != 6u) ? MIR_IGNORE_NULL_CHECK : 0u;
540 EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
541 }
542}
543
544TEST_F(LocalValueNumberingTest, EscapingArrayRefs) {
545 static const MIRDef mirs[] = {
546 DEF_UNIQUE_REF(Instruction::NEW_ARRAY, 20u),
547 DEF_AGET(Instruction::AGET, 1u, 20u, 40u),
548 DEF_AGET(Instruction::AGET, 2u, 20u, 41u),
549 DEF_APUT(Instruction::APUT_OBJECT, 20u, 30u, 42u), // Array ref escapes.
550 DEF_AGET(Instruction::AGET, 4u, 20u, 40u),
551 DEF_AGET(Instruction::AGET, 5u, 20u, 41u),
552 DEF_APUT_WIDE(Instruction::APUT_WIDE, 6u, 31u, 43u), // No aliasing, different type.
553 DEF_AGET(Instruction::AGET, 7u, 20u, 40u),
554 DEF_AGET(Instruction::AGET, 8u, 20u, 41u),
555 DEF_APUT(Instruction::APUT, 9u, 32u, 40u), // May alias with all elements.
556 DEF_AGET(Instruction::AGET, 10u, 20u, 40u), // New value (same index name).
557 DEF_AGET(Instruction::AGET, 11u, 20u, 41u), // New value (different index name).
558 };
559
560 PrepareMIRs(mirs);
561 PerformLVN();
562 ASSERT_EQ(value_names_.size(), 12u);
563 EXPECT_EQ(value_names_[1], value_names_[4]);
564 EXPECT_EQ(value_names_[2], value_names_[5]);
565 EXPECT_EQ(value_names_[4], value_names_[7]);
566 EXPECT_EQ(value_names_[5], value_names_[8]);
567 EXPECT_NE(value_names_[7], value_names_[10]); // New value.
568 EXPECT_NE(value_names_[8], value_names_[11]); // New value.
569 for (size_t i = 0u; i != mir_count_; ++i) {
570 int expected =
571 ((i != 0u && i != 3u && i != 6u && i != 9u) ? MIR_IGNORE_NULL_CHECK : 0u) |
572 ((i >= 4 && i != 6u && i != 9u) ? MIR_IGNORE_RANGE_CHECK : 0u);
573 EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
574 }
575}
576
577TEST_F(LocalValueNumberingTest, StoringSameValueKeepsMemoryVersion) {
578 static const IFieldDef ifields[] = {
579 { 1u, 1u, 1u, false },
580 };
581 static const MIRDef mirs[] = {
582 DEF_IGET(Instruction::IGET, 0u, 10u, 0u),
583 DEF_IGET(Instruction::IGET, 1u, 11u, 0u),
584 DEF_IPUT(Instruction::IPUT, 1u, 11u, 0u), // Store the same value.
585 DEF_IGET(Instruction::IGET, 3u, 10u, 0u),
586 DEF_AGET(Instruction::AGET, 4u, 12u, 40u),
587 DEF_AGET(Instruction::AGET, 5u, 13u, 40u),
588 DEF_APUT(Instruction::APUT, 5u, 13u, 40u), // Store the same value.
589 DEF_AGET(Instruction::AGET, 7u, 12u, 40u),
590 };
591
592 PrepareIFields(ifields);
593 PrepareMIRs(mirs);
594 PerformLVN();
595 ASSERT_EQ(value_names_.size(), 8u);
596 EXPECT_NE(value_names_[0], value_names_[1]);
597 EXPECT_EQ(value_names_[0], value_names_[3]);
598 EXPECT_NE(value_names_[4], value_names_[5]);
599 EXPECT_EQ(value_names_[4], value_names_[7]);
600 for (size_t i = 0u; i != mir_count_; ++i) {
601 int expected =
602 ((i == 2u || i == 3u || i == 6u || i == 7u) ? MIR_IGNORE_NULL_CHECK : 0u) |
603 ((i == 6u || i == 7u) ? MIR_IGNORE_RANGE_CHECK : 0u);
604 EXPECT_EQ(expected, mirs_[i].optimization_flags) << i;
605 }
606}
607
Vladimir Markof418f322014-07-09 14:45:36 +0100608TEST_F(LocalValueNumberingTest, ClInitOnSget) {
609 static const SFieldDef sfields[] = {
610 { 0u, 1u, 0u, false },
611 { 1u, 2u, 1u, false },
612 };
613 static const MIRDef mirs[] = {
614 DEF_SGET(Instruction::SGET_OBJECT, 0u, 0u),
615 DEF_AGET(Instruction::AGET, 1u, 0u, 100u),
616 DEF_SGET(Instruction::SGET_OBJECT, 2u, 1u),
617 DEF_SGET(Instruction::SGET_OBJECT, 3u, 0u),
618 DEF_AGET(Instruction::AGET, 4u, 3u, 100u),
619 };
620
621 PrepareSFields(sfields);
622 MakeSFieldUninitialized(1u);
623 PrepareMIRs(mirs);
624 PerformLVN();
625 ASSERT_EQ(value_names_.size(), 5u);
626 EXPECT_NE(value_names_[0], value_names_[3]);
627}
628
Vladimir Markof59f18b2014-02-17 15:53:57 +0000629} // namespace art