| 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/generic-node-inl.h" | 5 #include "src/compiler/generic-node-inl.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 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 782 if (cont->IsBranch()) { | 782 if (cont->IsBranch()) { |
| 783 selector->Emit(opcode, NULL, left, right, g.Label(cont->true_block()), | 783 selector->Emit(opcode, NULL, left, right, g.Label(cont->true_block()), |
| 784 g.Label(cont->false_block()))->MarkAsControl(); | 784 g.Label(cont->false_block()))->MarkAsControl(); |
| 785 } else { | 785 } else { |
| 786 DCHECK(cont->IsSet()); | 786 DCHECK(cont->IsSet()); |
| 787 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | 787 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); |
| 788 } | 788 } |
| 789 } | 789 } |
| 790 | 790 |
| 791 | 791 |
| 792 // Shared routine for multiple compare operations. |
| 793 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
| 794 Node* left, Node* right, FlagsContinuation* cont, |
| 795 bool commutative) { |
| 796 X64OperandGenerator g(selector); |
| 797 if (commutative && g.CanBeBetterLeftOperand(right)) { |
| 798 std::swap(left, right); |
| 799 } |
| 800 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont); |
| 801 } |
| 802 |
| 803 |
| 792 // Shared routine for multiple word compare operations. | 804 // Shared routine for multiple word compare operations. |
| 793 static void VisitWordCompare(InstructionSelector* selector, Node* node, | 805 static void VisitWordCompare(InstructionSelector* selector, Node* node, |
| 794 InstructionCode opcode, FlagsContinuation* cont, | 806 InstructionCode opcode, FlagsContinuation* cont) { |
| 795 bool commutative) { | |
| 796 X64OperandGenerator g(selector); | 807 X64OperandGenerator g(selector); |
| 797 Node* left = node->InputAt(0); | 808 Node* const left = node->InputAt(0); |
| 798 Node* right = node->InputAt(1); | 809 Node* const right = node->InputAt(1); |
| 799 | 810 |
| 800 // Match immediates on left or right side of comparison. | 811 // Match immediates on left or right side of comparison. |
| 801 if (g.CanBeImmediate(right)) { | 812 if (g.CanBeImmediate(right)) { |
| 802 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont); | 813 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont); |
| 803 } else if (g.CanBeImmediate(left)) { | 814 } else if (g.CanBeImmediate(left)) { |
| 804 if (!commutative) cont->Commute(); | 815 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); |
| 805 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont); | 816 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont); |
| 806 } else { | 817 } else { |
| 807 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont); | 818 VisitCompare(selector, opcode, left, right, cont, |
| 819 node->op()->HasProperty(Operator::kCommutative)); |
| 808 } | 820 } |
| 809 } | 821 } |
| 810 | 822 |
| 811 | 823 |
| 824 // Shared routine for multiple float64 compare operations. |
| 812 static void VisitFloat64Compare(InstructionSelector* selector, Node* node, | 825 static void VisitFloat64Compare(InstructionSelector* selector, Node* node, |
| 813 FlagsContinuation* cont) { | 826 FlagsContinuation* cont) { |
| 814 X64OperandGenerator g(selector); | 827 VisitCompare(selector, kSSEFloat64Cmp, node->InputAt(0), node->InputAt(1), |
| 815 Node* left = node->InputAt(0); | 828 cont, node->op()->HasProperty(Operator::kCommutative)); |
| 816 Node* right = node->InputAt(1); | |
| 817 VisitCompare(selector, kSSEFloat64Cmp, g.UseRegister(left), g.Use(right), | |
| 818 cont); | |
| 819 } | 829 } |
| 820 | 830 |
| 821 | 831 |
| 822 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 832 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
| 823 BasicBlock* fbranch) { | 833 BasicBlock* fbranch) { |
| 824 X64OperandGenerator g(this); | 834 X64OperandGenerator g(this); |
| 825 Node* user = branch; | 835 Node* user = branch; |
| 826 Node* value = branch->InputAt(0); | 836 Node* value = branch->InputAt(0); |
| 827 | 837 |
| 828 FlagsContinuation cont(kNotEqual, tbranch, fbranch); | 838 FlagsContinuation cont(kNotEqual, tbranch, fbranch); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 856 } else { | 866 } else { |
| 857 break; | 867 break; |
| 858 } | 868 } |
| 859 } | 869 } |
| 860 | 870 |
| 861 // Try to combine the branch with a comparison. | 871 // Try to combine the branch with a comparison. |
| 862 if (CanCover(user, value)) { | 872 if (CanCover(user, value)) { |
| 863 switch (value->opcode()) { | 873 switch (value->opcode()) { |
| 864 case IrOpcode::kWord32Equal: | 874 case IrOpcode::kWord32Equal: |
| 865 cont.OverwriteAndNegateIfEqual(kEqual); | 875 cont.OverwriteAndNegateIfEqual(kEqual); |
| 866 return VisitWordCompare(this, value, kX64Cmp32, &cont, false); | 876 return VisitWordCompare(this, value, kX64Cmp32, &cont); |
| 867 case IrOpcode::kInt32LessThan: | 877 case IrOpcode::kInt32LessThan: |
| 868 cont.OverwriteAndNegateIfEqual(kSignedLessThan); | 878 cont.OverwriteAndNegateIfEqual(kSignedLessThan); |
| 869 return VisitWordCompare(this, value, kX64Cmp32, &cont, false); | 879 return VisitWordCompare(this, value, kX64Cmp32, &cont); |
| 870 case IrOpcode::kInt32LessThanOrEqual: | 880 case IrOpcode::kInt32LessThanOrEqual: |
| 871 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); | 881 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); |
| 872 return VisitWordCompare(this, value, kX64Cmp32, &cont, false); | 882 return VisitWordCompare(this, value, kX64Cmp32, &cont); |
| 873 case IrOpcode::kUint32LessThan: | 883 case IrOpcode::kUint32LessThan: |
| 874 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); | 884 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); |
| 875 return VisitWordCompare(this, value, kX64Cmp32, &cont, false); | 885 return VisitWordCompare(this, value, kX64Cmp32, &cont); |
| 876 case IrOpcode::kUint32LessThanOrEqual: | 886 case IrOpcode::kUint32LessThanOrEqual: |
| 877 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); | 887 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); |
| 878 return VisitWordCompare(this, value, kX64Cmp32, &cont, false); | 888 return VisitWordCompare(this, value, kX64Cmp32, &cont); |
| 879 case IrOpcode::kWord64Equal: | 889 case IrOpcode::kWord64Equal: |
| 880 cont.OverwriteAndNegateIfEqual(kEqual); | 890 cont.OverwriteAndNegateIfEqual(kEqual); |
| 881 return VisitWordCompare(this, value, kX64Cmp, &cont, false); | 891 return VisitWordCompare(this, value, kX64Cmp, &cont); |
| 882 case IrOpcode::kInt64LessThan: | 892 case IrOpcode::kInt64LessThan: |
| 883 cont.OverwriteAndNegateIfEqual(kSignedLessThan); | 893 cont.OverwriteAndNegateIfEqual(kSignedLessThan); |
| 884 return VisitWordCompare(this, value, kX64Cmp, &cont, false); | 894 return VisitWordCompare(this, value, kX64Cmp, &cont); |
| 885 case IrOpcode::kInt64LessThanOrEqual: | 895 case IrOpcode::kInt64LessThanOrEqual: |
| 886 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); | 896 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); |
| 887 return VisitWordCompare(this, value, kX64Cmp, &cont, false); | 897 return VisitWordCompare(this, value, kX64Cmp, &cont); |
| 888 case IrOpcode::kUint64LessThan: | 898 case IrOpcode::kUint64LessThan: |
| 889 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); | 899 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); |
| 890 return VisitWordCompare(this, value, kX64Cmp, &cont, false); | 900 return VisitWordCompare(this, value, kX64Cmp, &cont); |
| 891 case IrOpcode::kFloat64Equal: | 901 case IrOpcode::kFloat64Equal: |
| 892 cont.OverwriteAndNegateIfEqual(kUnorderedEqual); | 902 cont.OverwriteAndNegateIfEqual(kUnorderedEqual); |
| 893 return VisitFloat64Compare(this, value, &cont); | 903 return VisitFloat64Compare(this, value, &cont); |
| 894 case IrOpcode::kFloat64LessThan: | 904 case IrOpcode::kFloat64LessThan: |
| 895 cont.OverwriteAndNegateIfEqual(kUnorderedLessThan); | 905 cont.OverwriteAndNegateIfEqual(kUnorderedLessThan); |
| 896 return VisitFloat64Compare(this, value, &cont); | 906 return VisitFloat64Compare(this, value, &cont); |
| 897 case IrOpcode::kFloat64LessThanOrEqual: | 907 case IrOpcode::kFloat64LessThanOrEqual: |
| 898 cont.OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual); | 908 cont.OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual); |
| 899 return VisitFloat64Compare(this, value, &cont); | 909 return VisitFloat64Compare(this, value, &cont); |
| 900 case IrOpcode::kProjection: | 910 case IrOpcode::kProjection: |
| (...skipping 15 matching lines...) Expand all Loading... |
| 916 case IrOpcode::kInt32SubWithOverflow: | 926 case IrOpcode::kInt32SubWithOverflow: |
| 917 cont.OverwriteAndNegateIfEqual(kOverflow); | 927 cont.OverwriteAndNegateIfEqual(kOverflow); |
| 918 return VisitBinop(this, node, kX64Sub32, &cont); | 928 return VisitBinop(this, node, kX64Sub32, &cont); |
| 919 default: | 929 default: |
| 920 break; | 930 break; |
| 921 } | 931 } |
| 922 } | 932 } |
| 923 } | 933 } |
| 924 break; | 934 break; |
| 925 case IrOpcode::kInt32Sub: | 935 case IrOpcode::kInt32Sub: |
| 926 return VisitWordCompare(this, value, kX64Cmp32, &cont, false); | 936 return VisitWordCompare(this, value, kX64Cmp32, &cont); |
| 927 case IrOpcode::kInt64Sub: | 937 case IrOpcode::kInt64Sub: |
| 928 return VisitWordCompare(this, value, kX64Cmp, &cont, false); | 938 return VisitWordCompare(this, value, kX64Cmp, &cont); |
| 929 case IrOpcode::kWord32And: | 939 case IrOpcode::kWord32And: |
| 930 return VisitWordCompare(this, value, kX64Test32, &cont, true); | 940 return VisitWordCompare(this, value, kX64Test32, &cont); |
| 931 case IrOpcode::kWord64And: | 941 case IrOpcode::kWord64And: |
| 932 return VisitWordCompare(this, value, kX64Test, &cont, true); | 942 return VisitWordCompare(this, value, kX64Test, &cont); |
| 933 default: | 943 default: |
| 934 break; | 944 break; |
| 935 } | 945 } |
| 936 } | 946 } |
| 937 | 947 |
| 938 // Branch could not be combined with a compare, emit compare against 0. | 948 // Branch could not be combined with a compare, emit compare against 0. |
| 939 VisitCompare(this, kX64Cmp32, g.Use(value), g.TempImmediate(0), &cont); | 949 VisitCompare(this, kX64Cmp32, g.Use(value), g.TempImmediate(0), &cont); |
| 940 } | 950 } |
| 941 | 951 |
| 942 | 952 |
| 943 void InstructionSelector::VisitWord32Equal(Node* const node) { | 953 void InstructionSelector::VisitWord32Equal(Node* const node) { |
| 944 Node* const user = node; | 954 Node* const user = node; |
| 945 FlagsContinuation cont(kEqual, node); | 955 FlagsContinuation cont(kEqual, node); |
| 946 Int32BinopMatcher m(user); | 956 Int32BinopMatcher m(user); |
| 947 if (m.right().Is(0)) { | 957 if (m.right().Is(0)) { |
| 948 Node* const value = m.left().node(); | 958 Node* const value = m.left().node(); |
| 949 if (CanCover(user, value)) { | 959 if (CanCover(user, value)) { |
| 950 switch (value->opcode()) { | 960 switch (value->opcode()) { |
| 951 case IrOpcode::kInt32Sub: | 961 case IrOpcode::kInt32Sub: |
| 952 return VisitWordCompare(this, value, kX64Cmp32, &cont, false); | 962 return VisitWordCompare(this, value, kX64Cmp32, &cont); |
| 953 case IrOpcode::kWord32And: | 963 case IrOpcode::kWord32And: |
| 954 return VisitWordCompare(this, value, kX64Test32, &cont, true); | 964 return VisitWordCompare(this, value, kX64Test32, &cont); |
| 955 default: | 965 default: |
| 956 break; | 966 break; |
| 957 } | 967 } |
| 958 } | 968 } |
| 959 } | 969 } |
| 960 VisitWordCompare(this, node, kX64Cmp32, &cont, false); | 970 VisitWordCompare(this, node, kX64Cmp32, &cont); |
| 961 } | 971 } |
| 962 | 972 |
| 963 | 973 |
| 964 void InstructionSelector::VisitInt32LessThan(Node* node) { | 974 void InstructionSelector::VisitInt32LessThan(Node* node) { |
| 965 FlagsContinuation cont(kSignedLessThan, node); | 975 FlagsContinuation cont(kSignedLessThan, node); |
| 966 VisitWordCompare(this, node, kX64Cmp32, &cont, false); | 976 VisitWordCompare(this, node, kX64Cmp32, &cont); |
| 967 } | 977 } |
| 968 | 978 |
| 969 | 979 |
| 970 void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) { | 980 void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) { |
| 971 FlagsContinuation cont(kSignedLessThanOrEqual, node); | 981 FlagsContinuation cont(kSignedLessThanOrEqual, node); |
| 972 VisitWordCompare(this, node, kX64Cmp32, &cont, false); | 982 VisitWordCompare(this, node, kX64Cmp32, &cont); |
| 973 } | 983 } |
| 974 | 984 |
| 975 | 985 |
| 976 void InstructionSelector::VisitUint32LessThan(Node* node) { | 986 void InstructionSelector::VisitUint32LessThan(Node* node) { |
| 977 FlagsContinuation cont(kUnsignedLessThan, node); | 987 FlagsContinuation cont(kUnsignedLessThan, node); |
| 978 VisitWordCompare(this, node, kX64Cmp32, &cont, false); | 988 VisitWordCompare(this, node, kX64Cmp32, &cont); |
| 979 } | 989 } |
| 980 | 990 |
| 981 | 991 |
| 982 void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) { | 992 void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) { |
| 983 FlagsContinuation cont(kUnsignedLessThanOrEqual, node); | 993 FlagsContinuation cont(kUnsignedLessThanOrEqual, node); |
| 984 VisitWordCompare(this, node, kX64Cmp32, &cont, false); | 994 VisitWordCompare(this, node, kX64Cmp32, &cont); |
| 985 } | 995 } |
| 986 | 996 |
| 987 | 997 |
| 988 void InstructionSelector::VisitWord64Equal(Node* const node) { | 998 void InstructionSelector::VisitWord64Equal(Node* const node) { |
| 989 Node* const user = node; | 999 Node* const user = node; |
| 990 FlagsContinuation cont(kEqual, node); | 1000 FlagsContinuation cont(kEqual, node); |
| 991 Int64BinopMatcher m(user); | 1001 Int64BinopMatcher m(user); |
| 992 if (m.right().Is(0)) { | 1002 if (m.right().Is(0)) { |
| 993 Node* const value = m.left().node(); | 1003 Node* const value = m.left().node(); |
| 994 if (CanCover(user, value)) { | 1004 if (CanCover(user, value)) { |
| 995 switch (value->opcode()) { | 1005 switch (value->opcode()) { |
| 996 case IrOpcode::kInt64Sub: | 1006 case IrOpcode::kInt64Sub: |
| 997 return VisitWordCompare(this, value, kX64Cmp, &cont, false); | 1007 return VisitWordCompare(this, value, kX64Cmp, &cont); |
| 998 case IrOpcode::kWord64And: | 1008 case IrOpcode::kWord64And: |
| 999 return VisitWordCompare(this, value, kX64Test, &cont, true); | 1009 return VisitWordCompare(this, value, kX64Test, &cont); |
| 1000 default: | 1010 default: |
| 1001 break; | 1011 break; |
| 1002 } | 1012 } |
| 1003 } | 1013 } |
| 1004 } | 1014 } |
| 1005 VisitWordCompare(this, node, kX64Cmp, &cont, false); | 1015 VisitWordCompare(this, node, kX64Cmp, &cont); |
| 1006 } | 1016 } |
| 1007 | 1017 |
| 1008 | 1018 |
| 1009 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { | 1019 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { |
| 1010 if (Node* ovf = node->FindProjection(1)) { | 1020 if (Node* ovf = node->FindProjection(1)) { |
| 1011 FlagsContinuation cont(kOverflow, ovf); | 1021 FlagsContinuation cont(kOverflow, ovf); |
| 1012 VisitBinop(this, node, kX64Add32, &cont); | 1022 VisitBinop(this, node, kX64Add32, &cont); |
| 1013 } | 1023 } |
| 1014 FlagsContinuation cont; | 1024 FlagsContinuation cont; |
| 1015 VisitBinop(this, node, kX64Add32, &cont); | 1025 VisitBinop(this, node, kX64Add32, &cont); |
| 1016 } | 1026 } |
| 1017 | 1027 |
| 1018 | 1028 |
| 1019 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { | 1029 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { |
| 1020 if (Node* ovf = node->FindProjection(1)) { | 1030 if (Node* ovf = node->FindProjection(1)) { |
| 1021 FlagsContinuation cont(kOverflow, ovf); | 1031 FlagsContinuation cont(kOverflow, ovf); |
| 1022 return VisitBinop(this, node, kX64Sub32, &cont); | 1032 return VisitBinop(this, node, kX64Sub32, &cont); |
| 1023 } | 1033 } |
| 1024 FlagsContinuation cont; | 1034 FlagsContinuation cont; |
| 1025 VisitBinop(this, node, kX64Sub32, &cont); | 1035 VisitBinop(this, node, kX64Sub32, &cont); |
| 1026 } | 1036 } |
| 1027 | 1037 |
| 1028 | 1038 |
| 1029 void InstructionSelector::VisitInt64LessThan(Node* node) { | 1039 void InstructionSelector::VisitInt64LessThan(Node* node) { |
| 1030 FlagsContinuation cont(kSignedLessThan, node); | 1040 FlagsContinuation cont(kSignedLessThan, node); |
| 1031 VisitWordCompare(this, node, kX64Cmp, &cont, false); | 1041 VisitWordCompare(this, node, kX64Cmp, &cont); |
| 1032 } | 1042 } |
| 1033 | 1043 |
| 1034 | 1044 |
| 1035 void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) { | 1045 void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) { |
| 1036 FlagsContinuation cont(kSignedLessThanOrEqual, node); | 1046 FlagsContinuation cont(kSignedLessThanOrEqual, node); |
| 1037 VisitWordCompare(this, node, kX64Cmp, &cont, false); | 1047 VisitWordCompare(this, node, kX64Cmp, &cont); |
| 1038 } | 1048 } |
| 1039 | 1049 |
| 1040 | 1050 |
| 1041 void InstructionSelector::VisitUint64LessThan(Node* node) { | 1051 void InstructionSelector::VisitUint64LessThan(Node* node) { |
| 1042 FlagsContinuation cont(kUnsignedLessThan, node); | 1052 FlagsContinuation cont(kUnsignedLessThan, node); |
| 1043 VisitWordCompare(this, node, kX64Cmp, &cont, false); | 1053 VisitWordCompare(this, node, kX64Cmp, &cont); |
| 1044 } | 1054 } |
| 1045 | 1055 |
| 1046 | 1056 |
| 1047 void InstructionSelector::VisitFloat64Equal(Node* node) { | 1057 void InstructionSelector::VisitFloat64Equal(Node* node) { |
| 1048 FlagsContinuation cont(kUnorderedEqual, node); | 1058 FlagsContinuation cont(kUnorderedEqual, node); |
| 1049 VisitFloat64Compare(this, node, &cont); | 1059 VisitFloat64Compare(this, node, &cont); |
| 1050 } | 1060 } |
| 1051 | 1061 |
| 1052 | 1062 |
| 1053 void InstructionSelector::VisitFloat64LessThan(Node* node) { | 1063 void InstructionSelector::VisitFloat64LessThan(Node* node) { |
| 1054 FlagsContinuation cont(kUnorderedLessThan, node); | 1064 FlagsContinuation cont(kUnorderedLessThan, node); |
| 1055 VisitFloat64Compare(this, node, &cont); | 1065 VisitFloat64Compare(this, node, &cont); |
| 1056 } | 1066 } |
| 1057 | 1067 |
| 1058 | 1068 |
| 1059 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { | 1069 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { |
| 1060 FlagsContinuation cont(kUnorderedLessThanOrEqual, node); | 1070 FlagsContinuation cont(kUnorderedLessThanOrEqual, node); |
| 1061 VisitFloat64Compare(this, node, &cont); | 1071 VisitFloat64Compare(this, node, &cont); |
| 1062 } | 1072 } |
| 1063 | 1073 |
| 1064 } // namespace compiler | 1074 } // namespace compiler |
| 1065 } // namespace internal | 1075 } // namespace internal |
| 1066 } // namespace v8 | 1076 } // namespace v8 |
| OLD | NEW |