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 803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
814 } else if (g.CanBeImmediate(left)) { | 814 } else if (g.CanBeImmediate(left)) { |
815 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); | 815 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); |
816 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont); | 816 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont); |
817 } else { | 817 } else { |
818 VisitCompare(selector, opcode, left, right, cont, | 818 VisitCompare(selector, opcode, left, right, cont, |
819 node->op()->HasProperty(Operator::kCommutative)); | 819 node->op()->HasProperty(Operator::kCommutative)); |
820 } | 820 } |
821 } | 821 } |
822 | 822 |
823 | 823 |
| 824 // Shared routine for comparison with zero. |
| 825 static void VisitCompareZero(InstructionSelector* selector, Node* node, |
| 826 InstructionCode opcode, FlagsContinuation* cont) { |
| 827 X64OperandGenerator g(selector); |
| 828 VisitCompare(selector, opcode, g.Use(node), g.TempImmediate(0), cont); |
| 829 } |
| 830 |
| 831 |
824 // Shared routine for multiple float64 compare operations. | 832 // Shared routine for multiple float64 compare operations. |
825 static void VisitFloat64Compare(InstructionSelector* selector, Node* node, | 833 static void VisitFloat64Compare(InstructionSelector* selector, Node* node, |
826 FlagsContinuation* cont) { | 834 FlagsContinuation* cont) { |
827 VisitCompare(selector, kSSEFloat64Cmp, node->InputAt(0), node->InputAt(1), | 835 VisitCompare(selector, kSSEFloat64Cmp, node->InputAt(0), node->InputAt(1), |
828 cont, node->op()->HasProperty(Operator::kCommutative)); | 836 cont, node->op()->HasProperty(Operator::kCommutative)); |
829 } | 837 } |
830 | 838 |
831 | 839 |
832 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 840 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
833 BasicBlock* fbranch) { | 841 BasicBlock* fbranch) { |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
939 case IrOpcode::kWord32And: | 947 case IrOpcode::kWord32And: |
940 return VisitWordCompare(this, value, kX64Test32, &cont); | 948 return VisitWordCompare(this, value, kX64Test32, &cont); |
941 case IrOpcode::kWord64And: | 949 case IrOpcode::kWord64And: |
942 return VisitWordCompare(this, value, kX64Test, &cont); | 950 return VisitWordCompare(this, value, kX64Test, &cont); |
943 default: | 951 default: |
944 break; | 952 break; |
945 } | 953 } |
946 } | 954 } |
947 | 955 |
948 // Branch could not be combined with a compare, emit compare against 0. | 956 // Branch could not be combined with a compare, emit compare against 0. |
949 VisitCompare(this, kX64Cmp32, g.Use(value), g.TempImmediate(0), &cont); | 957 VisitCompareZero(this, value, kX64Cmp32, &cont); |
950 } | 958 } |
951 | 959 |
952 | 960 |
953 void InstructionSelector::VisitWord32Equal(Node* const node) { | 961 void InstructionSelector::VisitWord32Equal(Node* const node) { |
954 Node* const user = node; | 962 Node* user = node; |
955 FlagsContinuation cont(kEqual, node); | 963 FlagsContinuation cont(kEqual, node); |
956 Int32BinopMatcher m(user); | 964 Int32BinopMatcher m(user); |
957 if (m.right().Is(0)) { | 965 if (m.right().Is(0)) { |
958 Node* const value = m.left().node(); | 966 Node* value = m.left().node(); |
| 967 |
| 968 // Try to combine with comparisons against 0 by simply inverting the branch. |
| 969 while (CanCover(user, value) && value->opcode() == IrOpcode::kWord32Equal) { |
| 970 Int32BinopMatcher m(value); |
| 971 if (m.right().Is(0)) { |
| 972 user = value; |
| 973 value = m.left().node(); |
| 974 cont.Negate(); |
| 975 } else { |
| 976 break; |
| 977 } |
| 978 } |
| 979 |
| 980 // Try to combine the branch with a comparison. |
959 if (CanCover(user, value)) { | 981 if (CanCover(user, value)) { |
960 switch (value->opcode()) { | 982 switch (value->opcode()) { |
961 case IrOpcode::kInt32Sub: | 983 case IrOpcode::kInt32Sub: |
962 return VisitWordCompare(this, value, kX64Cmp32, &cont); | 984 return VisitWordCompare(this, value, kX64Cmp32, &cont); |
963 case IrOpcode::kWord32And: | 985 case IrOpcode::kWord32And: |
964 return VisitWordCompare(this, value, kX64Test32, &cont); | 986 return VisitWordCompare(this, value, kX64Test32, &cont); |
965 default: | 987 default: |
966 break; | 988 break; |
967 } | 989 } |
968 } | 990 } |
| 991 return VisitCompareZero(this, value, kX64Cmp32, &cont); |
969 } | 992 } |
970 VisitWordCompare(this, node, kX64Cmp32, &cont); | 993 VisitWordCompare(this, node, kX64Cmp32, &cont); |
971 } | 994 } |
972 | 995 |
973 | 996 |
974 void InstructionSelector::VisitInt32LessThan(Node* node) { | 997 void InstructionSelector::VisitInt32LessThan(Node* node) { |
975 FlagsContinuation cont(kSignedLessThan, node); | 998 FlagsContinuation cont(kSignedLessThan, node); |
976 VisitWordCompare(this, node, kX64Cmp32, &cont); | 999 VisitWordCompare(this, node, kX64Cmp32, &cont); |
977 } | 1000 } |
978 | 1001 |
(...skipping 10 matching lines...) Expand all Loading... |
989 } | 1012 } |
990 | 1013 |
991 | 1014 |
992 void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) { | 1015 void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) { |
993 FlagsContinuation cont(kUnsignedLessThanOrEqual, node); | 1016 FlagsContinuation cont(kUnsignedLessThanOrEqual, node); |
994 VisitWordCompare(this, node, kX64Cmp32, &cont); | 1017 VisitWordCompare(this, node, kX64Cmp32, &cont); |
995 } | 1018 } |
996 | 1019 |
997 | 1020 |
998 void InstructionSelector::VisitWord64Equal(Node* const node) { | 1021 void InstructionSelector::VisitWord64Equal(Node* const node) { |
999 Node* const user = node; | 1022 Node* user = node; |
1000 FlagsContinuation cont(kEqual, node); | 1023 FlagsContinuation cont(kEqual, node); |
1001 Int64BinopMatcher m(user); | 1024 Int64BinopMatcher m(user); |
1002 if (m.right().Is(0)) { | 1025 if (m.right().Is(0)) { |
1003 Node* const value = m.left().node(); | 1026 Node* value = m.left().node(); |
| 1027 |
| 1028 // Try to combine with comparisons against 0 by simply inverting the branch. |
| 1029 while (CanCover(user, value) && value->opcode() == IrOpcode::kWord64Equal) { |
| 1030 Int64BinopMatcher m(value); |
| 1031 if (m.right().Is(0)) { |
| 1032 user = value; |
| 1033 value = m.left().node(); |
| 1034 cont.Negate(); |
| 1035 } else { |
| 1036 break; |
| 1037 } |
| 1038 } |
| 1039 |
| 1040 // Try to combine the branch with a comparison. |
1004 if (CanCover(user, value)) { | 1041 if (CanCover(user, value)) { |
1005 switch (value->opcode()) { | 1042 switch (value->opcode()) { |
1006 case IrOpcode::kInt64Sub: | 1043 case IrOpcode::kInt64Sub: |
1007 return VisitWordCompare(this, value, kX64Cmp, &cont); | 1044 return VisitWordCompare(this, value, kX64Cmp, &cont); |
1008 case IrOpcode::kWord64And: | 1045 case IrOpcode::kWord64And: |
1009 return VisitWordCompare(this, value, kX64Test, &cont); | 1046 return VisitWordCompare(this, value, kX64Test, &cont); |
1010 default: | 1047 default: |
1011 break; | 1048 break; |
1012 } | 1049 } |
1013 } | 1050 } |
| 1051 return VisitCompareZero(this, value, kX64Cmp, &cont); |
1014 } | 1052 } |
1015 VisitWordCompare(this, node, kX64Cmp, &cont); | 1053 VisitWordCompare(this, node, kX64Cmp, &cont); |
1016 } | 1054 } |
1017 | 1055 |
1018 | 1056 |
1019 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { | 1057 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { |
1020 if (Node* ovf = node->FindProjection(1)) { | 1058 if (Node* ovf = node->FindProjection(1)) { |
1021 FlagsContinuation cont(kOverflow, ovf); | 1059 FlagsContinuation cont(kOverflow, ovf); |
1022 VisitBinop(this, node, kX64Add32, &cont); | 1060 VisitBinop(this, node, kX64Add32, &cont); |
1023 } | 1061 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1067 | 1105 |
1068 | 1106 |
1069 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { | 1107 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { |
1070 FlagsContinuation cont(kUnorderedLessThanOrEqual, node); | 1108 FlagsContinuation cont(kUnorderedLessThanOrEqual, node); |
1071 VisitFloat64Compare(this, node, &cont); | 1109 VisitFloat64Compare(this, node, &cont); |
1072 } | 1110 } |
1073 | 1111 |
1074 } // namespace compiler | 1112 } // namespace compiler |
1075 } // namespace internal | 1113 } // namespace internal |
1076 } // namespace v8 | 1114 } // namespace v8 |
OLD | NEW |