Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(391)

Side by Side Diff: src/compiler/ia32/instruction-selector-ia32.cc

Issue 669133004: [turbofan] Improve code generation for inline comparisons with zero. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: REBASE Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/compiler/arm/instruction-selector-arm.cc ('k') | src/compiler/instruction-selector.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 629 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 // Emit the call instruction. 640 // Emit the call instruction.
641 InstructionOperand** first_output = 641 InstructionOperand** first_output =
642 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL; 642 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL;
643 Instruction* call_instr = 643 Instruction* call_instr =
644 Emit(opcode, buffer.outputs.size(), first_output, 644 Emit(opcode, buffer.outputs.size(), first_output,
645 buffer.instruction_args.size(), &buffer.instruction_args.front()); 645 buffer.instruction_args.size(), &buffer.instruction_args.front());
646 call_instr->MarkAsCall(); 646 call_instr->MarkAsCall();
647 } 647 }
648 648
649 649
650 namespace {
651
650 // Shared routine for multiple compare operations. 652 // Shared routine for multiple compare operations.
651 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, 653 void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
652 InstructionOperand* left, InstructionOperand* right, 654 InstructionOperand* left, InstructionOperand* right,
653 FlagsContinuation* cont) { 655 FlagsContinuation* cont) {
654 IA32OperandGenerator g(selector); 656 IA32OperandGenerator g(selector);
655 if (cont->IsBranch()) { 657 if (cont->IsBranch()) {
656 selector->Emit(cont->Encode(opcode), NULL, left, right, 658 selector->Emit(cont->Encode(opcode), NULL, left, right,
657 g.Label(cont->true_block()), 659 g.Label(cont->true_block()),
658 g.Label(cont->false_block()))->MarkAsControl(); 660 g.Label(cont->false_block()))->MarkAsControl();
659 } else { 661 } else {
660 DCHECK(cont->IsSet()); 662 DCHECK(cont->IsSet());
661 // TODO(titzer): Needs byte register. 663 // TODO(titzer): Needs byte register.
662 selector->Emit(cont->Encode(opcode), g.DefineAsRegister(cont->result()), 664 selector->Emit(cont->Encode(opcode), g.DefineAsRegister(cont->result()),
663 left, right); 665 left, right);
664 } 666 }
665 } 667 }
666 668
667 669
668 // Shared routine for multiple compare operations. 670 // Shared routine for multiple compare operations.
669 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, 671 void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
670 Node* left, Node* right, FlagsContinuation* cont, 672 Node* left, Node* right, FlagsContinuation* cont,
671 bool commutative) { 673 bool commutative) {
672 IA32OperandGenerator g(selector); 674 IA32OperandGenerator g(selector);
673 if (commutative && g.CanBeBetterLeftOperand(right)) { 675 if (commutative && g.CanBeBetterLeftOperand(right)) {
674 std::swap(left, right); 676 std::swap(left, right);
675 } 677 }
676 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont); 678 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont);
677 } 679 }
678 680
679 681
682 // Shared routine for multiple float compare operations.
683 void VisitFloat64Compare(InstructionSelector* selector, Node* node,
684 FlagsContinuation* cont) {
685 VisitCompare(selector, kSSEFloat64Cmp, node->InputAt(0), node->InputAt(1),
686 cont, node->op()->HasProperty(Operator::kCommutative));
687 }
688
689
680 // Shared routine for multiple word compare operations. 690 // Shared routine for multiple word compare operations.
681 static void VisitWordCompare(InstructionSelector* selector, Node* node, 691 void VisitWordCompare(InstructionSelector* selector, Node* node,
682 InstructionCode opcode, FlagsContinuation* cont) { 692 InstructionCode opcode, FlagsContinuation* cont) {
683 IA32OperandGenerator g(selector); 693 IA32OperandGenerator g(selector);
684 Node* const left = node->InputAt(0); 694 Node* const left = node->InputAt(0);
685 Node* const right = node->InputAt(1); 695 Node* const right = node->InputAt(1);
686 696
687 // Match immediates on left or right side of comparison. 697 // Match immediates on left or right side of comparison.
688 if (g.CanBeImmediate(right)) { 698 if (g.CanBeImmediate(right)) {
689 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont); 699 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont);
690 } else if (g.CanBeImmediate(left)) { 700 } else if (g.CanBeImmediate(left)) {
691 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); 701 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
692 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont); 702 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont);
693 } else { 703 } else {
694 VisitCompare(selector, opcode, left, right, cont, 704 VisitCompare(selector, opcode, left, right, cont,
695 node->op()->HasProperty(Operator::kCommutative)); 705 node->op()->HasProperty(Operator::kCommutative));
696 } 706 }
697 } 707 }
698 708
699 709
700 // Shared routine for multiple float compare operations. 710 void VisitWordCompare(InstructionSelector* selector, Node* node,
701 static void VisitFloat64Compare(InstructionSelector* selector, Node* node, 711 FlagsContinuation* cont) {
702 FlagsContinuation* cont) { 712 VisitWordCompare(selector, node, kIA32Cmp, cont);
703 VisitCompare(selector, kSSEFloat64Cmp, node->InputAt(0), node->InputAt(1),
704 cont, node->op()->HasProperty(Operator::kCommutative));
705 } 713 }
706 714
707 715
708 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, 716 // Shared routine for word comparison with zero.
709 BasicBlock* fbranch) { 717 void VisitWordCompareZero(InstructionSelector* selector, Node* user,
710 IA32OperandGenerator g(this); 718 Node* value, FlagsContinuation* cont) {
711 Node* user = branch;
712 Node* value = branch->InputAt(0);
713
714 FlagsContinuation cont(kNotEqual, tbranch, fbranch);
715
716 // If we can fall through to the true block, invert the branch.
717 if (IsNextInAssemblyOrder(tbranch)) {
718 cont.Negate();
719 cont.SwapBlocks();
720 }
721
722 // Try to combine with comparisons against 0 by simply inverting the branch.
723 while (CanCover(user, value) && value->opcode() == IrOpcode::kWord32Equal) {
724 Int32BinopMatcher m(value);
725 if (m.right().Is(0)) {
726 user = value;
727 value = m.left().node();
728 cont.Negate();
729 } else {
730 break;
731 }
732 }
733
734 // Try to combine the branch with a comparison. 719 // Try to combine the branch with a comparison.
735 if (CanCover(user, value)) { 720 while (selector->CanCover(user, value)) {
736 switch (value->opcode()) { 721 switch (value->opcode()) {
737 case IrOpcode::kWord32Equal: 722 case IrOpcode::kWord32Equal: {
738 cont.OverwriteAndNegateIfEqual(kEqual); 723 // Try to combine with comparisons against 0 by simply inverting the
739 return VisitWordCompare(this, value, kIA32Cmp, &cont); 724 // continuation.
725 Int32BinopMatcher m(value);
726 if (m.right().Is(0)) {
727 user = value;
728 value = m.left().node();
729 cont->Negate();
730 continue;
731 }
732 cont->OverwriteAndNegateIfEqual(kEqual);
733 return VisitWordCompare(selector, value, cont);
734 }
740 case IrOpcode::kInt32LessThan: 735 case IrOpcode::kInt32LessThan:
741 cont.OverwriteAndNegateIfEqual(kSignedLessThan); 736 cont->OverwriteAndNegateIfEqual(kSignedLessThan);
742 return VisitWordCompare(this, value, kIA32Cmp, &cont); 737 return VisitWordCompare(selector, value, cont);
743 case IrOpcode::kInt32LessThanOrEqual: 738 case IrOpcode::kInt32LessThanOrEqual:
744 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); 739 cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
745 return VisitWordCompare(this, value, kIA32Cmp, &cont); 740 return VisitWordCompare(selector, value, cont);
746 case IrOpcode::kUint32LessThan: 741 case IrOpcode::kUint32LessThan:
747 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); 742 cont->OverwriteAndNegateIfEqual(kUnsignedLessThan);
748 return VisitWordCompare(this, value, kIA32Cmp, &cont); 743 return VisitWordCompare(selector, value, cont);
749 case IrOpcode::kUint32LessThanOrEqual: 744 case IrOpcode::kUint32LessThanOrEqual:
750 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); 745 cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
751 return VisitWordCompare(this, value, kIA32Cmp, &cont); 746 return VisitWordCompare(selector, value, cont);
752 case IrOpcode::kFloat64Equal: 747 case IrOpcode::kFloat64Equal:
753 cont.OverwriteAndNegateIfEqual(kUnorderedEqual); 748 cont->OverwriteAndNegateIfEqual(kUnorderedEqual);
754 return VisitFloat64Compare(this, value, &cont); 749 return VisitFloat64Compare(selector, value, cont);
755 case IrOpcode::kFloat64LessThan: 750 case IrOpcode::kFloat64LessThan:
756 cont.OverwriteAndNegateIfEqual(kUnorderedLessThan); 751 cont->OverwriteAndNegateIfEqual(kUnorderedLessThan);
757 return VisitFloat64Compare(this, value, &cont); 752 return VisitFloat64Compare(selector, value, cont);
758 case IrOpcode::kFloat64LessThanOrEqual: 753 case IrOpcode::kFloat64LessThanOrEqual:
759 cont.OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual); 754 cont->OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual);
760 return VisitFloat64Compare(this, value, &cont); 755 return VisitFloat64Compare(selector, value, cont);
761 case IrOpcode::kProjection: 756 case IrOpcode::kProjection:
762 // Check if this is the overflow output projection of an 757 // Check if this is the overflow output projection of an
763 // <Operation>WithOverflow node. 758 // <Operation>WithOverflow node.
764 if (OpParameter<size_t>(value) == 1u) { 759 if (OpParameter<size_t>(value) == 1u) {
765 // We cannot combine the <Operation>WithOverflow with this branch 760 // We cannot combine the <Operation>WithOverflow with this branch
766 // unless the 0th projection (the use of the actual value of the 761 // unless the 0th projection (the use of the actual value of the
767 // <Operation> is either NULL, which means there's no use of the 762 // <Operation> is either NULL, which means there's no use of the
768 // actual value, or was already defined, which means it is scheduled 763 // actual value, or was already defined, which means it is scheduled
769 // *AFTER* this branch). 764 // *AFTER* this branch).
770 Node* node = value->InputAt(0); 765 Node* node = value->InputAt(0);
771 Node* result = node->FindProjection(0); 766 Node* result = node->FindProjection(0);
772 if (result == NULL || IsDefined(result)) { 767 if (result == NULL || selector->IsDefined(result)) {
773 switch (node->opcode()) { 768 switch (node->opcode()) {
774 case IrOpcode::kInt32AddWithOverflow: 769 case IrOpcode::kInt32AddWithOverflow:
775 cont.OverwriteAndNegateIfEqual(kOverflow); 770 cont->OverwriteAndNegateIfEqual(kOverflow);
776 return VisitBinop(this, node, kIA32Add, &cont); 771 return VisitBinop(selector, node, kIA32Add, cont);
777 case IrOpcode::kInt32SubWithOverflow: 772 case IrOpcode::kInt32SubWithOverflow:
778 cont.OverwriteAndNegateIfEqual(kOverflow); 773 cont->OverwriteAndNegateIfEqual(kOverflow);
779 return VisitBinop(this, node, kIA32Sub, &cont); 774 return VisitBinop(selector, node, kIA32Sub, cont);
780 default: 775 default:
781 break; 776 break;
782 } 777 }
783 } 778 }
784 } 779 }
785 break; 780 break;
786 case IrOpcode::kInt32Sub: 781 case IrOpcode::kInt32Sub:
787 return VisitWordCompare(this, value, kIA32Cmp, &cont); 782 return VisitWordCompare(selector, value, cont);
788 case IrOpcode::kWord32And: 783 case IrOpcode::kWord32And:
789 return VisitWordCompare(this, value, kIA32Test, &cont); 784 return VisitWordCompare(selector, value, kIA32Test, cont);
790 default: 785 default:
791 break; 786 break;
792 } 787 }
788 break;
793 } 789 }
794 790
795 // Branch could not be combined with a compare, emit compare against 0. 791 // Continuation could not be combined with a compare, emit compare against 0.
796 VisitCompare(this, kIA32Cmp, g.Use(value), g.TempImmediate(0), &cont); 792 IA32OperandGenerator g(selector);
793 VisitCompare(selector, kIA32Cmp, g.Use(value), g.TempImmediate(0), cont);
794 }
795
796 } // namespace
797
798
799 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
800 BasicBlock* fbranch) {
801 FlagsContinuation cont(kNotEqual, tbranch, fbranch);
802 if (IsNextInAssemblyOrder(tbranch)) { // We can fallthru to the true block.
803 cont.Negate();
804 cont.SwapBlocks();
805 }
806 VisitWordCompareZero(this, branch, branch->InputAt(0), &cont);
797 } 807 }
798 808
799 809
800 void InstructionSelector::VisitWord32Equal(Node* const node) { 810 void InstructionSelector::VisitWord32Equal(Node* const node) {
801 Node* const user = node;
802 FlagsContinuation cont(kEqual, node); 811 FlagsContinuation cont(kEqual, node);
803 Int32BinopMatcher m(user); 812 Int32BinopMatcher m(node);
804 if (m.right().Is(0)) { 813 if (m.right().Is(0)) {
805 Node* const value = m.left().node(); 814 return VisitWordCompareZero(this, m.node(), m.left().node(), &cont);
806 if (CanCover(user, value)) {
807 switch (value->opcode()) {
808 case IrOpcode::kInt32Sub:
809 return VisitWordCompare(this, value, kIA32Cmp, &cont);
810 case IrOpcode::kWord32And:
811 return VisitWordCompare(this, value, kIA32Test, &cont);
812 default:
813 break;
814 }
815 }
816 } 815 }
817 VisitWordCompare(this, node, kIA32Cmp, &cont); 816 VisitWordCompare(this, node, &cont);
818 } 817 }
819 818
820 819
821 void InstructionSelector::VisitInt32LessThan(Node* node) { 820 void InstructionSelector::VisitInt32LessThan(Node* node) {
822 FlagsContinuation cont(kSignedLessThan, node); 821 FlagsContinuation cont(kSignedLessThan, node);
823 VisitWordCompare(this, node, kIA32Cmp, &cont); 822 VisitWordCompare(this, node, &cont);
824 } 823 }
825 824
826 825
827 void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) { 826 void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) {
828 FlagsContinuation cont(kSignedLessThanOrEqual, node); 827 FlagsContinuation cont(kSignedLessThanOrEqual, node);
829 VisitWordCompare(this, node, kIA32Cmp, &cont); 828 VisitWordCompare(this, node, &cont);
830 } 829 }
831 830
832 831
833 void InstructionSelector::VisitUint32LessThan(Node* node) { 832 void InstructionSelector::VisitUint32LessThan(Node* node) {
834 FlagsContinuation cont(kUnsignedLessThan, node); 833 FlagsContinuation cont(kUnsignedLessThan, node);
835 VisitWordCompare(this, node, kIA32Cmp, &cont); 834 VisitWordCompare(this, node, &cont);
836 } 835 }
837 836
838 837
839 void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) { 838 void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) {
840 FlagsContinuation cont(kUnsignedLessThanOrEqual, node); 839 FlagsContinuation cont(kUnsignedLessThanOrEqual, node);
841 VisitWordCompare(this, node, kIA32Cmp, &cont); 840 VisitWordCompare(this, node, &cont);
842 } 841 }
843 842
844 843
845 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { 844 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
846 if (Node* ovf = node->FindProjection(1)) { 845 if (Node* ovf = node->FindProjection(1)) {
847 FlagsContinuation cont(kOverflow, ovf); 846 FlagsContinuation cont(kOverflow, ovf);
848 return VisitBinop(this, node, kIA32Add, &cont); 847 return VisitBinop(this, node, kIA32Add, &cont);
849 } 848 }
850 FlagsContinuation cont; 849 FlagsContinuation cont;
851 VisitBinop(this, node, kIA32Add, &cont); 850 VisitBinop(this, node, kIA32Add, &cont);
(...skipping 23 matching lines...) Expand all
875 874
876 875
877 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { 876 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
878 FlagsContinuation cont(kUnorderedLessThanOrEqual, node); 877 FlagsContinuation cont(kUnorderedLessThanOrEqual, node);
879 VisitFloat64Compare(this, node, &cont); 878 VisitFloat64Compare(this, node, &cont);
880 } 879 }
881 880
882 } // namespace compiler 881 } // namespace compiler
883 } // namespace internal 882 } // namespace internal
884 } // namespace v8 883 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/arm/instruction-selector-arm.cc ('k') | src/compiler/instruction-selector.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698