OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file | 3 // found in the LICENSE file |
4 | 4 |
5 #include "test/unittests/compiler/instruction-selector-unittest.h" | 5 #include "test/unittests/compiler/instruction-selector-unittest.h" |
6 | 6 |
7 namespace v8 { | 7 namespace v8 { |
8 namespace internal { | 8 namespace internal { |
9 namespace compiler { | 9 namespace compiler { |
10 | 10 |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 EXPECT_EQ(2U, s[0]->InputCount()); | 288 EXPECT_EQ(2U, s[0]->InputCount()); |
289 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); | 289 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); |
290 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | 290 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
291 EXPECT_EQ(1U, s[0]->OutputCount()); | 291 EXPECT_EQ(1U, s[0]->OutputCount()); |
292 } | 292 } |
293 } | 293 } |
294 | 294 |
295 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest, | 295 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest, |
296 ::testing::ValuesIn(kShiftInstructions)); | 296 ::testing::ValuesIn(kShiftInstructions)); |
297 | 297 |
| 298 TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) { |
| 299 // The available shift operand range is `0 <= imm < 32`, but we also test |
| 300 // that immediates outside this range are handled properly (modulo-32). |
| 301 TRACED_FORRANGE(int32_t, shift, -32, 63) { |
| 302 int32_t lsb = shift & 0x1f; |
| 303 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { |
| 304 uint32_t jnk = rng()->NextInt(); |
| 305 jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0; |
| 306 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk; |
| 307 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 308 m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)), |
| 309 m.Int32Constant(shift))); |
| 310 Stream s = m.Build(); |
| 311 ASSERT_EQ(1U, s.size()); |
| 312 EXPECT_EQ(kMips64Ext, s[0]->arch_opcode()); |
| 313 ASSERT_EQ(3U, s[0]->InputCount()); |
| 314 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); |
| 315 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); |
| 316 } |
| 317 } |
| 318 TRACED_FORRANGE(int32_t, shift, -32, 63) { |
| 319 int32_t lsb = shift & 0x1f; |
| 320 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { |
| 321 uint32_t jnk = rng()->NextInt(); |
| 322 jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0; |
| 323 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk; |
| 324 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 325 m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)), |
| 326 m.Int32Constant(shift))); |
| 327 Stream s = m.Build(); |
| 328 ASSERT_EQ(1U, s.size()); |
| 329 EXPECT_EQ(kMips64Ext, s[0]->arch_opcode()); |
| 330 ASSERT_EQ(3U, s[0]->InputCount()); |
| 331 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); |
| 332 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); |
| 333 } |
| 334 } |
| 335 } |
| 336 |
| 337 |
| 338 TEST_F(InstructionSelectorTest, Word64ShrWithWord64AndWithImmediate) { |
| 339 // The available shift operand range is `0 <= imm < 64`, but we also test |
| 340 // that immediates outside this range are handled properly (modulo-64). |
| 341 TRACED_FORRANGE(int32_t, shift, -64, 127) { |
| 342 int32_t lsb = shift & 0x3f; |
| 343 TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) { |
| 344 uint64_t jnk = rng()->NextInt64(); |
| 345 jnk = (lsb > 0) ? (jnk >> (64 - lsb)) : 0; |
| 346 uint64_t msk = |
| 347 ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk; |
| 348 StreamBuilder m(this, kMachInt64, kMachInt64); |
| 349 m.Return(m.Word64Shr(m.Word64And(m.Parameter(0), m.Int64Constant(msk)), |
| 350 m.Int64Constant(shift))); |
| 351 Stream s = m.Build(); |
| 352 ASSERT_EQ(1U, s.size()); |
| 353 EXPECT_EQ(kMips64Dext, s[0]->arch_opcode()); |
| 354 ASSERT_EQ(3U, s[0]->InputCount()); |
| 355 EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1))); |
| 356 EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2))); |
| 357 } |
| 358 } |
| 359 TRACED_FORRANGE(int32_t, shift, -64, 127) { |
| 360 int32_t lsb = shift & 0x3f; |
| 361 TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) { |
| 362 uint64_t jnk = rng()->NextInt64(); |
| 363 jnk = (lsb > 0) ? (jnk >> (64 - lsb)) : 0; |
| 364 uint64_t msk = |
| 365 ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk; |
| 366 StreamBuilder m(this, kMachInt64, kMachInt64); |
| 367 m.Return(m.Word64Shr(m.Word64And(m.Int64Constant(msk), m.Parameter(0)), |
| 368 m.Int64Constant(shift))); |
| 369 Stream s = m.Build(); |
| 370 ASSERT_EQ(1U, s.size()); |
| 371 EXPECT_EQ(kMips64Dext, s[0]->arch_opcode()); |
| 372 ASSERT_EQ(3U, s[0]->InputCount()); |
| 373 EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1))); |
| 374 EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2))); |
| 375 } |
| 376 } |
| 377 } |
| 378 |
| 379 |
298 // ---------------------------------------------------------------------------- | 380 // ---------------------------------------------------------------------------- |
299 // Logical instructions. | 381 // Logical instructions. |
300 // ---------------------------------------------------------------------------- | 382 // ---------------------------------------------------------------------------- |
301 typedef InstructionSelectorTestWithParam<MachInst2> | 383 typedef InstructionSelectorTestWithParam<MachInst2> |
302 InstructionSelectorLogicalTest; | 384 InstructionSelectorLogicalTest; |
303 | 385 |
304 | 386 |
305 TEST_P(InstructionSelectorLogicalTest, Parameter) { | 387 TEST_P(InstructionSelectorLogicalTest, Parameter) { |
306 const MachInst2 dpi = GetParam(); | 388 const MachInst2 dpi = GetParam(); |
307 const MachineType type = dpi.machine_type; | 389 const MachineType type = dpi.machine_type; |
308 StreamBuilder m(this, type, type, type); | 390 StreamBuilder m(this, type, type, type); |
309 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | 391 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); |
310 Stream s = m.Build(); | 392 Stream s = m.Build(); |
311 ASSERT_EQ(1U, s.size()); | 393 ASSERT_EQ(1U, s.size()); |
312 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | 394 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
313 EXPECT_EQ(2U, s[0]->InputCount()); | 395 EXPECT_EQ(2U, s[0]->InputCount()); |
314 EXPECT_EQ(1U, s[0]->OutputCount()); | 396 EXPECT_EQ(1U, s[0]->OutputCount()); |
315 } | 397 } |
316 | 398 |
317 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest, | 399 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest, |
318 ::testing::ValuesIn(kLogicalInstructions)); | 400 ::testing::ValuesIn(kLogicalInstructions)); |
319 | 401 |
| 402 |
| 403 TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) { |
| 404 // The available shift operand range is `0 <= imm < 32`, but we also test |
| 405 // that immediates outside this range are handled properly (modulo-32). |
| 406 TRACED_FORRANGE(int32_t, shift, -32, 63) { |
| 407 int32_t lsb = shift & 0x1f; |
| 408 TRACED_FORRANGE(int32_t, width, 1, 31) { |
| 409 uint32_t msk = (1 << width) - 1; |
| 410 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 411 m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)), |
| 412 m.Int32Constant(msk))); |
| 413 Stream s = m.Build(); |
| 414 ASSERT_EQ(1U, s.size()); |
| 415 EXPECT_EQ(kMips64Ext, s[0]->arch_opcode()); |
| 416 ASSERT_EQ(3U, s[0]->InputCount()); |
| 417 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); |
| 418 int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width; |
| 419 EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2))); |
| 420 } |
| 421 } |
| 422 TRACED_FORRANGE(int32_t, shift, -32, 63) { |
| 423 int32_t lsb = shift & 0x1f; |
| 424 TRACED_FORRANGE(int32_t, width, 1, 31) { |
| 425 uint32_t msk = (1 << width) - 1; |
| 426 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 427 m.Return( |
| 428 m.Word32And(m.Int32Constant(msk), |
| 429 m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)))); |
| 430 Stream s = m.Build(); |
| 431 ASSERT_EQ(1U, s.size()); |
| 432 EXPECT_EQ(kMips64Ext, s[0]->arch_opcode()); |
| 433 ASSERT_EQ(3U, s[0]->InputCount()); |
| 434 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); |
| 435 int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width; |
| 436 EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2))); |
| 437 } |
| 438 } |
| 439 } |
| 440 |
| 441 |
| 442 TEST_F(InstructionSelectorTest, Word64AndWithImmediateWithWord64Shr) { |
| 443 // The available shift operand range is `0 <= imm < 64`, but we also test |
| 444 // that immediates outside this range are handled properly (modulo-64). |
| 445 TRACED_FORRANGE(int64_t, shift, -64, 127) { |
| 446 int64_t lsb = shift & 0x3f; |
| 447 TRACED_FORRANGE(int64_t, width, 1, 63) { |
| 448 uint64_t msk = (V8_UINT64_C(1) << width) - 1; |
| 449 StreamBuilder m(this, kMachInt64, kMachInt64); |
| 450 m.Return(m.Word64And(m.Word64Shr(m.Parameter(0), m.Int64Constant(shift)), |
| 451 m.Int64Constant(msk))); |
| 452 Stream s = m.Build(); |
| 453 ASSERT_EQ(1U, s.size()); |
| 454 EXPECT_EQ(kMips64Dext, s[0]->arch_opcode()); |
| 455 ASSERT_EQ(3U, s[0]->InputCount()); |
| 456 EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1))); |
| 457 int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width; |
| 458 EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2))); |
| 459 } |
| 460 } |
| 461 TRACED_FORRANGE(int64_t, shift, -64, 127) { |
| 462 int64_t lsb = shift & 0x3f; |
| 463 TRACED_FORRANGE(int64_t, width, 1, 63) { |
| 464 uint64_t msk = (V8_UINT64_C(1) << width) - 1; |
| 465 StreamBuilder m(this, kMachInt64, kMachInt64); |
| 466 m.Return( |
| 467 m.Word64And(m.Int64Constant(msk), |
| 468 m.Word64Shr(m.Parameter(0), m.Int64Constant(shift)))); |
| 469 Stream s = m.Build(); |
| 470 ASSERT_EQ(1U, s.size()); |
| 471 EXPECT_EQ(kMips64Dext, s[0]->arch_opcode()); |
| 472 ASSERT_EQ(3U, s[0]->InputCount()); |
| 473 EXPECT_EQ(lsb, s.ToInt64(s[0]->InputAt(1))); |
| 474 int64_t actual_width = (lsb + width > 64) ? (64 - lsb) : width; |
| 475 EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2))); |
| 476 } |
| 477 } |
| 478 } |
| 479 |
| 480 |
320 // ---------------------------------------------------------------------------- | 481 // ---------------------------------------------------------------------------- |
321 // MUL/DIV instructions. | 482 // MUL/DIV instructions. |
322 // ---------------------------------------------------------------------------- | 483 // ---------------------------------------------------------------------------- |
323 typedef InstructionSelectorTestWithParam<MachInst2> | 484 typedef InstructionSelectorTestWithParam<MachInst2> |
324 InstructionSelectorMulDivTest; | 485 InstructionSelectorMulDivTest; |
325 | 486 |
326 TEST_P(InstructionSelectorMulDivTest, Parameter) { | 487 TEST_P(InstructionSelectorMulDivTest, Parameter) { |
327 const MachInst2 dpi = GetParam(); | 488 const MachInst2 dpi = GetParam(); |
328 const MachineType type = dpi.machine_type; | 489 const MachineType type = dpi.machine_type; |
329 StreamBuilder m(this, type, type, type); | 490 StreamBuilder m(this, type, type, type); |
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
945 ASSERT_EQ(1U, s.size()); | 1106 ASSERT_EQ(1U, s.size()); |
946 EXPECT_EQ(kMips64Float64Min, s[0]->arch_opcode()); | 1107 EXPECT_EQ(kMips64Float64Min, s[0]->arch_opcode()); |
947 ASSERT_EQ(2U, s[0]->InputCount()); | 1108 ASSERT_EQ(2U, s[0]->InputCount()); |
948 ASSERT_EQ(1U, s[0]->OutputCount()); | 1109 ASSERT_EQ(1U, s[0]->OutputCount()); |
949 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 1110 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
950 } | 1111 } |
951 | 1112 |
952 } // namespace compiler | 1113 } // namespace compiler |
953 } // namespace internal | 1114 } // namespace internal |
954 } // namespace v8 | 1115 } // namespace v8 |
OLD | NEW |