| 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 |