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 <list> | 5 #include <list> |
6 | 6 |
7 #include "src/compiler/instruction-selector-unittest.h" | 7 #include "src/compiler/instruction-selector-unittest.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
11 namespace compiler { | 11 namespace compiler { |
12 | 12 |
13 namespace { | 13 namespace { |
14 | 14 |
| 15 typedef RawMachineAssembler::Label MLabel; |
| 16 |
15 template <typename T> | 17 template <typename T> |
16 struct MachInst { | 18 struct MachInst { |
17 T constructor; | 19 T constructor; |
18 const char* constructor_name; | 20 const char* constructor_name; |
19 ArchOpcode arch_opcode; | 21 ArchOpcode arch_opcode; |
20 MachineType machine_type; | 22 MachineType machine_type; |
21 }; | 23 }; |
22 | 24 |
23 typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1; | 25 typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1; |
24 typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2; | 26 typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 2944, 3377, 3458, 3475, 3476, 3540, 3574, | 83 2944, 3377, 3458, 3475, 3476, 3540, 3574, |
82 3601, 3813, 3871, 3917, 4095, 4096, 16384, | 84 3601, 3813, 3871, 3917, 4095, 4096, 16384, |
83 364544, 462848, 970752, 1523712, 1863680, 2363392, 3219456, | 85 364544, 462848, 970752, 1523712, 1863680, 2363392, 3219456, |
84 3280896, 4247552, 4526080, 4575232, 4960256, 5505024, 5894144, | 86 3280896, 4247552, 4526080, 4575232, 4960256, 5505024, 5894144, |
85 6004736, 6193152, 6385664, 6795264, 7114752, 7233536, 7348224, | 87 6004736, 6193152, 6385664, 6795264, 7114752, 7233536, 7348224, |
86 7499776, 7573504, 7729152, 8634368, 8937472, 9465856, 10354688, | 88 7499776, 7573504, 7729152, 8634368, 8937472, 9465856, 10354688, |
87 10682368, 11059200, 11460608, 13168640, 13176832, 14336000, 15028224, | 89 10682368, 11059200, 11460608, 13168640, 13176832, 14336000, 15028224, |
88 15597568, 15892480, 16773120}; | 90 15597568, 15892480, 16773120}; |
89 | 91 |
90 | 92 |
| 93 // ARM64 flag setting data processing instructions. |
| 94 static const MachInst2 kDPFlagSetInstructions[] = { |
| 95 {&RawMachineAssembler::Word32And, "Word32And", kArm64Tst32, kMachInt32}, |
| 96 {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Cmn32, kMachInt32}, |
| 97 {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Cmp32, kMachInt32}}; |
| 98 |
| 99 |
91 // ARM64 arithmetic with overflow instructions. | 100 // ARM64 arithmetic with overflow instructions. |
92 static const MachInst2 kOvfAddSubInstructions[] = { | 101 static const MachInst2 kOvfAddSubInstructions[] = { |
93 {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow", | 102 {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow", |
94 kArm64Add32, kMachInt32}, | 103 kArm64Add32, kMachInt32}, |
95 {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow", | 104 {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow", |
96 kArm64Sub32, kMachInt32}}; | 105 kArm64Sub32, kMachInt32}}; |
97 | 106 |
98 | 107 |
99 // ARM64 shift instructions. | 108 // ARM64 shift instructions. |
100 static const MachInst2 kShiftInstructions[] = { | 109 static const MachInst2 kShiftInstructions[] = { |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 | 346 |
338 ASSERT_EQ(1U, s.size()); | 347 ASSERT_EQ(1U, s.size()); |
339 EXPECT_EQ(kArm64Neg, s[0]->arch_opcode()); | 348 EXPECT_EQ(kArm64Neg, s[0]->arch_opcode()); |
340 EXPECT_EQ(1U, s[0]->InputCount()); | 349 EXPECT_EQ(1U, s[0]->InputCount()); |
341 EXPECT_EQ(1U, s[0]->OutputCount()); | 350 EXPECT_EQ(1U, s[0]->OutputCount()); |
342 } | 351 } |
343 } | 352 } |
344 | 353 |
345 | 354 |
346 // ----------------------------------------------------------------------------- | 355 // ----------------------------------------------------------------------------- |
| 356 // Data processing controlled branches. |
| 357 |
| 358 |
| 359 typedef InstructionSelectorTestWithParam<MachInst2> |
| 360 InstructionSelectorDPFlagSetTest; |
| 361 |
| 362 |
| 363 TEST_P(InstructionSelectorDPFlagSetTest, BranchWithParameters) { |
| 364 const MachInst2 dpi = GetParam(); |
| 365 const MachineType type = dpi.machine_type; |
| 366 StreamBuilder m(this, type, type, type); |
| 367 MLabel a, b; |
| 368 m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b); |
| 369 m.Bind(&a); |
| 370 m.Return(m.Int32Constant(1)); |
| 371 m.Bind(&b); |
| 372 m.Return(m.Int32Constant(0)); |
| 373 Stream s = m.Build(); |
| 374 ASSERT_EQ(1U, s.size()); |
| 375 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| 376 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 377 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 378 } |
| 379 |
| 380 |
| 381 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
| 382 InstructionSelectorDPFlagSetTest, |
| 383 ::testing::ValuesIn(kDPFlagSetInstructions)); |
| 384 |
| 385 |
| 386 TEST_F(InstructionSelectorTest, AndBranchWithImmediateOnRight) { |
| 387 TRACED_FOREACH(int32_t, imm, kLogicalImmediates) { |
| 388 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 389 MLabel a, b; |
| 390 m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(imm)), &a, &b); |
| 391 m.Bind(&a); |
| 392 m.Return(m.Int32Constant(1)); |
| 393 m.Bind(&b); |
| 394 m.Return(m.Int32Constant(0)); |
| 395 Stream s = m.Build(); |
| 396 ASSERT_EQ(1U, s.size()); |
| 397 EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode()); |
| 398 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 399 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 400 } |
| 401 } |
| 402 |
| 403 |
| 404 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnRight) { |
| 405 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
| 406 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 407 MLabel a, b; |
| 408 m.Branch(m.Int32Add(m.Parameter(0), m.Int32Constant(imm)), &a, &b); |
| 409 m.Bind(&a); |
| 410 m.Return(m.Int32Constant(1)); |
| 411 m.Bind(&b); |
| 412 m.Return(m.Int32Constant(0)); |
| 413 Stream s = m.Build(); |
| 414 ASSERT_EQ(1U, s.size()); |
| 415 EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode()); |
| 416 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 417 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 418 } |
| 419 } |
| 420 |
| 421 |
| 422 TEST_F(InstructionSelectorTest, SubBranchWithImmediateOnRight) { |
| 423 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
| 424 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 425 MLabel a, b; |
| 426 m.Branch(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm)), &a, &b); |
| 427 m.Bind(&a); |
| 428 m.Return(m.Int32Constant(1)); |
| 429 m.Bind(&b); |
| 430 m.Return(m.Int32Constant(0)); |
| 431 Stream s = m.Build(); |
| 432 ASSERT_EQ(1U, s.size()); |
| 433 EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode()); |
| 434 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 435 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 436 } |
| 437 } |
| 438 |
| 439 |
| 440 TEST_F(InstructionSelectorTest, AndBranchWithImmediateOnLeft) { |
| 441 TRACED_FOREACH(int32_t, imm, kLogicalImmediates) { |
| 442 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 443 MLabel a, b; |
| 444 m.Branch(m.Word32And(m.Int32Constant(imm), m.Parameter(0)), &a, &b); |
| 445 m.Bind(&a); |
| 446 m.Return(m.Int32Constant(1)); |
| 447 m.Bind(&b); |
| 448 m.Return(m.Int32Constant(0)); |
| 449 Stream s = m.Build(); |
| 450 ASSERT_EQ(1U, s.size()); |
| 451 EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode()); |
| 452 ASSERT_LE(1U, s[0]->InputCount()); |
| 453 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 454 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 455 } |
| 456 } |
| 457 |
| 458 |
| 459 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnLeft) { |
| 460 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
| 461 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 462 MLabel a, b; |
| 463 m.Branch(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)), &a, &b); |
| 464 m.Bind(&a); |
| 465 m.Return(m.Int32Constant(1)); |
| 466 m.Bind(&b); |
| 467 m.Return(m.Int32Constant(0)); |
| 468 Stream s = m.Build(); |
| 469 ASSERT_EQ(1U, s.size()); |
| 470 EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode()); |
| 471 ASSERT_LE(1U, s[0]->InputCount()); |
| 472 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 473 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 474 } |
| 475 } |
| 476 |
| 477 |
| 478 // ----------------------------------------------------------------------------- |
347 // Add and subtract instructions with overflow. | 479 // Add and subtract instructions with overflow. |
348 | 480 |
349 | 481 |
350 typedef InstructionSelectorTestWithParam<MachInst2> | 482 typedef InstructionSelectorTestWithParam<MachInst2> |
351 InstructionSelectorOvfAddSubTest; | 483 InstructionSelectorOvfAddSubTest; |
352 | 484 |
353 | 485 |
354 TEST_P(InstructionSelectorOvfAddSubTest, OvfParameter) { | 486 TEST_P(InstructionSelectorOvfAddSubTest, OvfParameter) { |
355 const MachInst2 dpi = GetParam(); | 487 const MachInst2 dpi = GetParam(); |
356 const MachineType type = dpi.machine_type; | 488 const MachineType type = dpi.machine_type; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | 579 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
448 ASSERT_EQ(2U, s[0]->InputCount()); | 580 ASSERT_EQ(2U, s[0]->InputCount()); |
449 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | 581 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
450 EXPECT_EQ(2U, s[0]->OutputCount()); | 582 EXPECT_EQ(2U, s[0]->OutputCount()); |
451 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | 583 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
452 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | 584 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
453 } | 585 } |
454 } | 586 } |
455 | 587 |
456 | 588 |
| 589 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithParameters) { |
| 590 const MachInst2 dpi = GetParam(); |
| 591 const MachineType type = dpi.machine_type; |
| 592 StreamBuilder m(this, type, type, type); |
| 593 MLabel a, b; |
| 594 Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)); |
| 595 m.Branch(m.Projection(1, n), &a, &b); |
| 596 m.Bind(&a); |
| 597 m.Return(m.Int32Constant(0)); |
| 598 m.Bind(&b); |
| 599 m.Return(m.Projection(0, n)); |
| 600 Stream s = m.Build(); |
| 601 ASSERT_EQ(1U, s.size()); |
| 602 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| 603 EXPECT_EQ(4U, s[0]->InputCount()); |
| 604 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 605 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 606 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 607 } |
| 608 |
| 609 |
| 610 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithImmediateOnRight) { |
| 611 const MachInst2 dpi = GetParam(); |
| 612 const MachineType type = dpi.machine_type; |
| 613 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
| 614 StreamBuilder m(this, type, type); |
| 615 MLabel a, b; |
| 616 Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)); |
| 617 m.Branch(m.Projection(1, n), &a, &b); |
| 618 m.Bind(&a); |
| 619 m.Return(m.Int32Constant(0)); |
| 620 m.Bind(&b); |
| 621 m.Return(m.Projection(0, n)); |
| 622 Stream s = m.Build(); |
| 623 ASSERT_EQ(1U, s.size()); |
| 624 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| 625 ASSERT_EQ(4U, s[0]->InputCount()); |
| 626 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 627 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 628 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 629 } |
| 630 } |
| 631 |
| 632 |
457 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | 633 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
458 InstructionSelectorOvfAddSubTest, | 634 InstructionSelectorOvfAddSubTest, |
459 ::testing::ValuesIn(kOvfAddSubInstructions)); | 635 ::testing::ValuesIn(kOvfAddSubInstructions)); |
460 | 636 |
461 | 637 |
462 TEST_F(InstructionSelectorTest, OvfFlagAddImmediateOnLeft) { | 638 TEST_F(InstructionSelectorTest, OvfFlagAddImmediateOnLeft) { |
463 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { | 639 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
464 StreamBuilder m(this, kMachInt32, kMachInt32); | 640 StreamBuilder m(this, kMachInt32, kMachInt32); |
465 m.Return(m.Projection( | 641 m.Return(m.Projection( |
466 1, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0)))); | 642 1, m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0)))); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
505 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode()); | 681 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode()); |
506 ASSERT_EQ(2U, s[0]->InputCount()); | 682 ASSERT_EQ(2U, s[0]->InputCount()); |
507 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | 683 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
508 EXPECT_EQ(2U, s[0]->OutputCount()); | 684 EXPECT_EQ(2U, s[0]->OutputCount()); |
509 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | 685 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
510 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | 686 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
511 } | 687 } |
512 } | 688 } |
513 | 689 |
514 | 690 |
| 691 TEST_F(InstructionSelectorTest, OvfBranchWithImmediateOnLeft) { |
| 692 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
| 693 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 694 MLabel a, b; |
| 695 Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0)); |
| 696 m.Branch(m.Projection(1, n), &a, &b); |
| 697 m.Bind(&a); |
| 698 m.Return(m.Int32Constant(0)); |
| 699 m.Bind(&b); |
| 700 m.Return(m.Projection(0, n)); |
| 701 Stream s = m.Build(); |
| 702 |
| 703 ASSERT_EQ(1U, s.size()); |
| 704 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode()); |
| 705 ASSERT_EQ(4U, s[0]->InputCount()); |
| 706 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 707 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 708 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 709 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 710 } |
| 711 } |
| 712 |
| 713 |
515 // ----------------------------------------------------------------------------- | 714 // ----------------------------------------------------------------------------- |
516 // Shift instructions. | 715 // Shift instructions. |
517 | 716 |
518 | 717 |
519 typedef InstructionSelectorTestWithParam<MachInst2> | 718 typedef InstructionSelectorTestWithParam<MachInst2> |
520 InstructionSelectorShiftTest; | 719 InstructionSelectorShiftTest; |
521 | 720 |
522 | 721 |
523 TEST_P(InstructionSelectorShiftTest, Parameter) { | 722 TEST_P(InstructionSelectorShiftTest, Parameter) { |
524 const MachInst2 dpi = GetParam(); | 723 const MachInst2 dpi = GetParam(); |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
712 } | 911 } |
713 | 912 |
714 | 913 |
715 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | 914 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
716 InstructionSelectorMemoryAccessTest, | 915 InstructionSelectorMemoryAccessTest, |
717 ::testing::ValuesIn(kMemoryAccesses)); | 916 ::testing::ValuesIn(kMemoryAccesses)); |
718 | 917 |
719 } // namespace compiler | 918 } // namespace compiler |
720 } // namespace internal | 919 } // namespace internal |
721 } // namespace v8 | 920 } // namespace v8 |
OLD | NEW |