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/instruction-selector-impl.h" | 5 #include "src/compiler/instruction-selector-impl.h" |
6 #include "src/compiler/node-matchers.h" | 6 #include "src/compiler/node-matchers.h" |
7 #include "src/compiler/node-properties-inl.h" | 7 #include "src/compiler/node-properties-inl.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 IA32OperandGenerator g(selector); | 252 IA32OperandGenerator g(selector); |
253 Int32BinopMatcher m(node); | 253 Int32BinopMatcher m(node); |
254 Node* left = m.left().node(); | 254 Node* left = m.left().node(); |
255 Node* right = m.right().node(); | 255 Node* right = m.right().node(); |
256 InstructionOperand* inputs[4]; | 256 InstructionOperand* inputs[4]; |
257 size_t input_count = 0; | 257 size_t input_count = 0; |
258 InstructionOperand* outputs[2]; | 258 InstructionOperand* outputs[2]; |
259 size_t output_count = 0; | 259 size_t output_count = 0; |
260 | 260 |
261 // TODO(turbofan): match complex addressing modes. | 261 // TODO(turbofan): match complex addressing modes. |
262 if (g.CanBeImmediate(right)) { | 262 if (left == right) { |
| 263 // If both inputs refer to the same operand, enforce allocating a register |
| 264 // for both of them to ensure that we don't end up generating code like |
| 265 // this: |
| 266 // |
| 267 // mov eax, [ebp-0x10] |
| 268 // add eax, [ebp-0x10] |
| 269 // jo label |
| 270 InstructionOperand* const input = g.UseRegister(left); |
| 271 inputs[input_count++] = input; |
| 272 inputs[input_count++] = input; |
| 273 } else if (g.CanBeImmediate(right)) { |
263 inputs[input_count++] = g.UseRegister(left); | 274 inputs[input_count++] = g.UseRegister(left); |
264 inputs[input_count++] = g.UseImmediate(right); | 275 inputs[input_count++] = g.UseImmediate(right); |
265 } else { | 276 } else { |
266 if (node->op()->HasProperty(Operator::kCommutative) && | 277 if (node->op()->HasProperty(Operator::kCommutative) && |
267 g.CanBeBetterLeftOperand(right)) { | 278 g.CanBeBetterLeftOperand(right)) { |
268 std::swap(left, right); | 279 std::swap(left, right); |
269 } | 280 } |
270 inputs[input_count++] = g.UseRegister(left); | 281 inputs[input_count++] = g.UseRegister(left); |
271 inputs[input_count++] = g.Use(right); | 282 inputs[input_count++] = g.Use(right); |
272 } | 283 } |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont); | 678 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont); |
668 } else if (g.CanBeImmediate(left)) { | 679 } else if (g.CanBeImmediate(left)) { |
669 if (!commutative) cont->Commute(); | 680 if (!commutative) cont->Commute(); |
670 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont); | 681 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont); |
671 } else { | 682 } else { |
672 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont); | 683 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont); |
673 } | 684 } |
674 } | 685 } |
675 | 686 |
676 | 687 |
677 static void VisitWordTest(InstructionSelector* selector, Node* node, | |
678 FlagsContinuation* cont) { | |
679 IA32OperandGenerator g(selector); | |
680 VisitCompare(selector, kIA32Test, g.Use(node), g.TempImmediate(-1), cont); | |
681 } | |
682 | |
683 | |
684 // Shared routine for multiple float compare operations. | 688 // Shared routine for multiple float compare operations. |
685 static void VisitFloat64Compare(InstructionSelector* selector, Node* node, | 689 static void VisitFloat64Compare(InstructionSelector* selector, Node* node, |
686 FlagsContinuation* cont) { | 690 FlagsContinuation* cont) { |
687 IA32OperandGenerator g(selector); | 691 IA32OperandGenerator g(selector); |
688 Node* left = node->InputAt(0); | 692 Node* left = node->InputAt(0); |
689 Node* right = node->InputAt(1); | 693 Node* right = node->InputAt(1); |
690 VisitCompare(selector, kSSEFloat64Cmp, g.UseRegister(left), g.Use(right), | 694 VisitCompare(selector, kSSEFloat64Cmp, g.UseRegister(left), g.Use(right), |
691 cont); | 695 cont); |
692 } | 696 } |
693 | 697 |
694 | 698 |
695 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 699 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
696 BasicBlock* fbranch) { | 700 BasicBlock* fbranch) { |
697 OperandGenerator g(this); | 701 IA32OperandGenerator g(this); |
698 Node* user = branch; | 702 Node* user = branch; |
699 Node* value = branch->InputAt(0); | 703 Node* value = branch->InputAt(0); |
700 | 704 |
701 FlagsContinuation cont(kNotEqual, tbranch, fbranch); | 705 FlagsContinuation cont(kNotEqual, tbranch, fbranch); |
702 | 706 |
703 // If we can fall through to the true block, invert the branch. | 707 // If we can fall through to the true block, invert the branch. |
704 if (IsNextInAssemblyOrder(tbranch)) { | 708 if (IsNextInAssemblyOrder(tbranch)) { |
705 cont.Negate(); | 709 cont.Negate(); |
706 cont.SwapBlocks(); | 710 cont.SwapBlocks(); |
707 } | 711 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
773 case IrOpcode::kInt32Sub: | 777 case IrOpcode::kInt32Sub: |
774 return VisitWordCompare(this, value, kIA32Cmp, &cont, false); | 778 return VisitWordCompare(this, value, kIA32Cmp, &cont, false); |
775 case IrOpcode::kWord32And: | 779 case IrOpcode::kWord32And: |
776 return VisitWordCompare(this, value, kIA32Test, &cont, true); | 780 return VisitWordCompare(this, value, kIA32Test, &cont, true); |
777 default: | 781 default: |
778 break; | 782 break; |
779 } | 783 } |
780 } | 784 } |
781 | 785 |
782 // Branch could not be combined with a compare, emit compare against 0. | 786 // Branch could not be combined with a compare, emit compare against 0. |
783 VisitWordTest(this, value, &cont); | 787 VisitCompare(this, kIA32Cmp, g.Use(value), g.TempImmediate(0), &cont); |
784 } | 788 } |
785 | 789 |
786 | 790 |
787 void InstructionSelector::VisitWord32Equal(Node* const node) { | 791 void InstructionSelector::VisitWord32Equal(Node* const node) { |
788 Node* const user = node; | 792 Node* const user = node; |
789 FlagsContinuation cont(kEqual, node); | 793 FlagsContinuation cont(kEqual, node); |
790 Int32BinopMatcher m(user); | 794 Int32BinopMatcher m(user); |
791 if (m.right().Is(0)) { | 795 if (m.right().Is(0)) { |
792 Node* const value = m.left().node(); | 796 Node* const value = m.left().node(); |
793 if (CanCover(user, value)) { | 797 if (CanCover(user, value)) { |
794 switch (value->opcode()) { | 798 switch (value->opcode()) { |
795 case IrOpcode::kInt32Sub: | 799 case IrOpcode::kInt32Sub: |
796 return VisitWordCompare(this, value, kIA32Cmp, &cont, false); | 800 return VisitWordCompare(this, value, kIA32Cmp, &cont, false); |
797 case IrOpcode::kWord32And: | 801 case IrOpcode::kWord32And: |
798 return VisitWordCompare(this, value, kIA32Test, &cont, true); | 802 return VisitWordCompare(this, value, kIA32Test, &cont, true); |
799 default: | 803 default: |
800 break; | 804 break; |
801 } | 805 } |
802 return VisitWordTest(this, value, &cont); | |
803 } | 806 } |
804 } | 807 } |
805 return VisitWordCompare(this, node, kIA32Cmp, &cont, false); | 808 return VisitWordCompare(this, node, kIA32Cmp, &cont, false); |
806 } | 809 } |
807 | 810 |
808 | 811 |
809 void InstructionSelector::VisitInt32LessThan(Node* node) { | 812 void InstructionSelector::VisitInt32LessThan(Node* node) { |
810 FlagsContinuation cont(kSignedLessThan, node); | 813 FlagsContinuation cont(kSignedLessThan, node); |
811 return VisitWordCompare(this, node, kIA32Cmp, &cont, false); | 814 return VisitWordCompare(this, node, kIA32Cmp, &cont, false); |
812 } | 815 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
863 | 866 |
864 | 867 |
865 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { | 868 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { |
866 FlagsContinuation cont(kUnorderedLessThanOrEqual, node); | 869 FlagsContinuation cont(kUnorderedLessThanOrEqual, node); |
867 VisitFloat64Compare(this, node, &cont); | 870 VisitFloat64Compare(this, node, &cont); |
868 } | 871 } |
869 | 872 |
870 } // namespace compiler | 873 } // namespace compiler |
871 } // namespace internal | 874 } // namespace internal |
872 } // namespace v8 | 875 } // namespace v8 |
OLD | NEW |