| 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 "src/base/bits.h" | 5 #include "src/base/bits.h" |
| 6 #include "src/compiler/instruction-selector-impl.h" | 6 #include "src/compiler/instruction-selector-impl.h" |
| 7 #include "src/compiler/node-matchers.h" | 7 #include "src/compiler/node-matchers.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 case kArmMul: | 84 case kArmMul: |
| 85 case kArmMla: | 85 case kArmMla: |
| 86 case kArmMls: | 86 case kArmMls: |
| 87 case kArmSmmul: | 87 case kArmSmmul: |
| 88 case kArmSmmla: | 88 case kArmSmmla: |
| 89 case kArmUmull: | 89 case kArmUmull: |
| 90 case kArmSdiv: | 90 case kArmSdiv: |
| 91 case kArmUdiv: | 91 case kArmUdiv: |
| 92 case kArmBfc: | 92 case kArmBfc: |
| 93 case kArmUbfx: | 93 case kArmUbfx: |
| 94 case kArmSxtb: |
| 95 case kArmSxth: |
| 96 case kArmSxtab: |
| 97 case kArmSxtah: |
| 98 case kArmUxtb: |
| 99 case kArmUxth: |
| 100 case kArmUxtab: |
| 101 case kArmUxtah: |
| 94 case kArmVcmpF64: | 102 case kArmVcmpF64: |
| 95 case kArmVaddF64: | 103 case kArmVaddF64: |
| 96 case kArmVsubF64: | 104 case kArmVsubF64: |
| 97 case kArmVmulF64: | 105 case kArmVmulF64: |
| 98 case kArmVmlaF64: | 106 case kArmVmlaF64: |
| 99 case kArmVmlsF64: | 107 case kArmVmlsF64: |
| 100 case kArmVdivF64: | 108 case kArmVdivF64: |
| 101 case kArmVmodF64: | 109 case kArmVmodF64: |
| 102 case kArmVnegF64: | 110 case kArmVnegF64: |
| 103 case kArmVsqrtF64: | 111 case kArmVsqrtF64: |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 static void VisitBinop(InstructionSelector* selector, Node* node, | 256 static void VisitBinop(InstructionSelector* selector, Node* node, |
| 249 InstructionCode opcode, InstructionCode reverse_opcode, | 257 InstructionCode opcode, InstructionCode reverse_opcode, |
| 250 FlagsContinuation* cont) { | 258 FlagsContinuation* cont) { |
| 251 ArmOperandGenerator g(selector); | 259 ArmOperandGenerator g(selector); |
| 252 Int32BinopMatcher m(node); | 260 Int32BinopMatcher m(node); |
| 253 InstructionOperand* inputs[5]; | 261 InstructionOperand* inputs[5]; |
| 254 size_t input_count = 0; | 262 size_t input_count = 0; |
| 255 InstructionOperand* outputs[2]; | 263 InstructionOperand* outputs[2]; |
| 256 size_t output_count = 0; | 264 size_t output_count = 0; |
| 257 | 265 |
| 258 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(), | 266 if (m.left().node() == m.right().node()) { |
| 259 &input_count, &inputs[1])) { | 267 // If both inputs refer to the same operand, enforce allocating a register |
| 268 // for both of them to ensure that we don't end up generating code like |
| 269 // this: |
| 270 // |
| 271 // mov r0, r1, asr #16 |
| 272 // adds r0, r0, r1, asr #16 |
| 273 // bvs label |
| 274 InstructionOperand* const input = g.UseRegister(m.left().node()); |
| 275 opcode |= AddressingModeField::encode(kMode_Operand2_R); |
| 276 inputs[input_count++] = input; |
| 277 inputs[input_count++] = input; |
| 278 } else if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(), |
| 279 &input_count, &inputs[1])) { |
| 260 inputs[0] = g.UseRegister(m.left().node()); | 280 inputs[0] = g.UseRegister(m.left().node()); |
| 261 input_count++; | 281 input_count++; |
| 262 } else if (TryMatchImmediateOrShift(selector, &reverse_opcode, | 282 } else if (TryMatchImmediateOrShift(selector, &reverse_opcode, |
| 263 m.left().node(), &input_count, | 283 m.left().node(), &input_count, |
| 264 &inputs[1])) { | 284 &inputs[1])) { |
| 265 inputs[0] = g.UseRegister(m.right().node()); | 285 inputs[0] = g.UseRegister(m.right().node()); |
| 266 opcode = reverse_opcode; | 286 opcode = reverse_opcode; |
| 267 input_count++; | 287 input_count++; |
| 268 } else { | 288 } else { |
| 269 opcode |= AddressingModeField::encode(kMode_Operand2_R); | 289 opcode |= AddressingModeField::encode(kMode_Operand2_R); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 return; | 443 return; |
| 424 } | 444 } |
| 425 } | 445 } |
| 426 if (m.right().IsWord32Xor() && CanCover(node, m.right().node())) { | 446 if (m.right().IsWord32Xor() && CanCover(node, m.right().node())) { |
| 427 Int32BinopMatcher mright(m.right().node()); | 447 Int32BinopMatcher mright(m.right().node()); |
| 428 if (mright.right().Is(-1)) { | 448 if (mright.right().Is(-1)) { |
| 429 EmitBic(this, node, m.left().node(), mright.left().node()); | 449 EmitBic(this, node, m.left().node(), mright.left().node()); |
| 430 return; | 450 return; |
| 431 } | 451 } |
| 432 } | 452 } |
| 433 if (IsSupported(ARMv7) && m.right().HasValue()) { | 453 if (m.right().HasValue()) { |
| 434 // Try to interpret this AND as UBFX. | |
| 435 uint32_t const value = m.right().Value(); | 454 uint32_t const value = m.right().Value(); |
| 436 uint32_t width = base::bits::CountPopulation32(value); | 455 uint32_t width = base::bits::CountPopulation32(value); |
| 437 uint32_t msb = base::bits::CountLeadingZeros32(value); | 456 uint32_t msb = base::bits::CountLeadingZeros32(value); |
| 438 if (width != 0 && msb + width == 32) { | 457 // Try to interpret this AND as UBFX. |
| 458 if (IsSupported(ARMv7) && width != 0 && msb + width == 32) { |
| 439 DCHECK_EQ(0, base::bits::CountTrailingZeros32(value)); | 459 DCHECK_EQ(0, base::bits::CountTrailingZeros32(value)); |
| 440 if (m.left().IsWord32Shr()) { | 460 if (m.left().IsWord32Shr()) { |
| 441 Int32BinopMatcher mleft(m.left().node()); | 461 Int32BinopMatcher mleft(m.left().node()); |
| 442 if (mleft.right().IsInRange(0, 31)) { | 462 if (mleft.right().IsInRange(0, 31)) { |
| 443 Emit(kArmUbfx, g.DefineAsRegister(node), | 463 Emit(kArmUbfx, g.DefineAsRegister(node), |
| 444 g.UseRegister(mleft.left().node()), | 464 g.UseRegister(mleft.left().node()), |
| 445 g.UseImmediate(mleft.right().node()), g.TempImmediate(width)); | 465 g.UseImmediate(mleft.right().node()), g.TempImmediate(width)); |
| 446 return; | 466 return; |
| 447 } | 467 } |
| 448 } | 468 } |
| 449 Emit(kArmUbfx, g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 469 Emit(kArmUbfx, g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
| 450 g.TempImmediate(0), g.TempImmediate(width)); | 470 g.TempImmediate(0), g.TempImmediate(width)); |
| 451 return; | 471 return; |
| 452 } | 472 } |
| 453 | |
| 454 // Try to interpret this AND as BIC. | 473 // Try to interpret this AND as BIC. |
| 455 if (g.CanBeImmediate(~value)) { | 474 if (g.CanBeImmediate(~value)) { |
| 456 Emit(kArmBic | AddressingModeField::encode(kMode_Operand2_I), | 475 Emit(kArmBic | AddressingModeField::encode(kMode_Operand2_I), |
| 457 g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 476 g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
| 458 g.TempImmediate(~value)); | 477 g.TempImmediate(~value)); |
| 459 return; | 478 return; |
| 460 } | 479 } |
| 461 | 480 // Try to interpret this AND as UXTH. |
| 481 if (value == 0xffff) { |
| 482 Emit(kArmUxth, g.DefineAsRegister(m.node()), |
| 483 g.UseRegister(m.left().node()), g.TempImmediate(0)); |
| 484 return; |
| 485 } |
| 462 // Try to interpret this AND as BFC. | 486 // Try to interpret this AND as BFC. |
| 463 width = 32 - width; | 487 if (IsSupported(ARMv7)) { |
| 464 msb = base::bits::CountLeadingZeros32(~value); | 488 width = 32 - width; |
| 465 uint32_t lsb = base::bits::CountTrailingZeros32(~value); | 489 msb = base::bits::CountLeadingZeros32(~value); |
| 466 if (msb + width + lsb == 32) { | 490 uint32_t lsb = base::bits::CountTrailingZeros32(~value); |
| 467 Emit(kArmBfc, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()), | 491 if (msb + width + lsb == 32) { |
| 468 g.TempImmediate(lsb), g.TempImmediate(width)); | 492 Emit(kArmBfc, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()), |
| 469 return; | 493 g.TempImmediate(lsb), g.TempImmediate(width)); |
| 494 return; |
| 495 } |
| 470 } | 496 } |
| 471 } | 497 } |
| 472 VisitBinop(this, node, kArmAnd, kArmAnd); | 498 VisitBinop(this, node, kArmAnd, kArmAnd); |
| 473 } | 499 } |
| 474 | 500 |
| 475 | 501 |
| 476 void InstructionSelector::VisitWord32Or(Node* node) { | 502 void InstructionSelector::VisitWord32Or(Node* node) { |
| 477 VisitBinop(this, node, kArmOrr, kArmOrr); | 503 VisitBinop(this, node, kArmOrr, kArmOrr); |
| 478 } | 504 } |
| 479 | 505 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 g.TempImmediate(width)); | 590 g.TempImmediate(width)); |
| 565 return; | 591 return; |
| 566 } | 592 } |
| 567 } | 593 } |
| 568 } | 594 } |
| 569 VisitShift(this, node, TryMatchLSR); | 595 VisitShift(this, node, TryMatchLSR); |
| 570 } | 596 } |
| 571 | 597 |
| 572 | 598 |
| 573 void InstructionSelector::VisitWord32Sar(Node* node) { | 599 void InstructionSelector::VisitWord32Sar(Node* node) { |
| 600 ArmOperandGenerator g(this); |
| 601 Int32BinopMatcher m(node); |
| 602 if (CanCover(m.node(), m.left().node()) && m.left().IsWord32Shl()) { |
| 603 Int32BinopMatcher mleft(m.left().node()); |
| 604 if (mleft.right().Is(16) && m.right().Is(16)) { |
| 605 Emit(kArmSxth, g.DefineAsRegister(node), |
| 606 g.UseRegister(mleft.left().node()), g.TempImmediate(0)); |
| 607 return; |
| 608 } else if (mleft.right().Is(24) && m.right().Is(24)) { |
| 609 Emit(kArmSxtb, g.DefineAsRegister(node), |
| 610 g.UseRegister(mleft.left().node()), g.TempImmediate(0)); |
| 611 return; |
| 612 } |
| 613 } |
| 574 VisitShift(this, node, TryMatchASR); | 614 VisitShift(this, node, TryMatchASR); |
| 575 } | 615 } |
| 576 | 616 |
| 577 | 617 |
| 578 void InstructionSelector::VisitWord32Ror(Node* node) { | 618 void InstructionSelector::VisitWord32Ror(Node* node) { |
| 579 VisitShift(this, node, TryMatchROR); | 619 VisitShift(this, node, TryMatchROR); |
| 580 } | 620 } |
| 581 | 621 |
| 582 | 622 |
| 583 void InstructionSelector::VisitInt32Add(Node* node) { | 623 void InstructionSelector::VisitInt32Add(Node* node) { |
| 584 ArmOperandGenerator g(this); | 624 ArmOperandGenerator g(this); |
| 585 Int32BinopMatcher m(node); | 625 Int32BinopMatcher m(node); |
| 586 if (m.left().IsInt32Mul() && CanCover(node, m.left().node())) { | 626 if (CanCover(node, m.left().node())) { |
| 587 Int32BinopMatcher mleft(m.left().node()); | 627 switch (m.left().opcode()) { |
| 588 Emit(kArmMla, g.DefineAsRegister(node), g.UseRegister(mleft.left().node()), | 628 case IrOpcode::kInt32Mul: { |
| 589 g.UseRegister(mleft.right().node()), g.UseRegister(m.right().node())); | 629 Int32BinopMatcher mleft(m.left().node()); |
| 590 return; | 630 Emit(kArmMla, g.DefineAsRegister(node), |
| 631 g.UseRegister(mleft.left().node()), |
| 632 g.UseRegister(mleft.right().node()), |
| 633 g.UseRegister(m.right().node())); |
| 634 return; |
| 635 } |
| 636 case IrOpcode::kInt32MulHigh: { |
| 637 Int32BinopMatcher mleft(m.left().node()); |
| 638 Emit(kArmSmmla, g.DefineAsRegister(node), |
| 639 g.UseRegister(mleft.left().node()), |
| 640 g.UseRegister(mleft.right().node()), |
| 641 g.UseRegister(m.right().node())); |
| 642 return; |
| 643 } |
| 644 case IrOpcode::kWord32And: { |
| 645 Int32BinopMatcher mleft(m.left().node()); |
| 646 if (mleft.right().Is(0xff)) { |
| 647 Emit(kArmUxtab, g.DefineAsRegister(node), |
| 648 g.UseRegister(m.right().node()), |
| 649 g.UseRegister(mleft.left().node()), g.TempImmediate(0)); |
| 650 return; |
| 651 } else if (mleft.right().Is(0xffff)) { |
| 652 Emit(kArmUxtah, g.DefineAsRegister(node), |
| 653 g.UseRegister(m.right().node()), |
| 654 g.UseRegister(mleft.left().node()), g.TempImmediate(0)); |
| 655 return; |
| 656 } |
| 657 } |
| 658 case IrOpcode::kWord32Sar: { |
| 659 Int32BinopMatcher mleft(m.left().node()); |
| 660 if (CanCover(mleft.node(), mleft.left().node()) && |
| 661 mleft.left().IsWord32Shl()) { |
| 662 Int32BinopMatcher mleftleft(mleft.left().node()); |
| 663 if (mleft.right().Is(24) && mleftleft.right().Is(24)) { |
| 664 Emit(kArmSxtab, g.DefineAsRegister(node), |
| 665 g.UseRegister(m.right().node()), |
| 666 g.UseRegister(mleftleft.left().node()), g.TempImmediate(0)); |
| 667 return; |
| 668 } else if (mleft.right().Is(16) && mleftleft.right().Is(16)) { |
| 669 Emit(kArmSxtah, g.DefineAsRegister(node), |
| 670 g.UseRegister(m.right().node()), |
| 671 g.UseRegister(mleftleft.left().node()), g.TempImmediate(0)); |
| 672 return; |
| 673 } |
| 674 } |
| 675 } |
| 676 default: |
| 677 break; |
| 678 } |
| 591 } | 679 } |
| 592 if (m.right().IsInt32Mul() && CanCover(node, m.right().node())) { | 680 if (CanCover(node, m.right().node())) { |
| 593 Int32BinopMatcher mright(m.right().node()); | 681 switch (m.right().opcode()) { |
| 594 Emit(kArmMla, g.DefineAsRegister(node), g.UseRegister(mright.left().node()), | 682 case IrOpcode::kInt32Mul: { |
| 595 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); | 683 Int32BinopMatcher mright(m.right().node()); |
| 596 return; | 684 Emit(kArmMla, g.DefineAsRegister(node), |
| 597 } | 685 g.UseRegister(mright.left().node()), |
| 598 if (m.left().IsInt32MulHigh() && CanCover(node, m.left().node())) { | 686 g.UseRegister(mright.right().node()), |
| 599 Int32BinopMatcher mleft(m.left().node()); | 687 g.UseRegister(m.left().node())); |
| 600 Emit(kArmSmmla, g.DefineAsRegister(node), | 688 return; |
| 601 g.UseRegister(mleft.left().node()), | 689 } |
| 602 g.UseRegister(mleft.right().node()), g.UseRegister(m.right().node())); | 690 case IrOpcode::kInt32MulHigh: { |
| 603 return; | 691 Int32BinopMatcher mright(m.right().node()); |
| 604 } | 692 Emit(kArmSmmla, g.DefineAsRegister(node), |
| 605 if (m.right().IsInt32MulHigh() && CanCover(node, m.right().node())) { | 693 g.UseRegister(mright.left().node()), |
| 606 Int32BinopMatcher mright(m.right().node()); | 694 g.UseRegister(mright.right().node()), |
| 607 Emit(kArmSmmla, g.DefineAsRegister(node), | 695 g.UseRegister(m.left().node())); |
| 608 g.UseRegister(mright.left().node()), | 696 return; |
| 609 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); | 697 } |
| 610 return; | 698 case IrOpcode::kWord32And: { |
| 699 Int32BinopMatcher mright(m.right().node()); |
| 700 if (mright.right().Is(0xff)) { |
| 701 Emit(kArmUxtab, g.DefineAsRegister(node), |
| 702 g.UseRegister(m.left().node()), |
| 703 g.UseRegister(mright.left().node()), g.TempImmediate(0)); |
| 704 return; |
| 705 } else if (mright.right().Is(0xffff)) { |
| 706 Emit(kArmUxtah, g.DefineAsRegister(node), |
| 707 g.UseRegister(m.left().node()), |
| 708 g.UseRegister(mright.left().node()), g.TempImmediate(0)); |
| 709 return; |
| 710 } |
| 711 } |
| 712 case IrOpcode::kWord32Sar: { |
| 713 Int32BinopMatcher mright(m.right().node()); |
| 714 if (CanCover(mright.node(), mright.left().node()) && |
| 715 mright.left().IsWord32Shl()) { |
| 716 Int32BinopMatcher mrightleft(mright.left().node()); |
| 717 if (mright.right().Is(24) && mrightleft.right().Is(24)) { |
| 718 Emit(kArmSxtab, g.DefineAsRegister(node), |
| 719 g.UseRegister(m.left().node()), |
| 720 g.UseRegister(mrightleft.left().node()), g.TempImmediate(0)); |
| 721 return; |
| 722 } else if (mright.right().Is(16) && mrightleft.right().Is(16)) { |
| 723 Emit(kArmSxtah, g.DefineAsRegister(node), |
| 724 g.UseRegister(m.left().node()), |
| 725 g.UseRegister(mrightleft.left().node()), g.TempImmediate(0)); |
| 726 return; |
| 727 } |
| 728 } |
| 729 } |
| 730 default: |
| 731 break; |
| 732 } |
| 611 } | 733 } |
| 612 VisitBinop(this, node, kArmAdd, kArmAdd); | 734 VisitBinop(this, node, kArmAdd, kArmAdd); |
| 613 } | 735 } |
| 614 | 736 |
| 615 | 737 |
| 616 void InstructionSelector::VisitInt32Sub(Node* node) { | 738 void InstructionSelector::VisitInt32Sub(Node* node) { |
| 617 ArmOperandGenerator g(this); | 739 ArmOperandGenerator g(this); |
| 618 Int32BinopMatcher m(node); | 740 Int32BinopMatcher m(node); |
| 619 if (IsSupported(MLS) && m.right().IsInt32Mul() && | 741 if (IsSupported(MLS) && m.right().IsInt32Mul() && |
| 620 CanCover(node, m.right().node())) { | 742 CanCover(node, m.right().node())) { |
| (...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1196 MachineOperatorBuilder::kFloat64Ceil | | 1318 MachineOperatorBuilder::kFloat64Ceil | |
| 1197 MachineOperatorBuilder::kFloat64RoundTruncate | | 1319 MachineOperatorBuilder::kFloat64RoundTruncate | |
| 1198 MachineOperatorBuilder::kFloat64RoundTiesAway; | 1320 MachineOperatorBuilder::kFloat64RoundTiesAway; |
| 1199 } | 1321 } |
| 1200 return flags; | 1322 return flags; |
| 1201 } | 1323 } |
| 1202 | 1324 |
| 1203 } // namespace compiler | 1325 } // namespace compiler |
| 1204 } // namespace internal | 1326 } // namespace internal |
| 1205 } // namespace v8 | 1327 } // namespace v8 |
| OLD | NEW |