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 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 X64OperandGenerator g(selector); | 233 X64OperandGenerator g(selector); |
234 Int32BinopMatcher m(node); | 234 Int32BinopMatcher m(node); |
235 Node* left = m.left().node(); | 235 Node* left = m.left().node(); |
236 Node* right = m.right().node(); | 236 Node* right = m.right().node(); |
237 InstructionOperand* inputs[4]; | 237 InstructionOperand* inputs[4]; |
238 size_t input_count = 0; | 238 size_t input_count = 0; |
239 InstructionOperand* outputs[2]; | 239 InstructionOperand* outputs[2]; |
240 size_t output_count = 0; | 240 size_t output_count = 0; |
241 | 241 |
242 // TODO(turbofan): match complex addressing modes. | 242 // TODO(turbofan): match complex addressing modes. |
243 if (g.CanBeImmediate(right)) { | 243 if (left == right) { |
| 244 // If both inputs refer to the same operand, enforce allocating a register |
| 245 // for both of them to ensure that we don't end up generating code like |
| 246 // this: |
| 247 // |
| 248 // mov rax, [rbp-0x10] |
| 249 // add rax, [rbp-0x10] |
| 250 // jo label |
| 251 InstructionOperand* const input = g.UseRegister(left); |
| 252 inputs[input_count++] = input; |
| 253 inputs[input_count++] = input; |
| 254 } else if (g.CanBeImmediate(right)) { |
244 inputs[input_count++] = g.UseRegister(left); | 255 inputs[input_count++] = g.UseRegister(left); |
245 inputs[input_count++] = g.UseImmediate(right); | 256 inputs[input_count++] = g.UseImmediate(right); |
246 } else { | 257 } else { |
247 if (node->op()->HasProperty(Operator::kCommutative) && | 258 if (node->op()->HasProperty(Operator::kCommutative) && |
248 g.CanBeBetterLeftOperand(right)) { | 259 g.CanBeBetterLeftOperand(right)) { |
249 std::swap(left, right); | 260 std::swap(left, right); |
250 } | 261 } |
251 inputs[input_count++] = g.UseRegister(left); | 262 inputs[input_count++] = g.UseRegister(left); |
252 inputs[input_count++] = g.Use(right); | 263 inputs[input_count++] = g.Use(right); |
253 } | 264 } |
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont); | 800 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont); |
790 } else if (g.CanBeImmediate(left)) { | 801 } else if (g.CanBeImmediate(left)) { |
791 if (!commutative) cont->Commute(); | 802 if (!commutative) cont->Commute(); |
792 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont); | 803 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont); |
793 } else { | 804 } else { |
794 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont); | 805 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont); |
795 } | 806 } |
796 } | 807 } |
797 | 808 |
798 | 809 |
799 static void VisitWordTest(InstructionSelector* selector, Node* node, | |
800 InstructionCode opcode, FlagsContinuation* cont) { | |
801 X64OperandGenerator g(selector); | |
802 VisitCompare(selector, opcode, g.Use(node), g.TempImmediate(-1), cont); | |
803 } | |
804 | |
805 | |
806 static void VisitFloat64Compare(InstructionSelector* selector, Node* node, | 810 static void VisitFloat64Compare(InstructionSelector* selector, Node* node, |
807 FlagsContinuation* cont) { | 811 FlagsContinuation* cont) { |
808 X64OperandGenerator g(selector); | 812 X64OperandGenerator g(selector); |
809 Node* left = node->InputAt(0); | 813 Node* left = node->InputAt(0); |
810 Node* right = node->InputAt(1); | 814 Node* right = node->InputAt(1); |
811 VisitCompare(selector, kSSEFloat64Cmp, g.UseRegister(left), g.Use(right), | 815 VisitCompare(selector, kSSEFloat64Cmp, g.UseRegister(left), g.Use(right), |
812 cont); | 816 cont); |
813 } | 817 } |
814 | 818 |
815 | 819 |
816 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 820 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
817 BasicBlock* fbranch) { | 821 BasicBlock* fbranch) { |
818 OperandGenerator g(this); | 822 X64OperandGenerator g(this); |
819 Node* user = branch; | 823 Node* user = branch; |
820 Node* value = branch->InputAt(0); | 824 Node* value = branch->InputAt(0); |
821 | 825 |
822 FlagsContinuation cont(kNotEqual, tbranch, fbranch); | 826 FlagsContinuation cont(kNotEqual, tbranch, fbranch); |
823 | 827 |
824 // If we can fall through to the true block, invert the branch. | 828 // If we can fall through to the true block, invert the branch. |
825 if (IsNextInAssemblyOrder(tbranch)) { | 829 if (IsNextInAssemblyOrder(tbranch)) { |
826 cont.Negate(); | 830 cont.Negate(); |
827 cont.SwapBlocks(); | 831 cont.SwapBlocks(); |
828 } | 832 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
911 cont.OverwriteAndNegateIfEqual(kOverflow); | 915 cont.OverwriteAndNegateIfEqual(kOverflow); |
912 return VisitBinop(this, node, kX64Sub32, &cont); | 916 return VisitBinop(this, node, kX64Sub32, &cont); |
913 default: | 917 default: |
914 break; | 918 break; |
915 } | 919 } |
916 } | 920 } |
917 } | 921 } |
918 break; | 922 break; |
919 case IrOpcode::kInt32Sub: | 923 case IrOpcode::kInt32Sub: |
920 return VisitWordCompare(this, value, kX64Cmp32, &cont, false); | 924 return VisitWordCompare(this, value, kX64Cmp32, &cont, false); |
| 925 case IrOpcode::kInt64Sub: |
| 926 return VisitWordCompare(this, value, kX64Cmp, &cont, false); |
921 case IrOpcode::kWord32And: | 927 case IrOpcode::kWord32And: |
922 return VisitWordCompare(this, value, kX64Test32, &cont, true); | 928 return VisitWordCompare(this, value, kX64Test32, &cont, true); |
| 929 case IrOpcode::kWord64And: |
| 930 return VisitWordCompare(this, value, kX64Test, &cont, true); |
923 default: | 931 default: |
924 break; | 932 break; |
925 } | 933 } |
926 } | 934 } |
927 | 935 |
928 // Branch could not be combined with a compare, emit compare against 0. | 936 // Branch could not be combined with a compare, emit compare against 0. |
929 VisitWordTest(this, value, kX64Test32, &cont); | 937 VisitCompare(this, kX64Cmp32, g.Use(value), g.TempImmediate(0), &cont); |
930 } | 938 } |
931 | 939 |
932 | 940 |
933 void InstructionSelector::VisitWord32Equal(Node* const node) { | 941 void InstructionSelector::VisitWord32Equal(Node* const node) { |
934 Node* const user = node; | 942 Node* const user = node; |
935 FlagsContinuation cont(kEqual, node); | 943 FlagsContinuation cont(kEqual, node); |
936 Int32BinopMatcher m(user); | 944 Int32BinopMatcher m(user); |
937 if (m.right().Is(0)) { | 945 if (m.right().Is(0)) { |
938 Node* const value = m.left().node(); | 946 Node* const value = m.left().node(); |
939 if (CanCover(user, value)) { | 947 if (CanCover(user, value)) { |
940 switch (value->opcode()) { | 948 switch (value->opcode()) { |
941 case IrOpcode::kInt32Sub: | 949 case IrOpcode::kInt32Sub: |
942 return VisitWordCompare(this, value, kX64Cmp32, &cont, false); | 950 return VisitWordCompare(this, value, kX64Cmp32, &cont, false); |
943 case IrOpcode::kWord32And: | 951 case IrOpcode::kWord32And: |
944 return VisitWordCompare(this, value, kX64Test32, &cont, true); | 952 return VisitWordCompare(this, value, kX64Test32, &cont, true); |
945 default: | 953 default: |
946 break; | 954 break; |
947 } | 955 } |
948 return VisitWordTest(this, value, kX64Test32, &cont); | |
949 } | 956 } |
950 } | 957 } |
951 VisitWordCompare(this, node, kX64Cmp32, &cont, false); | 958 VisitWordCompare(this, node, kX64Cmp32, &cont, false); |
952 } | 959 } |
953 | 960 |
954 | 961 |
955 void InstructionSelector::VisitInt32LessThan(Node* node) { | 962 void InstructionSelector::VisitInt32LessThan(Node* node) { |
956 FlagsContinuation cont(kSignedLessThan, node); | 963 FlagsContinuation cont(kSignedLessThan, node); |
957 VisitWordCompare(this, node, kX64Cmp32, &cont, false); | 964 VisitWordCompare(this, node, kX64Cmp32, &cont, false); |
958 } | 965 } |
(...skipping 25 matching lines...) Expand all Loading... |
984 Node* const value = m.left().node(); | 991 Node* const value = m.left().node(); |
985 if (CanCover(user, value)) { | 992 if (CanCover(user, value)) { |
986 switch (value->opcode()) { | 993 switch (value->opcode()) { |
987 case IrOpcode::kInt64Sub: | 994 case IrOpcode::kInt64Sub: |
988 return VisitWordCompare(this, value, kX64Cmp, &cont, false); | 995 return VisitWordCompare(this, value, kX64Cmp, &cont, false); |
989 case IrOpcode::kWord64And: | 996 case IrOpcode::kWord64And: |
990 return VisitWordCompare(this, value, kX64Test, &cont, true); | 997 return VisitWordCompare(this, value, kX64Test, &cont, true); |
991 default: | 998 default: |
992 break; | 999 break; |
993 } | 1000 } |
994 return VisitWordTest(this, value, kX64Test, &cont); | |
995 } | 1001 } |
996 } | 1002 } |
997 VisitWordCompare(this, node, kX64Cmp, &cont, false); | 1003 VisitWordCompare(this, node, kX64Cmp, &cont, false); |
998 } | 1004 } |
999 | 1005 |
1000 | 1006 |
1001 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { | 1007 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { |
1002 if (Node* ovf = node->FindProjection(1)) { | 1008 if (Node* ovf = node->FindProjection(1)) { |
1003 FlagsContinuation cont(kOverflow, ovf); | 1009 FlagsContinuation cont(kOverflow, ovf); |
1004 VisitBinop(this, node, kX64Add32, &cont); | 1010 VisitBinop(this, node, kX64Add32, &cont); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1049 | 1055 |
1050 | 1056 |
1051 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { | 1057 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { |
1052 FlagsContinuation cont(kUnorderedLessThanOrEqual, node); | 1058 FlagsContinuation cont(kUnorderedLessThanOrEqual, node); |
1053 VisitFloat64Compare(this, node, &cont); | 1059 VisitFloat64Compare(this, node, &cont); |
1054 } | 1060 } |
1055 | 1061 |
1056 } // namespace compiler | 1062 } // namespace compiler |
1057 } // namespace internal | 1063 } // namespace internal |
1058 } // namespace v8 | 1064 } // namespace v8 |
OLD | NEW |