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