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 |