| 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/compiler/instruction-selector.h" | 5 #include "src/compiler/instruction-selector.h" |
| 6 | 6 |
| 7 #include "src/compiler/instruction-selector-impl.h" | 7 #include "src/compiler/instruction-selector-impl.h" |
| 8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
| 9 #include "src/compiler/node-properties-inl.h" | 9 #include "src/compiler/node-properties-inl.h" |
| 10 #include "src/compiler/pipeline.h" | 10 #include "src/compiler/pipeline.h" |
| (...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 case IrOpcode::kWord64Shr: | 525 case IrOpcode::kWord64Shr: |
| 526 return VisitWord64Shr(node); | 526 return VisitWord64Shr(node); |
| 527 case IrOpcode::kWord64Sar: | 527 case IrOpcode::kWord64Sar: |
| 528 return VisitWord64Sar(node); | 528 return VisitWord64Sar(node); |
| 529 case IrOpcode::kWord64Equal: | 529 case IrOpcode::kWord64Equal: |
| 530 return VisitWord64Equal(node); | 530 return VisitWord64Equal(node); |
| 531 case IrOpcode::kInt32Add: | 531 case IrOpcode::kInt32Add: |
| 532 return VisitInt32Add(node); | 532 return VisitInt32Add(node); |
| 533 case IrOpcode::kInt32AddWithOverflow: | 533 case IrOpcode::kInt32AddWithOverflow: |
| 534 return VisitInt32AddWithOverflow(node); | 534 return VisitInt32AddWithOverflow(node); |
| 535 case IrOpcode::kUint32AddWithOverflow: |
| 536 return VisitUint32AddWithOverflow(node); |
| 535 case IrOpcode::kInt32Sub: | 537 case IrOpcode::kInt32Sub: |
| 536 return VisitInt32Sub(node); | 538 return VisitInt32Sub(node); |
| 537 case IrOpcode::kInt32SubWithOverflow: | 539 case IrOpcode::kInt32SubWithOverflow: |
| 538 return VisitInt32SubWithOverflow(node); | 540 return VisitInt32SubWithOverflow(node); |
| 541 case IrOpcode::kUint32SubWithOverflow: |
| 542 return VisitUint32SubWithOverflow(node); |
| 539 case IrOpcode::kInt32Mul: | 543 case IrOpcode::kInt32Mul: |
| 540 return VisitInt32Mul(node); | 544 return VisitInt32Mul(node); |
| 541 case IrOpcode::kInt32Div: | 545 case IrOpcode::kInt32Div: |
| 542 return VisitInt32Div(node); | 546 return VisitInt32Div(node); |
| 543 case IrOpcode::kInt32UDiv: | 547 case IrOpcode::kInt32UDiv: |
| 544 return VisitInt32UDiv(node); | 548 return VisitInt32UDiv(node); |
| 545 case IrOpcode::kInt32Mod: | 549 case IrOpcode::kInt32Mod: |
| 546 return VisitInt32Mod(node); | 550 return VisitInt32Mod(node); |
| 547 case IrOpcode::kInt32UMod: | 551 case IrOpcode::kInt32UMod: |
| 548 return VisitInt32UMod(node); | 552 return VisitInt32UMod(node); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 void InstructionSelector::VisitWord64Equal(Node* node) { | 650 void InstructionSelector::VisitWord64Equal(Node* node) { |
| 647 FlagsContinuation cont(kEqual, node); | 651 FlagsContinuation cont(kEqual, node); |
| 648 Int64BinopMatcher m(node); | 652 Int64BinopMatcher m(node); |
| 649 if (m.right().Is(0)) { | 653 if (m.right().Is(0)) { |
| 650 return VisitWord64Test(m.left().node(), &cont); | 654 return VisitWord64Test(m.left().node(), &cont); |
| 651 } | 655 } |
| 652 VisitWord64Compare(node, &cont); | 656 VisitWord64Compare(node, &cont); |
| 653 } | 657 } |
| 654 | 658 |
| 655 | 659 |
| 656 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { | |
| 657 if (Node* ovf = node->FindProjection(1)) { | |
| 658 FlagsContinuation cont(kOverflow, ovf); | |
| 659 return VisitInt32AddWithOverflow(node, &cont); | |
| 660 } | |
| 661 FlagsContinuation cont; | |
| 662 VisitInt32AddWithOverflow(node, &cont); | |
| 663 } | |
| 664 | |
| 665 | |
| 666 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { | |
| 667 if (Node* ovf = node->FindProjection(1)) { | |
| 668 FlagsContinuation cont(kOverflow, ovf); | |
| 669 return VisitInt32SubWithOverflow(node, &cont); | |
| 670 } | |
| 671 FlagsContinuation cont; | |
| 672 VisitInt32SubWithOverflow(node, &cont); | |
| 673 } | |
| 674 | |
| 675 | |
| 676 void InstructionSelector::VisitInt64LessThan(Node* node) { | 660 void InstructionSelector::VisitInt64LessThan(Node* node) { |
| 677 FlagsContinuation cont(kSignedLessThan, node); | 661 FlagsContinuation cont(kSignedLessThan, node); |
| 678 VisitWord64Compare(node, &cont); | 662 VisitWord64Compare(node, &cont); |
| 679 } | 663 } |
| 680 | 664 |
| 681 | 665 |
| 682 void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) { | 666 void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) { |
| 683 FlagsContinuation cont(kSignedLessThanOrEqual, node); | 667 FlagsContinuation cont(kSignedLessThanOrEqual, node); |
| 684 VisitWord64Compare(node, &cont); | 668 VisitWord64Compare(node, &cont); |
| 685 } | 669 } |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 788 MarkAsUsed(*i); | 772 MarkAsUsed(*i); |
| 789 } | 773 } |
| 790 } | 774 } |
| 791 | 775 |
| 792 | 776 |
| 793 void InstructionSelector::VisitProjection(Node* node) { | 777 void InstructionSelector::VisitProjection(Node* node) { |
| 794 OperandGenerator g(this); | 778 OperandGenerator g(this); |
| 795 Node* value = node->InputAt(0); | 779 Node* value = node->InputAt(0); |
| 796 switch (value->opcode()) { | 780 switch (value->opcode()) { |
| 797 case IrOpcode::kInt32AddWithOverflow: | 781 case IrOpcode::kInt32AddWithOverflow: |
| 782 case IrOpcode::kUint32AddWithOverflow: |
| 798 case IrOpcode::kInt32SubWithOverflow: | 783 case IrOpcode::kInt32SubWithOverflow: |
| 784 case IrOpcode::kUint32SubWithOverflow: |
| 799 if (OpParameter<int32_t>(node) == 0) { | 785 if (OpParameter<int32_t>(node) == 0) { |
| 800 Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value)); | 786 Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value)); |
| 801 } else { | 787 } else { |
| 802 DCHECK_EQ(1, OpParameter<int32_t>(node)); | 788 DCHECK_EQ(1, OpParameter<int32_t>(node)); |
| 803 MarkAsUsed(value); | 789 MarkAsUsed(value); |
| 804 } | 790 } |
| 805 break; | 791 break; |
| 806 default: | 792 default: |
| 807 break; | 793 break; |
| 808 } | 794 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 822 // fall through to the next block. | 808 // fall through to the next block. |
| 823 Emit(kArchNop, NULL)->MarkAsControl(); | 809 Emit(kArchNop, NULL)->MarkAsControl(); |
| 824 } else { | 810 } else { |
| 825 // jump to the next block. | 811 // jump to the next block. |
| 826 OperandGenerator g(this); | 812 OperandGenerator g(this); |
| 827 Emit(kArchJmp, NULL, g.Label(target))->MarkAsControl(); | 813 Emit(kArchJmp, NULL, g.Label(target))->MarkAsControl(); |
| 828 } | 814 } |
| 829 } | 815 } |
| 830 | 816 |
| 831 | 817 |
| 832 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | |
| 833 BasicBlock* fbranch) { | |
| 834 OperandGenerator g(this); | |
| 835 Node* user = branch; | |
| 836 Node* value = branch->InputAt(0); | |
| 837 | |
| 838 FlagsContinuation cont(kNotEqual, tbranch, fbranch); | |
| 839 | |
| 840 // If we can fall through to the true block, invert the branch. | |
| 841 if (IsNextInAssemblyOrder(tbranch)) { | |
| 842 cont.Negate(); | |
| 843 cont.SwapBlocks(); | |
| 844 } | |
| 845 | |
| 846 // Try to combine with comparisons against 0 by simply inverting the branch. | |
| 847 while (CanCover(user, value)) { | |
| 848 if (value->opcode() == IrOpcode::kWord32Equal) { | |
| 849 Int32BinopMatcher m(value); | |
| 850 if (m.right().Is(0)) { | |
| 851 user = value; | |
| 852 value = m.left().node(); | |
| 853 cont.Negate(); | |
| 854 } else { | |
| 855 break; | |
| 856 } | |
| 857 } else if (value->opcode() == IrOpcode::kWord64Equal) { | |
| 858 Int64BinopMatcher m(value); | |
| 859 if (m.right().Is(0)) { | |
| 860 user = value; | |
| 861 value = m.left().node(); | |
| 862 cont.Negate(); | |
| 863 } else { | |
| 864 break; | |
| 865 } | |
| 866 } else { | |
| 867 break; | |
| 868 } | |
| 869 } | |
| 870 | |
| 871 // Try to combine the branch with a comparison. | |
| 872 if (CanCover(user, value)) { | |
| 873 switch (value->opcode()) { | |
| 874 case IrOpcode::kWord32Equal: | |
| 875 cont.OverwriteAndNegateIfEqual(kEqual); | |
| 876 return VisitWord32Compare(value, &cont); | |
| 877 case IrOpcode::kInt32LessThan: | |
| 878 cont.OverwriteAndNegateIfEqual(kSignedLessThan); | |
| 879 return VisitWord32Compare(value, &cont); | |
| 880 case IrOpcode::kInt32LessThanOrEqual: | |
| 881 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); | |
| 882 return VisitWord32Compare(value, &cont); | |
| 883 case IrOpcode::kUint32LessThan: | |
| 884 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); | |
| 885 return VisitWord32Compare(value, &cont); | |
| 886 case IrOpcode::kUint32LessThanOrEqual: | |
| 887 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); | |
| 888 return VisitWord32Compare(value, &cont); | |
| 889 case IrOpcode::kWord64Equal: | |
| 890 cont.OverwriteAndNegateIfEqual(kEqual); | |
| 891 return VisitWord64Compare(value, &cont); | |
| 892 case IrOpcode::kInt64LessThan: | |
| 893 cont.OverwriteAndNegateIfEqual(kSignedLessThan); | |
| 894 return VisitWord64Compare(value, &cont); | |
| 895 case IrOpcode::kInt64LessThanOrEqual: | |
| 896 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); | |
| 897 return VisitWord64Compare(value, &cont); | |
| 898 case IrOpcode::kFloat64Equal: | |
| 899 cont.OverwriteAndNegateIfEqual(kUnorderedEqual); | |
| 900 return VisitFloat64Compare(value, &cont); | |
| 901 case IrOpcode::kFloat64LessThan: | |
| 902 cont.OverwriteAndNegateIfEqual(kUnorderedLessThan); | |
| 903 return VisitFloat64Compare(value, &cont); | |
| 904 case IrOpcode::kFloat64LessThanOrEqual: | |
| 905 cont.OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual); | |
| 906 return VisitFloat64Compare(value, &cont); | |
| 907 case IrOpcode::kProjection: | |
| 908 // Check if this is the overflow output projection of an | |
| 909 // <Operation>WithOverflow node. | |
| 910 if (OpParameter<int32_t>(value) == 1) { | |
| 911 // We cannot combine the <Operation>WithOverflow with this branch | |
| 912 // unless the 0th projection (the use of the actual value of the | |
| 913 // <Operation> is either NULL, which means there's no use of the | |
| 914 // actual value, or was already defined, which means it is scheduled | |
| 915 // *AFTER* this branch). | |
| 916 Node* node = value->InputAt(0); | |
| 917 Node* result = node->FindProjection(0); | |
| 918 if (result == NULL || IsDefined(result)) { | |
| 919 switch (node->opcode()) { | |
| 920 case IrOpcode::kInt32AddWithOverflow: | |
| 921 cont.OverwriteAndNegateIfEqual(kOverflow); | |
| 922 return VisitInt32AddWithOverflow(node, &cont); | |
| 923 case IrOpcode::kInt32SubWithOverflow: | |
| 924 cont.OverwriteAndNegateIfEqual(kOverflow); | |
| 925 return VisitInt32SubWithOverflow(node, &cont); | |
| 926 default: | |
| 927 break; | |
| 928 } | |
| 929 } | |
| 930 } | |
| 931 break; | |
| 932 default: | |
| 933 break; | |
| 934 } | |
| 935 } | |
| 936 | |
| 937 // Branch could not be combined with a compare, emit compare against 0. | |
| 938 VisitWord32Test(value, &cont); | |
| 939 } | |
| 940 | |
| 941 | |
| 942 void InstructionSelector::VisitReturn(Node* value) { | 818 void InstructionSelector::VisitReturn(Node* value) { |
| 943 OperandGenerator g(this); | 819 OperandGenerator g(this); |
| 944 if (value != NULL) { | 820 if (value != NULL) { |
| 945 Emit(kArchRet, NULL, g.UseLocation(value, linkage()->GetReturnLocation())); | 821 Emit(kArchRet, NULL, g.UseLocation(value, linkage()->GetReturnLocation())); |
| 946 } else { | 822 } else { |
| 947 Emit(kArchRet, NULL); | 823 Emit(kArchRet, NULL); |
| 948 } | 824 } |
| 949 } | 825 } |
| 950 | 826 |
| 951 | 827 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1045 | 921 |
| 1046 | 922 |
| 1047 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, | 923 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, |
| 1048 BasicBlock* deoptimization) {} | 924 BasicBlock* deoptimization) {} |
| 1049 | 925 |
| 1050 #endif // !V8_TURBOFAN_BACKEND | 926 #endif // !V8_TURBOFAN_BACKEND |
| 1051 | 927 |
| 1052 } // namespace compiler | 928 } // namespace compiler |
| 1053 } // namespace internal | 929 } // namespace internal |
| 1054 } // namespace v8 | 930 } // namespace v8 |
| OLD | NEW |