1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "dex/mir_field_info.h" 18 #include "global_value_numbering.h" 19 #include "local_value_numbering.h" 20 #include "gtest/gtest.h" 21 22 namespace art { 23 24 class LocalValueNumberingTest : public testing::Test { 25 protected: 26 struct IFieldDef { 27 uint16_t field_idx; 28 uintptr_t declaring_dex_file; 29 uint16_t declaring_field_idx; 30 bool is_volatile; 31 DexMemAccessType type; 32 }; 33 34 struct SFieldDef { 35 uint16_t field_idx; 36 uintptr_t declaring_dex_file; 37 uint16_t declaring_field_idx; 38 bool is_volatile; 39 DexMemAccessType type; 40 }; 41 42 struct MIRDef { 43 static constexpr size_t kMaxSsaDefs = 2; 44 static constexpr size_t kMaxSsaUses = 4; 45 46 Instruction::Code opcode; 47 int64_t value; 48 uint32_t field_info; 49 size_t num_uses; 50 int32_t uses[kMaxSsaUses]; 51 size_t num_defs; 52 int32_t defs[kMaxSsaDefs]; 53 }; 54 55 #define DEF_CONST(opcode, reg, value) \ 56 { opcode, value, 0u, 0, { }, 1, { reg } } 57 #define DEF_CONST_WIDE(opcode, reg, value) \ 58 { opcode, value, 0u, 0, { }, 2, { reg, reg + 1 } } 59 #define DEF_CONST_STRING(opcode, reg, index) \ 60 { opcode, index, 0u, 0, { }, 1, { reg } } 61 #define DEF_IGET(opcode, reg, obj, field_info) \ 62 { opcode, 0u, field_info, 1, { obj }, 1, { reg } } 63 #define DEF_IGET_WIDE(opcode, reg, obj, field_info) \ 64 { opcode, 0u, field_info, 1, { obj }, 2, { reg, reg + 1 } } 65 #define DEF_IPUT(opcode, reg, obj, field_info) \ 66 { opcode, 0u, field_info, 2, { reg, obj }, 0, { } } 67 #define DEF_IPUT_WIDE(opcode, reg, obj, field_info) \ 68 { opcode, 0u, field_info, 3, { reg, reg + 1, obj }, 0, { } } 69 #define DEF_SGET(opcode, reg, field_info) \ 70 { opcode, 0u, field_info, 0, { }, 1, { reg } } 71 #define DEF_SGET_WIDE(opcode, reg, field_info) \ 72 { opcode, 0u, field_info, 0, { }, 2, { reg, reg + 1 } } 73 #define DEF_SPUT(opcode, reg, field_info) \ 74 { opcode, 0u, field_info, 1, { reg }, 0, { } } 75 #define DEF_SPUT_WIDE(opcode, reg, field_info) \ 76 { opcode, 0u, field_info, 2, { reg, reg + 1 }, 0, { } } 77 #define DEF_AGET(opcode, reg, obj, idx) \ 78 { opcode, 0u, 0u, 2, { obj, idx }, 1, { reg } } 79 #define DEF_AGET_WIDE(opcode, reg, obj, idx) \ 80 { opcode, 0u, 0u, 2, { obj, idx }, 2, { reg, reg + 1 } } 81 #define DEF_APUT(opcode, reg, obj, idx) \ 82 { opcode, 0u, 0u, 3, { reg, obj, idx }, 0, { } } 83 #define DEF_APUT_WIDE(opcode, reg, obj, idx) \ 84 { opcode, 0u, 0u, 4, { reg, reg + 1, obj, idx }, 0, { } } 85 #define DEF_INVOKE1(opcode, reg) \ 86 { opcode, 0u, 0u, 1, { reg }, 0, { } } 87 #define DEF_UNIQUE_REF(opcode, reg) \ 88 { opcode, 0u, 0u, 0, { }, 1, { reg } } // CONST_CLASS, CONST_STRING, NEW_ARRAY, ... 89 #define DEF_DIV_REM(opcode, result, dividend, divisor) \ 90 { opcode, 0u, 0u, 2, { dividend, divisor }, 1, { result } } 91 #define DEF_DIV_REM_WIDE(opcode, result, dividend, divisor) \ 92 { opcode, 0u, 0u, 4, { dividend, dividend + 1, divisor, divisor + 1 }, 2, { result, result + 1 } } 93 94 void DoPrepareIFields(const IFieldDef* defs, size_t count) { 95 cu_.mir_graph->ifield_lowering_infos_.clear(); 96 cu_.mir_graph->ifield_lowering_infos_.reserve(count); 97 for (size_t i = 0u; i != count; ++i) { 98 const IFieldDef* def = &defs[i]; 99 MirIFieldLoweringInfo field_info(def->field_idx, def->type, false); 100 if (def->declaring_dex_file != 0u) { 101 field_info.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file); 102 field_info.declaring_field_idx_ = def->declaring_field_idx; 103 field_info.flags_ &= ~(def->is_volatile ? 0u : MirSFieldLoweringInfo::kFlagIsVolatile); 104 } 105 cu_.mir_graph->ifield_lowering_infos_.push_back(field_info); 106 } 107 } 108 109 template <size_t count> 110 void PrepareIFields(const IFieldDef (&defs)[count]) { 111 DoPrepareIFields(defs, count); 112 } 113 114 void DoPrepareSFields(const SFieldDef* defs, size_t count) { 115 cu_.mir_graph->sfield_lowering_infos_.clear(); 116 cu_.mir_graph->sfield_lowering_infos_.reserve(count); 117 for (size_t i = 0u; i != count; ++i) { 118 const SFieldDef* def = &defs[i]; 119 MirSFieldLoweringInfo field_info(def->field_idx, def->type); 120 // Mark even unresolved fields as initialized. 121 field_info.flags_ |= MirSFieldLoweringInfo::kFlagClassIsInitialized; 122 // NOTE: MirSFieldLoweringInfo::kFlagClassIsInDexCache isn't used by LVN. 123 if (def->declaring_dex_file != 0u) { 124 field_info.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file); 125 field_info.declaring_field_idx_ = def->declaring_field_idx; 126 field_info.flags_ &= ~(def->is_volatile ? 0u : MirSFieldLoweringInfo::kFlagIsVolatile); 127 } 128 cu_.mir_graph->sfield_lowering_infos_.push_back(field_info); 129 } 130 } 131 132 template <size_t count> 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; 139 mirs_ = cu_.arena.AllocArray<MIR>(count, kArenaAllocMIR); 140 ssa_reps_.resize(count); 141 for (size_t i = 0u; i != count; ++i) { 142 const MIRDef* def = &defs[i]; 143 MIR* mir = &mirs_[i]; 144 mir->dalvikInsn.opcode = def->opcode; 145 mir->dalvikInsn.vB = static_cast<int32_t>(def->value); 146 mir->dalvikInsn.vB_wide = def->value; 147 if (IsInstructionIGetOrIPut(def->opcode)) { 148 ASSERT_LT(def->field_info, cu_.mir_graph->ifield_lowering_infos_.size()); 149 mir->meta.ifield_lowering_info = def->field_info; 150 ASSERT_EQ(cu_.mir_graph->ifield_lowering_infos_[def->field_info].MemAccessType(), 151 IGetOrIPutMemAccessType(def->opcode)); 152 } else if (IsInstructionSGetOrSPut(def->opcode)) { 153 ASSERT_LT(def->field_info, cu_.mir_graph->sfield_lowering_infos_.size()); 154 mir->meta.sfield_lowering_info = def->field_info; 155 ASSERT_EQ(cu_.mir_graph->sfield_lowering_infos_[def->field_info].MemAccessType(), 156 SGetOrSPutMemAccessType(def->opcode)); 157 } 158 mir->ssa_rep = &ssa_reps_[i]; 159 mir->ssa_rep->num_uses = def->num_uses; 160 mir->ssa_rep->uses = const_cast<int32_t*>(def->uses); // Not modified by LVN. 161 mir->ssa_rep->num_defs = def->num_defs; 162 mir->ssa_rep->defs = const_cast<int32_t*>(def->defs); // Not modified by LVN. 163 mir->dalvikInsn.opcode = def->opcode; 164 mir->offset = i; // LVN uses offset only for debug output 165 mir->optimization_flags = 0u; 166 167 if (i != 0u) { 168 mirs_[i - 1u].next = mir; 169 } 170 } 171 mirs_[count - 1u].next = nullptr; 172 } 173 174 template <size_t count> 175 void PrepareMIRs(const MIRDef (&defs)[count]) { 176 DoPrepareMIRs(defs, count); 177 } 178 179 void MakeSFieldUninitialized(uint32_t sfield_index) { 180 CHECK_LT(sfield_index, cu_.mir_graph->sfield_lowering_infos_.size()); 181 cu_.mir_graph->sfield_lowering_infos_[sfield_index].flags_ &= 182 ~MirSFieldLoweringInfo::kFlagClassIsInitialized; 183 } 184 185 template <size_t count> 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 194 void PerformLVN() { 195 cu_.mir_graph->temp_.gvn.ifield_ids = GlobalValueNumbering::PrepareGvnFieldIds( 196 allocator_.get(), cu_.mir_graph->ifield_lowering_infos_); 197 cu_.mir_graph->temp_.gvn.sfield_ids = GlobalValueNumbering::PrepareGvnFieldIds( 198 allocator_.get(), cu_.mir_graph->sfield_lowering_infos_); 199 gvn_.reset(new (allocator_.get()) GlobalValueNumbering(&cu_, allocator_.get(), 200 GlobalValueNumbering::kModeLvn)); 201 lvn_.reset(new (allocator_.get()) LocalValueNumbering(gvn_.get(), 0u, allocator_.get())); 202 value_names_.resize(mir_count_); 203 for (size_t i = 0; i != mir_count_; ++i) { 204 value_names_[i] = lvn_->GetValueNumber(&mirs_[i]); 205 } 206 EXPECT_TRUE(gvn_->Good()); 207 } 208 209 LocalValueNumberingTest() 210 : pool_(), 211 cu_(&pool_, kRuntimeISA, nullptr, nullptr), 212 mir_count_(0u), 213 mirs_(nullptr), 214 ssa_reps_(), 215 allocator_(), 216 gvn_(), 217 lvn_(), 218 value_names_() { 219 cu_.mir_graph.reset(new MIRGraph(&cu_, &cu_.arena)); 220 allocator_.reset(ScopedArenaAllocator::Create(&cu_.arena_stack)); 221 // By default, the zero-initialized reg_location_[.] with ref == false tells LVN that 222 // 0 constants are integral, not references, and the values are all narrow. 223 // Nothing else is used by LVN/GVN. Tests can override the default values as needed. 224 cu_.mir_graph->reg_location_ = static_cast<RegLocation*>(cu_.arena.Alloc( 225 kMaxSsaRegs * sizeof(cu_.mir_graph->reg_location_[0]), kArenaAllocRegAlloc)); 226 cu_.mir_graph->num_ssa_regs_ = kMaxSsaRegs; 227 } 228 229 static constexpr size_t kMaxSsaRegs = 16384u; 230 231 ArenaPool pool_; 232 CompilationUnit cu_; 233 size_t mir_count_; 234 MIR* mirs_; 235 std::vector<SSARepresentation> ssa_reps_; 236 std::unique_ptr<ScopedArenaAllocator> allocator_; 237 std::unique_ptr<GlobalValueNumbering> gvn_; 238 std::unique_ptr<LocalValueNumbering> lvn_; 239 std::vector<uint16_t> value_names_; 240 }; 241 242 TEST_F(LocalValueNumberingTest, IGetIGetInvokeIGet) { 243 static const IFieldDef ifields[] = { 244 { 1u, 1u, 1u, false, kDexMemAccessWord }, 245 }; 246 static const MIRDef mirs[] = { 247 DEF_IGET(Instruction::IGET, 0u, 10u, 0u), 248 DEF_IGET(Instruction::IGET, 1u, 10u, 0u), 249 DEF_INVOKE1(Instruction::INVOKE_VIRTUAL, 11u), 250 DEF_IGET(Instruction::IGET, 2u, 10u, 0u), 251 }; 252 253 PrepareIFields(ifields); 254 PrepareMIRs(mirs); 255 PerformLVN(); 256 ASSERT_EQ(value_names_.size(), 4u); 257 EXPECT_EQ(value_names_[0], value_names_[1]); 258 EXPECT_NE(value_names_[0], value_names_[3]); 259 EXPECT_EQ(mirs_[0].optimization_flags, 0u); 260 EXPECT_EQ(mirs_[1].optimization_flags, MIR_IGNORE_NULL_CHECK); 261 EXPECT_EQ(mirs_[2].optimization_flags, 0u); 262 EXPECT_EQ(mirs_[3].optimization_flags, MIR_IGNORE_NULL_CHECK); 263 } 264 265 TEST_F(LocalValueNumberingTest, IGetIPutIGetIGetIGet) { 266 static const IFieldDef ifields[] = { 267 { 1u, 1u, 1u, false, kDexMemAccessObject }, 268 { 2u, 1u, 2u, false, kDexMemAccessWord }, 269 }; 270 static const MIRDef mirs[] = { 271 DEF_IGET(Instruction::IGET_OBJECT, 0u, 10u, 0u), 272 DEF_IPUT(Instruction::IPUT_OBJECT, 1u, 11u, 0u), // May alias. 273 DEF_IGET(Instruction::IGET_OBJECT, 2u, 10u, 0u), 274 DEF_IGET(Instruction::IGET, 3u, 0u, 1u), 275 DEF_IGET(Instruction::IGET, 4u, 2u, 1u), 276 }; 277 278 PrepareIFields(ifields); 279 PrepareMIRs(mirs); 280 PerformLVN(); 281 ASSERT_EQ(value_names_.size(), 5u); 282 EXPECT_NE(value_names_[0], value_names_[2]); 283 EXPECT_NE(value_names_[3], value_names_[4]); 284 for (size_t i = 0; i != arraysize(mirs); ++i) { 285 EXPECT_EQ((i == 2u) ? MIR_IGNORE_NULL_CHECK : 0, 286 mirs_[i].optimization_flags) << i; 287 } 288 } 289 290 TEST_F(LocalValueNumberingTest, UniquePreserve1) { 291 static const IFieldDef ifields[] = { 292 { 1u, 1u, 1u, false, kDexMemAccessWord }, 293 }; 294 static const MIRDef mirs[] = { 295 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 10u), 296 DEF_IGET(Instruction::IGET, 0u, 10u, 0u), 297 DEF_IPUT(Instruction::IPUT, 1u, 11u, 0u), // No aliasing since 10u is unique. 298 DEF_IGET(Instruction::IGET, 2u, 10u, 0u), 299 }; 300 301 PrepareIFields(ifields); 302 PrepareMIRs(mirs); 303 PerformLVN(); 304 ASSERT_EQ(value_names_.size(), 4u); 305 EXPECT_EQ(value_names_[1], value_names_[3]); 306 for (size_t i = 0; i != arraysize(mirs); ++i) { 307 EXPECT_EQ((i == 1u || i == 3u) ? MIR_IGNORE_NULL_CHECK : 0, 308 mirs_[i].optimization_flags) << i; 309 } 310 } 311 312 TEST_F(LocalValueNumberingTest, UniquePreserve2) { 313 static const IFieldDef ifields[] = { 314 { 1u, 1u, 1u, false, kDexMemAccessWord }, 315 }; 316 static const MIRDef mirs[] = { 317 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 11u), 318 DEF_IGET(Instruction::IGET, 0u, 10u, 0u), 319 DEF_IPUT(Instruction::IPUT, 1u, 11u, 0u), // No aliasing since 11u is unique. 320 DEF_IGET(Instruction::IGET, 2u, 10u, 0u), 321 }; 322 323 PrepareIFields(ifields); 324 PrepareMIRs(mirs); 325 PerformLVN(); 326 ASSERT_EQ(value_names_.size(), 4u); 327 EXPECT_EQ(value_names_[1], value_names_[3]); 328 for (size_t i = 0; i != arraysize(mirs); ++i) { 329 EXPECT_EQ((i == 2u || i == 3u) ? MIR_IGNORE_NULL_CHECK : 0, 330 mirs_[i].optimization_flags) << i; 331 } 332 } 333 334 TEST_F(LocalValueNumberingTest, UniquePreserveAndEscape) { 335 static const IFieldDef ifields[] = { 336 { 1u, 1u, 1u, false, kDexMemAccessWord }, 337 }; 338 static const MIRDef mirs[] = { 339 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 10u), 340 DEF_IGET(Instruction::IGET, 0u, 10u, 0u), 341 DEF_INVOKE1(Instruction::INVOKE_VIRTUAL, 11u), // 10u still unique. 342 DEF_IGET(Instruction::IGET, 2u, 10u, 0u), 343 DEF_INVOKE1(Instruction::INVOKE_VIRTUAL, 10u), // 10u not unique anymore. 344 DEF_IGET(Instruction::IGET, 3u, 10u, 0u), 345 }; 346 347 PrepareIFields(ifields); 348 PrepareMIRs(mirs); 349 PerformLVN(); 350 ASSERT_EQ(value_names_.size(), 6u); 351 EXPECT_EQ(value_names_[1], value_names_[3]); 352 EXPECT_NE(value_names_[1], value_names_[5]); 353 for (size_t i = 0; i != arraysize(mirs); ++i) { 354 EXPECT_EQ((i == 1u || i == 3u || i == 4u || i == 5u) ? MIR_IGNORE_NULL_CHECK : 0, 355 mirs_[i].optimization_flags) << i; 356 } 357 } 358 359 TEST_F(LocalValueNumberingTest, Volatile) { 360 static const IFieldDef ifields[] = { 361 { 1u, 1u, 1u, false, kDexMemAccessWord }, 362 { 2u, 1u, 2u, true, kDexMemAccessWord }, 363 }; 364 static const MIRDef mirs[] = { 365 DEF_IGET(Instruction::IGET, 0u, 10u, 1u), // Volatile. 366 DEF_IGET(Instruction::IGET, 1u, 0u, 0u), // Non-volatile. 367 DEF_IGET(Instruction::IGET, 2u, 10u, 1u), // Volatile. 368 DEF_IGET(Instruction::IGET, 3u, 2u, 1u), // Non-volatile. 369 DEF_IGET(Instruction::IGET, 4u, 0u, 0u), // Non-volatile. 370 }; 371 372 PrepareIFields(ifields); 373 PrepareMIRs(mirs); 374 PerformLVN(); 375 ASSERT_EQ(value_names_.size(), 5u); 376 EXPECT_NE(value_names_[0], value_names_[2]); // Volatile has always different value name. 377 EXPECT_NE(value_names_[1], value_names_[3]); // Used different base because of volatile. 378 EXPECT_NE(value_names_[1], value_names_[4]); // Not guaranteed to be the same after "acquire". 379 380 for (size_t i = 0; i != arraysize(mirs); ++i) { 381 EXPECT_EQ((i == 2u || i == 4u) ? MIR_IGNORE_NULL_CHECK : 0, 382 mirs_[i].optimization_flags) << i; 383 } 384 } 385 386 TEST_F(LocalValueNumberingTest, UnresolvedIField) { 387 static const IFieldDef ifields[] = { 388 { 1u, 1u, 1u, false, kDexMemAccessWord }, // Resolved field #1. 389 { 2u, 1u, 2u, false, kDexMemAccessWide }, // Resolved field #2. 390 { 3u, 0u, 0u, false, kDexMemAccessWord }, // Unresolved field. 391 }; 392 static const MIRDef mirs[] = { 393 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 30u), 394 DEF_IGET(Instruction::IGET, 1u, 30u, 0u), // Resolved field #1, unique object. 395 DEF_IGET(Instruction::IGET, 2u, 31u, 0u), // Resolved field #1. 396 DEF_IGET_WIDE(Instruction::IGET_WIDE, 3u, 31u, 1u), // Resolved field #2. 397 DEF_IGET(Instruction::IGET, 5u, 32u, 2u), // Unresolved IGET can be "acquire". 398 DEF_IGET(Instruction::IGET, 6u, 30u, 0u), // Resolved field #1, unique object. 399 DEF_IGET(Instruction::IGET, 7u, 31u, 0u), // Resolved field #1. 400 DEF_IGET_WIDE(Instruction::IGET_WIDE, 8u, 31u, 1u), // Resolved field #2. 401 DEF_IPUT(Instruction::IPUT, 10u, 32u, 2u), // IPUT clobbers field #1 (#2 is wide). 402 DEF_IGET(Instruction::IGET, 11u, 30u, 0u), // Resolved field #1, unique object. 403 DEF_IGET(Instruction::IGET, 12u, 31u, 0u), // Resolved field #1, new value name. 404 DEF_IGET_WIDE(Instruction::IGET_WIDE, 13u, 31u, 1u), // Resolved field #2. 405 DEF_IGET_WIDE(Instruction::IGET_WIDE, 15u, 30u, 1u), // Resolved field #2, unique object. 406 DEF_IPUT(Instruction::IPUT, 17u, 30u, 2u), // IPUT clobbers field #1 (#2 is wide). 407 DEF_IGET(Instruction::IGET, 18u, 30u, 0u), // Resolved field #1, unique object. 408 DEF_IGET_WIDE(Instruction::IGET_WIDE, 19u, 30u, 1u), // Resolved field #2, unique object. 409 }; 410 411 PrepareIFields(ifields); 412 PrepareMIRs(mirs); 413 static const int32_t wide_sregs[] = { 3, 8, 13, 15, 19 }; 414 MarkAsWideSRegs(wide_sregs); 415 PerformLVN(); 416 ASSERT_EQ(value_names_.size(), 16u); 417 // Unresolved field is potentially volatile, so we need to adhere to the volatile semantics. 418 EXPECT_EQ(value_names_[1], value_names_[5]); // Unique object. 419 EXPECT_NE(value_names_[2], value_names_[6]); // Not guaranteed to be the same after "acquire". 420 EXPECT_NE(value_names_[3], value_names_[7]); // Not guaranteed to be the same after "acquire". 421 EXPECT_EQ(value_names_[1], value_names_[9]); // Unique object. 422 EXPECT_NE(value_names_[6], value_names_[10]); // This aliased with unresolved IPUT. 423 EXPECT_EQ(value_names_[7], value_names_[11]); // Still the same after "release". 424 EXPECT_EQ(value_names_[12], value_names_[15]); // Still the same after "release". 425 EXPECT_NE(value_names_[1], value_names_[14]); // This aliased with unresolved IPUT. 426 EXPECT_EQ(mirs_[0].optimization_flags, 0u); 427 EXPECT_EQ(mirs_[1].optimization_flags, MIR_IGNORE_NULL_CHECK); 428 EXPECT_EQ(mirs_[2].optimization_flags, 0u); 429 EXPECT_EQ(mirs_[3].optimization_flags, MIR_IGNORE_NULL_CHECK); 430 EXPECT_EQ(mirs_[4].optimization_flags, 0u); 431 for (size_t i = 5u; i != mir_count_; ++i) { 432 EXPECT_EQ((i == 1u || i == 3u || i >=5u) ? MIR_IGNORE_NULL_CHECK : 0, 433 mirs_[i].optimization_flags) << i; 434 } 435 } 436 437 TEST_F(LocalValueNumberingTest, UnresolvedSField) { 438 static const SFieldDef sfields[] = { 439 { 1u, 1u, 1u, false, kDexMemAccessWord }, // Resolved field #1. 440 { 2u, 1u, 2u, false, kDexMemAccessWide }, // Resolved field #2. 441 { 3u, 0u, 0u, false, kDexMemAccessWord }, // Unresolved field. 442 }; 443 static const MIRDef mirs[] = { 444 DEF_SGET(Instruction::SGET, 0u, 0u), // Resolved field #1. 445 DEF_SGET_WIDE(Instruction::SGET_WIDE, 1u, 1u), // Resolved field #2. 446 DEF_SGET(Instruction::SGET, 3u, 2u), // Unresolved SGET can be "acquire". 447 DEF_SGET(Instruction::SGET, 4u, 0u), // Resolved field #1. 448 DEF_SGET_WIDE(Instruction::SGET_WIDE, 5u, 1u), // Resolved field #2. 449 DEF_SPUT(Instruction::SPUT, 7u, 2u), // SPUT clobbers field #1 (#2 is wide). 450 DEF_SGET(Instruction::SGET, 8u, 0u), // Resolved field #1. 451 DEF_SGET_WIDE(Instruction::SGET_WIDE, 9u, 1u), // Resolved field #2. 452 }; 453 454 PrepareSFields(sfields); 455 PrepareMIRs(mirs); 456 static const int32_t wide_sregs[] = { 1, 5, 9 }; 457 MarkAsWideSRegs(wide_sregs); 458 PerformLVN(); 459 ASSERT_EQ(value_names_.size(), 8u); 460 // Unresolved field is potentially volatile, so we need to adhere to the volatile semantics. 461 EXPECT_NE(value_names_[0], value_names_[3]); // Not guaranteed to be the same after "acquire". 462 EXPECT_NE(value_names_[1], value_names_[4]); // Not guaranteed to be the same after "acquire". 463 EXPECT_NE(value_names_[3], value_names_[6]); // This aliased with unresolved IPUT. 464 EXPECT_EQ(value_names_[4], value_names_[7]); // Still the same after "release". 465 for (size_t i = 0u; i != mir_count_; ++i) { 466 EXPECT_EQ(0, mirs_[i].optimization_flags) << i; 467 } 468 } 469 470 TEST_F(LocalValueNumberingTest, UninitializedSField) { 471 static const IFieldDef ifields[] = { 472 { 1u, 1u, 1u, false, kDexMemAccessWord }, // Resolved field #1. 473 }; 474 static const SFieldDef sfields[] = { 475 { 1u, 1u, 1u, false, kDexMemAccessWord }, // Resolved field #1. 476 { 2u, 1u, 2u, false, kDexMemAccessWord }, // Resolved field #2; uninitialized. 477 }; 478 static const MIRDef mirs[] = { 479 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 200u), 480 DEF_IGET(Instruction::IGET, 1u, 100u, 0u), 481 DEF_IGET(Instruction::IGET, 2u, 200u, 0u), 482 DEF_SGET(Instruction::SGET, 3u, 0u), 483 DEF_SGET(Instruction::SGET, 4u, 1u), // Can call <clinit>(). 484 DEF_IGET(Instruction::IGET, 5u, 100u, 0u), // Differs from 1u. 485 DEF_IGET(Instruction::IGET, 6u, 200u, 0u), // Same as 2u. 486 DEF_SGET(Instruction::SGET, 7u, 0u), // Differs from 3u. 487 }; 488 489 PrepareIFields(ifields); 490 PrepareSFields(sfields); 491 MakeSFieldUninitialized(1u); 492 PrepareMIRs(mirs); 493 PerformLVN(); 494 ASSERT_EQ(value_names_.size(), 8u); 495 EXPECT_NE(value_names_[1], value_names_[5]); 496 EXPECT_EQ(value_names_[2], value_names_[6]); 497 EXPECT_NE(value_names_[3], value_names_[7]); 498 } 499 500 TEST_F(LocalValueNumberingTest, ConstString) { 501 static const MIRDef mirs[] = { 502 DEF_CONST_STRING(Instruction::CONST_STRING, 0u, 0u), 503 DEF_CONST_STRING(Instruction::CONST_STRING, 1u, 0u), 504 DEF_CONST_STRING(Instruction::CONST_STRING, 2u, 2u), 505 DEF_CONST_STRING(Instruction::CONST_STRING, 3u, 0u), 506 DEF_INVOKE1(Instruction::INVOKE_DIRECT, 2u), 507 DEF_CONST_STRING(Instruction::CONST_STRING, 4u, 2u), 508 }; 509 510 PrepareMIRs(mirs); 511 PerformLVN(); 512 ASSERT_EQ(value_names_.size(), 6u); 513 EXPECT_EQ(value_names_[1], value_names_[0]); 514 EXPECT_NE(value_names_[2], value_names_[0]); 515 EXPECT_EQ(value_names_[3], value_names_[0]); 516 EXPECT_EQ(value_names_[5], value_names_[2]); 517 } 518 519 TEST_F(LocalValueNumberingTest, SameValueInDifferentMemoryLocations) { 520 static const IFieldDef ifields[] = { 521 { 1u, 1u, 1u, false, kDexMemAccessWord }, 522 { 2u, 1u, 2u, false, kDexMemAccessWord }, 523 }; 524 static const SFieldDef sfields[] = { 525 { 3u, 1u, 3u, false, kDexMemAccessWord }, 526 }; 527 static const MIRDef mirs[] = { 528 DEF_UNIQUE_REF(Instruction::NEW_ARRAY, 201u), 529 DEF_IGET(Instruction::IGET, 0u, 100u, 0u), 530 DEF_IPUT(Instruction::IPUT, 0u, 100u, 1u), 531 DEF_IPUT(Instruction::IPUT, 0u, 101u, 1u), 532 DEF_APUT(Instruction::APUT, 0u, 200u, 300u), 533 DEF_APUT(Instruction::APUT, 0u, 200u, 301u), 534 DEF_APUT(Instruction::APUT, 0u, 201u, 300u), 535 DEF_APUT(Instruction::APUT, 0u, 201u, 301u), 536 DEF_SPUT(Instruction::SPUT, 0u, 0u), 537 DEF_IGET(Instruction::IGET, 9u, 100u, 0u), 538 DEF_IGET(Instruction::IGET, 10u, 100u, 1u), 539 DEF_IGET(Instruction::IGET, 11u, 101u, 1u), 540 DEF_AGET(Instruction::AGET, 12u, 200u, 300u), 541 DEF_AGET(Instruction::AGET, 13u, 200u, 301u), 542 DEF_AGET(Instruction::AGET, 14u, 201u, 300u), 543 DEF_AGET(Instruction::AGET, 15u, 201u, 301u), 544 DEF_SGET(Instruction::SGET, 16u, 0u), 545 }; 546 547 PrepareIFields(ifields); 548 PrepareSFields(sfields); 549 PrepareMIRs(mirs); 550 PerformLVN(); 551 ASSERT_EQ(value_names_.size(), 17u); 552 for (size_t i = 9; i != arraysize(mirs); ++i) { 553 EXPECT_EQ(value_names_[1], value_names_[i]) << i; 554 } 555 for (size_t i = 0; i != arraysize(mirs); ++i) { 556 int expected_flags = 557 ((i == 2u || (i >= 5u && i <= 7u) || (i >= 9u && i <= 15u)) ? MIR_IGNORE_NULL_CHECK : 0) | 558 ((i >= 12u && i <= 15u) ? MIR_IGNORE_RANGE_CHECK : 0); 559 EXPECT_EQ(expected_flags, mirs_[i].optimization_flags) << i; 560 } 561 } 562 563 TEST_F(LocalValueNumberingTest, UniqueArrayAliasing) { 564 static const MIRDef mirs[] = { 565 DEF_UNIQUE_REF(Instruction::NEW_ARRAY, 20u), 566 DEF_AGET(Instruction::AGET, 1u, 20u, 40u), 567 DEF_APUT(Instruction::APUT, 2u, 20u, 41u), // May alias with index for sreg 40u. 568 DEF_AGET(Instruction::AGET, 3u, 20u, 40u), 569 }; 570 571 PrepareMIRs(mirs); 572 PerformLVN(); 573 ASSERT_EQ(value_names_.size(), 4u); 574 EXPECT_NE(value_names_[1], value_names_[3]); 575 for (size_t i = 0; i != arraysize(mirs); ++i) { 576 int expected_flags = 577 ((i >= 1u) ? MIR_IGNORE_NULL_CHECK : 0) | 578 ((i == 3u) ? MIR_IGNORE_RANGE_CHECK : 0); 579 EXPECT_EQ(expected_flags, mirs_[i].optimization_flags) << i; 580 } 581 } 582 583 TEST_F(LocalValueNumberingTest, EscapingRefs) { 584 static const IFieldDef ifields[] = { 585 { 1u, 1u, 1u, false, kDexMemAccessWord }, // Field #1. 586 { 2u, 1u, 2u, false, kDexMemAccessWord }, // Field #2. 587 { 3u, 1u, 3u, false, kDexMemAccessObject }, // For storing escaping refs. 588 { 4u, 1u, 4u, false, kDexMemAccessWide }, // Wide. 589 { 5u, 0u, 0u, false, kDexMemAccessWord }, // Unresolved field, int. 590 { 6u, 0u, 0u, false, kDexMemAccessWide }, // Unresolved field, wide. 591 }; 592 static const MIRDef mirs[] = { 593 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 20u), 594 DEF_IGET(Instruction::IGET, 1u, 20u, 0u), 595 DEF_IGET(Instruction::IGET, 2u, 20u, 1u), 596 DEF_IPUT(Instruction::IPUT_OBJECT, 20u, 30u, 2u), // Ref escapes. 597 DEF_IGET(Instruction::IGET, 4u, 20u, 0u), 598 DEF_IGET(Instruction::IGET, 5u, 20u, 1u), 599 DEF_IPUT(Instruction::IPUT, 6u, 31u, 0u), // May alias with field #1. 600 DEF_IGET(Instruction::IGET, 7u, 20u, 0u), // New value. 601 DEF_IGET(Instruction::IGET, 8u, 20u, 1u), // Still the same. 602 DEF_IPUT_WIDE(Instruction::IPUT_WIDE, 9u, 31u, 3u), // No aliasing, different type. 603 DEF_IGET(Instruction::IGET, 11u, 20u, 0u), 604 DEF_IGET(Instruction::IGET, 12u, 20u, 1u), 605 DEF_IPUT_WIDE(Instruction::IPUT_WIDE, 13u, 31u, 5u), // No aliasing, different type. 606 DEF_IGET(Instruction::IGET, 15u, 20u, 0u), 607 DEF_IGET(Instruction::IGET, 16u, 20u, 1u), 608 DEF_IPUT(Instruction::IPUT, 17u, 31u, 4u), // Aliasing, same type. 609 DEF_IGET(Instruction::IGET, 18u, 20u, 0u), 610 DEF_IGET(Instruction::IGET, 19u, 20u, 1u), 611 }; 612 613 PrepareIFields(ifields); 614 PrepareMIRs(mirs); 615 static const int32_t wide_sregs[] = { 9, 13 }; 616 MarkAsWideSRegs(wide_sregs); 617 PerformLVN(); 618 ASSERT_EQ(value_names_.size(), 18u); 619 EXPECT_EQ(value_names_[1], value_names_[4]); 620 EXPECT_EQ(value_names_[2], value_names_[5]); 621 EXPECT_NE(value_names_[4], value_names_[7]); // New value. 622 EXPECT_EQ(value_names_[5], value_names_[8]); 623 EXPECT_EQ(value_names_[7], value_names_[10]); 624 EXPECT_EQ(value_names_[8], value_names_[11]); 625 EXPECT_EQ(value_names_[10], value_names_[13]); 626 EXPECT_EQ(value_names_[11], value_names_[14]); 627 EXPECT_NE(value_names_[13], value_names_[16]); // New value. 628 EXPECT_NE(value_names_[14], value_names_[17]); // New value. 629 for (size_t i = 0u; i != mir_count_; ++i) { 630 int expected = 631 ((i != 0u && i != 3u && i != 6u) ? MIR_IGNORE_NULL_CHECK : 0) | 632 ((i == 3u) ? MIR_STORE_NON_NULL_VALUE: 0); 633 EXPECT_EQ(expected, mirs_[i].optimization_flags) << i; 634 } 635 } 636 637 TEST_F(LocalValueNumberingTest, EscapingArrayRefs) { 638 static const MIRDef mirs[] = { 639 DEF_UNIQUE_REF(Instruction::NEW_ARRAY, 20u), 640 DEF_AGET(Instruction::AGET, 1u, 20u, 40u), 641 DEF_AGET(Instruction::AGET, 2u, 20u, 41u), 642 DEF_APUT(Instruction::APUT_OBJECT, 20u, 30u, 42u), // Array ref escapes. 643 DEF_AGET(Instruction::AGET, 4u, 20u, 40u), 644 DEF_AGET(Instruction::AGET, 5u, 20u, 41u), 645 DEF_APUT_WIDE(Instruction::APUT_WIDE, 6u, 31u, 43u), // No aliasing, different type. 646 DEF_AGET(Instruction::AGET, 8u, 20u, 40u), 647 DEF_AGET(Instruction::AGET, 9u, 20u, 41u), 648 DEF_APUT(Instruction::APUT, 10u, 32u, 40u), // May alias with all elements. 649 DEF_AGET(Instruction::AGET, 11u, 20u, 40u), // New value (same index name). 650 DEF_AGET(Instruction::AGET, 12u, 20u, 41u), // New value (different index name). 651 }; 652 653 PrepareMIRs(mirs); 654 static const int32_t wide_sregs[] = { 6 }; 655 MarkAsWideSRegs(wide_sregs); 656 PerformLVN(); 657 ASSERT_EQ(value_names_.size(), 12u); 658 EXPECT_EQ(value_names_[1], value_names_[4]); 659 EXPECT_EQ(value_names_[2], value_names_[5]); 660 EXPECT_EQ(value_names_[4], value_names_[7]); 661 EXPECT_EQ(value_names_[5], value_names_[8]); 662 EXPECT_NE(value_names_[7], value_names_[10]); // New value. 663 EXPECT_NE(value_names_[8], value_names_[11]); // New value. 664 for (size_t i = 0u; i != mir_count_; ++i) { 665 int expected = 666 ((i != 0u && i != 3u && i != 6u && i != 9u) ? MIR_IGNORE_NULL_CHECK : 0u) | 667 ((i >= 4 && i != 6u && i != 9u) ? MIR_IGNORE_RANGE_CHECK : 0u) | 668 ((i == 3u) ? MIR_STORE_NON_NULL_VALUE: 0); 669 EXPECT_EQ(expected, mirs_[i].optimization_flags) << i; 670 } 671 } 672 673 TEST_F(LocalValueNumberingTest, StoringSameValueKeepsMemoryVersion) { 674 static const IFieldDef ifields[] = { 675 { 1u, 1u, 1u, false, kDexMemAccessWord }, 676 { 2u, 1u, 2u, false, kDexMemAccessWord }, 677 }; 678 static const SFieldDef sfields[] = { 679 { 2u, 1u, 2u, false, kDexMemAccessWord }, 680 }; 681 static const MIRDef mirs[] = { 682 DEF_IGET(Instruction::IGET, 0u, 30u, 0u), 683 DEF_IGET(Instruction::IGET, 1u, 31u, 0u), 684 DEF_IPUT(Instruction::IPUT, 1u, 31u, 0u), // Store the same value. 685 DEF_IGET(Instruction::IGET, 3u, 30u, 0u), 686 DEF_AGET(Instruction::AGET, 4u, 32u, 40u), 687 DEF_AGET(Instruction::AGET, 5u, 33u, 40u), 688 DEF_APUT(Instruction::APUT, 5u, 33u, 40u), // Store the same value. 689 DEF_AGET(Instruction::AGET, 7u, 32u, 40u), 690 DEF_SGET(Instruction::SGET, 8u, 0u), 691 DEF_SPUT(Instruction::SPUT, 8u, 0u), // Store the same value. 692 DEF_SGET(Instruction::SGET, 10u, 0u), 693 DEF_UNIQUE_REF(Instruction::NEW_INSTANCE, 50u), // Test with unique references. 694 { Instruction::FILLED_NEW_ARRAY, 0, 0u, 2, { 12u, 13u }, 0, { } }, 695 DEF_UNIQUE_REF(Instruction::MOVE_RESULT_OBJECT, 51u), 696 DEF_IGET(Instruction::IGET, 14u, 50u, 0u), 697 DEF_IGET(Instruction::IGET, 15u, 50u, 1u), 698 DEF_IPUT(Instruction::IPUT, 15u, 50u, 1u), // Store the same value. 699 DEF_IGET(Instruction::IGET, 17u, 50u, 0u), 700 DEF_AGET(Instruction::AGET, 18u, 51u, 40u), 701 DEF_AGET(Instruction::AGET, 19u, 51u, 41u), 702 DEF_APUT(Instruction::APUT, 19u, 51u, 41u), // Store the same value. 703 DEF_AGET(Instruction::AGET, 21u, 51u, 40u), 704 }; 705 706 PrepareIFields(ifields); 707 PrepareSFields(sfields); 708 PrepareMIRs(mirs); 709 PerformLVN(); 710 ASSERT_EQ(value_names_.size(), 22u); 711 EXPECT_NE(value_names_[0], value_names_[1]); 712 EXPECT_EQ(value_names_[0], value_names_[3]); 713 EXPECT_NE(value_names_[4], value_names_[5]); 714 EXPECT_EQ(value_names_[4], value_names_[7]); 715 EXPECT_EQ(value_names_[8], value_names_[10]); 716 EXPECT_NE(value_names_[14], value_names_[15]); 717 EXPECT_EQ(value_names_[14], value_names_[17]); 718 EXPECT_NE(value_names_[18], value_names_[19]); 719 EXPECT_EQ(value_names_[18], value_names_[21]); 720 for (size_t i = 0u; i != mir_count_; ++i) { 721 int expected = 722 ((i == 2u || i == 3u || i == 6u || i == 7u || (i >= 14u)) ? MIR_IGNORE_NULL_CHECK : 0u) | 723 ((i == 6u || i == 7u || i >= 20u) ? MIR_IGNORE_RANGE_CHECK : 0u); 724 EXPECT_EQ(expected, mirs_[i].optimization_flags) << i; 725 } 726 } 727 728 TEST_F(LocalValueNumberingTest, FilledNewArrayTracking) { 729 if (!kLocalValueNumberingEnableFilledNewArrayTracking) { 730 // Feature disabled. 731 return; 732 } 733 static const MIRDef mirs[] = { 734 DEF_CONST(Instruction::CONST, 0u, 100), 735 DEF_CONST(Instruction::CONST, 1u, 200), 736 { Instruction::FILLED_NEW_ARRAY, 0, 0u, 2, { 0u, 1u }, 0, { } }, 737 DEF_UNIQUE_REF(Instruction::MOVE_RESULT_OBJECT, 10u), 738 DEF_CONST(Instruction::CONST, 20u, 0), 739 DEF_CONST(Instruction::CONST, 21u, 1), 740 DEF_AGET(Instruction::AGET, 6u, 10u, 20u), 741 DEF_AGET(Instruction::AGET, 7u, 10u, 21u), 742 }; 743 744 PrepareMIRs(mirs); 745 PerformLVN(); 746 ASSERT_EQ(value_names_.size(), 8u); 747 EXPECT_EQ(value_names_[0], value_names_[6]); 748 EXPECT_EQ(value_names_[1], value_names_[7]); 749 for (size_t i = 0u; i != mir_count_; ++i) { 750 int expected = (i == 6u || i == 7u) ? (MIR_IGNORE_NULL_CHECK | MIR_IGNORE_RANGE_CHECK) : 0u; 751 EXPECT_EQ(expected, mirs_[i].optimization_flags) << i; 752 } 753 } 754 755 TEST_F(LocalValueNumberingTest, ClInitOnSget) { 756 static const SFieldDef sfields[] = { 757 { 0u, 1u, 0u, false, kDexMemAccessObject }, 758 { 1u, 2u, 1u, false, kDexMemAccessObject }, 759 }; 760 static const MIRDef mirs[] = { 761 DEF_SGET(Instruction::SGET_OBJECT, 0u, 0u), 762 DEF_AGET(Instruction::AGET, 1u, 0u, 100u), 763 DEF_SGET(Instruction::SGET_OBJECT, 2u, 1u), 764 DEF_SGET(Instruction::SGET_OBJECT, 3u, 0u), 765 DEF_AGET(Instruction::AGET, 4u, 3u, 100u), 766 }; 767 768 PrepareSFields(sfields); 769 MakeSFieldUninitialized(1u); 770 PrepareMIRs(mirs); 771 PerformLVN(); 772 ASSERT_EQ(value_names_.size(), 5u); 773 EXPECT_NE(value_names_[0], value_names_[3]); 774 } 775 776 TEST_F(LocalValueNumberingTest, DivZeroCheck) { 777 static const MIRDef mirs[] = { 778 DEF_DIV_REM(Instruction::DIV_INT, 1u, 10u, 20u), 779 DEF_DIV_REM(Instruction::DIV_INT, 2u, 20u, 20u), 780 DEF_DIV_REM(Instruction::DIV_INT_2ADDR, 3u, 10u, 1u), 781 DEF_DIV_REM(Instruction::REM_INT, 4u, 30u, 20u), 782 DEF_DIV_REM_WIDE(Instruction::REM_LONG, 5u, 12u, 14u), 783 DEF_DIV_REM_WIDE(Instruction::DIV_LONG_2ADDR, 7u, 16u, 14u), 784 }; 785 786 static const bool expected_ignore_div_zero_check[] = { 787 false, true, false, true, false, true, 788 }; 789 790 PrepareMIRs(mirs); 791 static const int32_t wide_sregs[] = { 5, 7, 12, 14, 16 }; 792 MarkAsWideSRegs(wide_sregs); 793 PerformLVN(); 794 for (size_t i = 0u; i != mir_count_; ++i) { 795 int expected = expected_ignore_div_zero_check[i] ? MIR_IGNORE_DIV_ZERO_CHECK : 0u; 796 EXPECT_EQ(expected, mirs_[i].optimization_flags) << i; 797 } 798 } 799 800 TEST_F(LocalValueNumberingTest, ConstWide) { 801 static const MIRDef mirs[] = { 802 // Core reg constants. 803 DEF_CONST(Instruction::CONST_WIDE_16, 0u, 0), 804 DEF_CONST(Instruction::CONST_WIDE_16, 2u, 1), 805 DEF_CONST(Instruction::CONST_WIDE_16, 4u, -1), 806 DEF_CONST(Instruction::CONST_WIDE_32, 6u, 1 << 16), 807 DEF_CONST(Instruction::CONST_WIDE_32, 8u, -1 << 16), 808 DEF_CONST(Instruction::CONST_WIDE_32, 10u, (1 << 16) + 1), 809 DEF_CONST(Instruction::CONST_WIDE_32, 12u, (1 << 16) - 1), 810 DEF_CONST(Instruction::CONST_WIDE_32, 14u, -(1 << 16) + 1), 811 DEF_CONST(Instruction::CONST_WIDE_32, 16u, -(1 << 16) - 1), 812 DEF_CONST(Instruction::CONST_WIDE, 18u, INT64_C(1) << 32), 813 DEF_CONST(Instruction::CONST_WIDE, 20u, INT64_C(-1) << 32), 814 DEF_CONST(Instruction::CONST_WIDE, 22u, (INT64_C(1) << 32) + 1), 815 DEF_CONST(Instruction::CONST_WIDE, 24u, (INT64_C(1) << 32) - 1), 816 DEF_CONST(Instruction::CONST_WIDE, 26u, (INT64_C(-1) << 32) + 1), 817 DEF_CONST(Instruction::CONST_WIDE, 28u, (INT64_C(-1) << 32) - 1), 818 DEF_CONST(Instruction::CONST_WIDE_HIGH16, 30u, 1), // Effectively 1 << 48. 819 DEF_CONST(Instruction::CONST_WIDE_HIGH16, 32u, 0xffff), // Effectively -1 << 48. 820 DEF_CONST(Instruction::CONST_WIDE, 34u, (INT64_C(1) << 48) + 1), 821 DEF_CONST(Instruction::CONST_WIDE, 36u, (INT64_C(1) << 48) - 1), 822 DEF_CONST(Instruction::CONST_WIDE, 38u, (INT64_C(-1) << 48) + 1), 823 DEF_CONST(Instruction::CONST_WIDE, 40u, (INT64_C(-1) << 48) - 1), 824 // FP reg constants. 825 DEF_CONST(Instruction::CONST_WIDE_16, 42u, 0), 826 DEF_CONST(Instruction::CONST_WIDE_16, 44u, 1), 827 DEF_CONST(Instruction::CONST_WIDE_16, 46u, -1), 828 DEF_CONST(Instruction::CONST_WIDE_32, 48u, 1 << 16), 829 DEF_CONST(Instruction::CONST_WIDE_32, 50u, -1 << 16), 830 DEF_CONST(Instruction::CONST_WIDE_32, 52u, (1 << 16) + 1), 831 DEF_CONST(Instruction::CONST_WIDE_32, 54u, (1 << 16) - 1), 832 DEF_CONST(Instruction::CONST_WIDE_32, 56u, -(1 << 16) + 1), 833 DEF_CONST(Instruction::CONST_WIDE_32, 58u, -(1 << 16) - 1), 834 DEF_CONST(Instruction::CONST_WIDE, 60u, INT64_C(1) << 32), 835 DEF_CONST(Instruction::CONST_WIDE, 62u, INT64_C(-1) << 32), 836 DEF_CONST(Instruction::CONST_WIDE, 64u, (INT64_C(1) << 32) + 1), 837 DEF_CONST(Instruction::CONST_WIDE, 66u, (INT64_C(1) << 32) - 1), 838 DEF_CONST(Instruction::CONST_WIDE, 68u, (INT64_C(-1) << 32) + 1), 839 DEF_CONST(Instruction::CONST_WIDE, 70u, (INT64_C(-1) << 32) - 1), 840 DEF_CONST(Instruction::CONST_WIDE_HIGH16, 72u, 1), // Effectively 1 << 48. 841 DEF_CONST(Instruction::CONST_WIDE_HIGH16, 74u, 0xffff), // Effectively -1 << 48. 842 DEF_CONST(Instruction::CONST_WIDE, 76u, (INT64_C(1) << 48) + 1), 843 DEF_CONST(Instruction::CONST_WIDE, 78u, (INT64_C(1) << 48) - 1), 844 DEF_CONST(Instruction::CONST_WIDE, 80u, (INT64_C(-1) << 48) + 1), 845 DEF_CONST(Instruction::CONST_WIDE, 82u, (INT64_C(-1) << 48) - 1), 846 }; 847 848 PrepareMIRs(mirs); 849 for (size_t i = 0; i != arraysize(mirs); ++i) { 850 const int32_t wide_sregs[] = { mirs_[i].ssa_rep->defs[0] }; 851 MarkAsWideSRegs(wide_sregs); 852 } 853 for (size_t i = arraysize(mirs) / 2u; i != arraysize(mirs); ++i) { 854 cu_.mir_graph->reg_location_[mirs_[i].ssa_rep->defs[0]].fp = true; 855 } 856 PerformLVN(); 857 for (size_t i = 0u; i != mir_count_; ++i) { 858 for (size_t j = i + 1u; j != mir_count_; ++j) { 859 EXPECT_NE(value_names_[i], value_names_[j]) << i << " " << j; 860 } 861 } 862 } 863 864 TEST_F(LocalValueNumberingTest, Const) { 865 static const MIRDef mirs[] = { 866 // Core reg constants. 867 DEF_CONST(Instruction::CONST_4, 0u, 0), 868 DEF_CONST(Instruction::CONST_4, 1u, 1), 869 DEF_CONST(Instruction::CONST_4, 2u, -1), 870 DEF_CONST(Instruction::CONST_16, 3u, 1 << 4), 871 DEF_CONST(Instruction::CONST_16, 4u, -1 << 4), 872 DEF_CONST(Instruction::CONST_16, 5u, (1 << 4) + 1), 873 DEF_CONST(Instruction::CONST_16, 6u, (1 << 4) - 1), 874 DEF_CONST(Instruction::CONST_16, 7u, -(1 << 4) + 1), 875 DEF_CONST(Instruction::CONST_16, 8u, -(1 << 4) - 1), 876 DEF_CONST(Instruction::CONST_HIGH16, 9u, 1), // Effectively 1 << 16. 877 DEF_CONST(Instruction::CONST_HIGH16, 10u, 0xffff), // Effectively -1 << 16. 878 DEF_CONST(Instruction::CONST, 11u, (1 << 16) + 1), 879 DEF_CONST(Instruction::CONST, 12u, (1 << 16) - 1), 880 DEF_CONST(Instruction::CONST, 13u, (-1 << 16) + 1), 881 DEF_CONST(Instruction::CONST, 14u, (-1 << 16) - 1), 882 // FP reg constants. 883 DEF_CONST(Instruction::CONST_4, 15u, 0), 884 DEF_CONST(Instruction::CONST_4, 16u, 1), 885 DEF_CONST(Instruction::CONST_4, 17u, -1), 886 DEF_CONST(Instruction::CONST_16, 18u, 1 << 4), 887 DEF_CONST(Instruction::CONST_16, 19u, -1 << 4), 888 DEF_CONST(Instruction::CONST_16, 20u, (1 << 4) + 1), 889 DEF_CONST(Instruction::CONST_16, 21u, (1 << 4) - 1), 890 DEF_CONST(Instruction::CONST_16, 22u, -(1 << 4) + 1), 891 DEF_CONST(Instruction::CONST_16, 23u, -(1 << 4) - 1), 892 DEF_CONST(Instruction::CONST_HIGH16, 24u, 1), // Effectively 1 << 16. 893 DEF_CONST(Instruction::CONST_HIGH16, 25u, 0xffff), // Effectively -1 << 16. 894 DEF_CONST(Instruction::CONST, 26u, (1 << 16) + 1), 895 DEF_CONST(Instruction::CONST, 27u, (1 << 16) - 1), 896 DEF_CONST(Instruction::CONST, 28u, (-1 << 16) + 1), 897 DEF_CONST(Instruction::CONST, 29u, (-1 << 16) - 1), 898 // null reference constant. 899 DEF_CONST(Instruction::CONST_4, 30u, 0), 900 }; 901 902 PrepareMIRs(mirs); 903 static_assert((arraysize(mirs) & 1) != 0, "missing null or unmatched fp/core"); 904 cu_.mir_graph->reg_location_[arraysize(mirs) - 1].ref = true; 905 for (size_t i = arraysize(mirs) / 2u; i != arraysize(mirs) - 1; ++i) { 906 cu_.mir_graph->reg_location_[mirs_[i].ssa_rep->defs[0]].fp = true; 907 } 908 PerformLVN(); 909 for (size_t i = 0u; i != mir_count_; ++i) { 910 for (size_t j = i + 1u; j != mir_count_; ++j) { 911 EXPECT_NE(value_names_[i], value_names_[j]) << i << " " << j; 912 } 913 } 914 } 915 916 } // namespace art 917