| 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 |