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 |