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

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

Issue 651783003: [turbofan] Make VisitBranch and friends to backend specific. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fixes Created 6 years, 2 months 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/instruction-selector.cc ('k') | no next file » | 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/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 687 matching lines...) Expand 10 before | Expand all | Expand 10 after
698 temps); 698 temps);
699 } 699 }
700 700
701 701
702 void InstructionSelector::VisitFloat64Sqrt(Node* node) { 702 void InstructionSelector::VisitFloat64Sqrt(Node* node) {
703 X64OperandGenerator g(this); 703 X64OperandGenerator g(this);
704 Emit(kSSEFloat64Sqrt, g.DefineAsRegister(node), g.Use(node->InputAt(0))); 704 Emit(kSSEFloat64Sqrt, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
705 } 705 }
706 706
707 707
708 void InstructionSelector::VisitInt32AddWithOverflow(Node* node, 708 void InstructionSelector::VisitCall(Node* node) {
709 FlagsContinuation* cont) { 709 X64OperandGenerator g(this);
710 VisitBinop(this, node, kX64Add32, cont); 710 CallDescriptor* descriptor = OpParameter<CallDescriptor*>(node);
711
712 FrameStateDescriptor* frame_state_descriptor = NULL;
713 if (descriptor->NeedsFrameState()) {
714 frame_state_descriptor = GetFrameStateDescriptor(
715 node->InputAt(static_cast<int>(descriptor->InputCount())));
716 }
717
718 CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
719
720 // Compute InstructionOperands for inputs and outputs.
721 InitializeCallBuffer(node, &buffer, true, true);
722
723 // Push any stack arguments.
724 for (NodeVectorRIter input = buffer.pushed_nodes.rbegin();
725 input != buffer.pushed_nodes.rend(); input++) {
726 // TODO(titzer): handle pushing double parameters.
727 Emit(kX64Push, NULL,
728 g.CanBeImmediate(*input) ? g.UseImmediate(*input) : g.Use(*input));
729 }
730
731 // Select the appropriate opcode based on the call type.
732 InstructionCode opcode;
733 switch (descriptor->kind()) {
734 case CallDescriptor::kCallCodeObject: {
735 opcode = kArchCallCodeObject;
736 break;
737 }
738 case CallDescriptor::kCallJSFunction:
739 opcode = kArchCallJSFunction;
740 break;
741 default:
742 UNREACHABLE();
743 return;
744 }
745 opcode |= MiscField::encode(descriptor->flags());
746
747 // Emit the call instruction.
748 Instruction* call_instr =
749 Emit(opcode, buffer.outputs.size(), &buffer.outputs.front(),
750 buffer.instruction_args.size(), &buffer.instruction_args.front());
751 call_instr->MarkAsCall();
711 } 752 }
712 753
713 754
714 void InstructionSelector::VisitInt32SubWithOverflow(Node* node,
715 FlagsContinuation* cont) {
716 VisitBinop(this, node, kX64Sub32, cont);
717 }
718
719
720 // Shared routine for multiple compare operations. 755 // Shared routine for multiple compare operations.
721 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, 756 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
722 InstructionOperand* left, InstructionOperand* right, 757 InstructionOperand* left, InstructionOperand* right,
723 FlagsContinuation* cont) { 758 FlagsContinuation* cont) {
724 X64OperandGenerator g(selector); 759 X64OperandGenerator g(selector);
725 opcode = cont->Encode(opcode); 760 opcode = cont->Encode(opcode);
726 if (cont->IsBranch()) { 761 if (cont->IsBranch()) {
727 selector->Emit(opcode, NULL, left, right, g.Label(cont->true_block()), 762 selector->Emit(opcode, NULL, left, right, g.Label(cont->true_block()),
728 g.Label(cont->false_block()))->MarkAsControl(); 763 g.Label(cont->false_block()))->MarkAsControl();
729 } else { 764 } else {
(...skipping 16 matching lines...) Expand all
746 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont); 781 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont);
747 } else if (g.CanBeImmediate(left)) { 782 } else if (g.CanBeImmediate(left)) {
748 if (!commutative) cont->Commute(); 783 if (!commutative) cont->Commute();
749 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont); 784 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont);
750 } else { 785 } else {
751 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont); 786 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont);
752 } 787 }
753 } 788 }
754 789
755 790
756 void InstructionSelector::VisitWord32Test(Node* node, FlagsContinuation* cont) { 791 static void VisitWordTest(InstructionSelector* selector, Node* node,
757 switch (node->opcode()) { 792 InstructionCode opcode, FlagsContinuation* cont) {
758 case IrOpcode::kInt32Sub: 793 X64OperandGenerator g(selector);
759 return VisitWordCompare(this, node, kX64Cmp32, cont, false); 794 VisitCompare(selector, opcode, g.Use(node), g.TempImmediate(-1), cont);
760 case IrOpcode::kWord32And: 795 }
761 return VisitWordCompare(this, node, kX64Test32, cont, true); 796
762 default: 797
763 break; 798 static void VisitFloat64Compare(InstructionSelector* selector, Node* node,
764 } 799 FlagsContinuation* cont) {
765 800 X64OperandGenerator g(selector);
766 X64OperandGenerator g(this);
767 VisitCompare(this, kX64Test32, g.Use(node), g.TempImmediate(-1), cont);
768 }
769
770
771 void InstructionSelector::VisitWord64Test(Node* node, FlagsContinuation* cont) {
772 switch (node->opcode()) {
773 case IrOpcode::kInt64Sub:
774 return VisitWordCompare(this, node, kX64Cmp, cont, false);
775 case IrOpcode::kWord64And:
776 return VisitWordCompare(this, node, kX64Test, cont, true);
777 default:
778 break;
779 }
780
781 X64OperandGenerator g(this);
782 VisitCompare(this, kX64Test, g.Use(node), g.TempImmediate(-1), cont);
783 }
784
785
786 void InstructionSelector::VisitWord32Compare(Node* node,
787 FlagsContinuation* cont) {
788 VisitWordCompare(this, node, kX64Cmp32, cont, false);
789 }
790
791
792 void InstructionSelector::VisitWord64Compare(Node* node,
793 FlagsContinuation* cont) {
794 VisitWordCompare(this, node, kX64Cmp, cont, false);
795 }
796
797
798 void InstructionSelector::VisitFloat64Compare(Node* node,
799 FlagsContinuation* cont) {
800 X64OperandGenerator g(this);
801 Node* left = node->InputAt(0); 801 Node* left = node->InputAt(0);
802 Node* right = node->InputAt(1); 802 Node* right = node->InputAt(1);
803 VisitCompare(this, kSSEFloat64Cmp, g.UseRegister(left), g.Use(right), cont); 803 VisitCompare(selector, kSSEFloat64Cmp, g.UseRegister(left), g.Use(right),
804 } 804 cont);
805 805 }
806 806
807 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, 807
808 BasicBlock* deoptimization) { 808 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
809 X64OperandGenerator g(this); 809 BasicBlock* fbranch) {
810 CallDescriptor* descriptor = OpParameter<CallDescriptor*>(call); 810 OperandGenerator g(this);
811 811 Node* user = branch;
812 FrameStateDescriptor* frame_state_descriptor = NULL; 812 Node* value = branch->InputAt(0);
813 if (descriptor->NeedsFrameState()) { 813
814 frame_state_descriptor = GetFrameStateDescriptor( 814 FlagsContinuation cont(kNotEqual, tbranch, fbranch);
815 call->InputAt(static_cast<int>(descriptor->InputCount()))); 815
816 } 816 // If we can fall through to the true block, invert the branch.
817 817 if (IsNextInAssemblyOrder(tbranch)) {
818 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); 818 cont.Negate();
819 819 cont.SwapBlocks();
820 // Compute InstructionOperands for inputs and outputs. 820 }
821 InitializeCallBuffer(call, &buffer, true, true); 821
822 822 // Try to combine with comparisons against 0 by simply inverting the branch.
823 // Push any stack arguments. 823 while (CanCover(user, value)) {
824 for (NodeVectorRIter input = buffer.pushed_nodes.rbegin(); 824 if (value->opcode() == IrOpcode::kWord32Equal) {
825 input != buffer.pushed_nodes.rend(); input++) { 825 Int32BinopMatcher m(value);
826 // TODO(titzer): handle pushing double parameters. 826 if (m.right().Is(0)) {
827 Emit(kX64Push, NULL, 827 user = value;
828 g.CanBeImmediate(*input) ? g.UseImmediate(*input) : g.Use(*input)); 828 value = m.left().node();
829 } 829 cont.Negate();
830 830 } else {
831 // Select the appropriate opcode based on the call type. 831 break;
832 InstructionCode opcode; 832 }
833 switch (descriptor->kind()) { 833 } else if (value->opcode() == IrOpcode::kWord64Equal) {
834 case CallDescriptor::kCallCodeObject: { 834 Int64BinopMatcher m(value);
835 opcode = kArchCallCodeObject; 835 if (m.right().Is(0)) {
836 user = value;
837 value = m.left().node();
838 cont.Negate();
839 } else {
840 break;
841 }
842 } else {
836 break; 843 break;
837 } 844 }
838 case CallDescriptor::kCallJSFunction: 845 }
839 opcode = kArchCallJSFunction; 846
840 break; 847 // Try to combine the branch with a comparison.
841 default: 848 if (CanCover(user, value)) {
842 UNREACHABLE(); 849 switch (value->opcode()) {
843 return; 850 case IrOpcode::kWord32Equal:
844 } 851 cont.OverwriteAndNegateIfEqual(kEqual);
845 opcode |= MiscField::encode(descriptor->flags()); 852 return VisitWordCompare(this, value, kX64Cmp32, &cont, false);
846 853 case IrOpcode::kInt32LessThan:
847 // Emit the call instruction. 854 cont.OverwriteAndNegateIfEqual(kSignedLessThan);
848 Instruction* call_instr = 855 return VisitWordCompare(this, value, kX64Cmp32, &cont, false);
849 Emit(opcode, buffer.outputs.size(), &buffer.outputs.front(), 856 case IrOpcode::kInt32LessThanOrEqual:
850 buffer.instruction_args.size(), &buffer.instruction_args.front()); 857 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
851 858 return VisitWordCompare(this, value, kX64Cmp32, &cont, false);
852 call_instr->MarkAsCall(); 859 case IrOpcode::kUint32LessThan:
853 if (deoptimization != NULL) { 860 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan);
854 DCHECK(continuation != NULL); 861 return VisitWordCompare(this, value, kX64Cmp32, &cont, false);
855 call_instr->MarkAsControl(); 862 case IrOpcode::kUint32LessThanOrEqual:
856 } 863 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
864 return VisitWordCompare(this, value, kX64Cmp32, &cont, false);
865 case IrOpcode::kWord64Equal:
866 cont.OverwriteAndNegateIfEqual(kEqual);
867 return VisitWordCompare(this, value, kX64Cmp, &cont, false);
868 case IrOpcode::kInt64LessThan:
869 cont.OverwriteAndNegateIfEqual(kSignedLessThan);
870 return VisitWordCompare(this, value, kX64Cmp, &cont, false);
871 case IrOpcode::kInt64LessThanOrEqual:
872 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
873 return VisitWordCompare(this, value, kX64Cmp, &cont, false);
874 case IrOpcode::kUint64LessThan:
875 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan);
876 return VisitWordCompare(this, value, kX64Cmp, &cont, false);
877 case IrOpcode::kFloat64Equal:
878 cont.OverwriteAndNegateIfEqual(kUnorderedEqual);
879 return VisitFloat64Compare(this, value, &cont);
880 case IrOpcode::kFloat64LessThan:
881 cont.OverwriteAndNegateIfEqual(kUnorderedLessThan);
882 return VisitFloat64Compare(this, value, &cont);
883 case IrOpcode::kFloat64LessThanOrEqual:
884 cont.OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual);
885 return VisitFloat64Compare(this, value, &cont);
886 case IrOpcode::kProjection:
887 // Check if this is the overflow output projection of an
888 // <Operation>WithOverflow node.
889 if (OpParameter<size_t>(value) == 1u) {
890 // We cannot combine the <Operation>WithOverflow with this branch
891 // unless the 0th projection (the use of the actual value of the
892 // <Operation> is either NULL, which means there's no use of the
893 // actual value, or was already defined, which means it is scheduled
894 // *AFTER* this branch).
895 Node* node = value->InputAt(0);
896 Node* result = node->FindProjection(0);
897 if (result == NULL || IsDefined(result)) {
898 switch (node->opcode()) {
899 case IrOpcode::kInt32AddWithOverflow:
900 cont.OverwriteAndNegateIfEqual(kOverflow);
901 return VisitBinop(this, node, kX64Add32, &cont);
902 case IrOpcode::kInt32SubWithOverflow:
903 cont.OverwriteAndNegateIfEqual(kOverflow);
904 return VisitBinop(this, node, kX64Sub32, &cont);
905 default:
906 break;
907 }
908 }
909 }
910 break;
911 case IrOpcode::kInt32Sub:
912 return VisitWordCompare(this, value, kX64Cmp32, &cont, false);
913 case IrOpcode::kWord32And:
914 return VisitWordCompare(this, value, kX64Test32, &cont, true);
915 default:
916 break;
917 }
918 }
919
920 // Branch could not be combined with a compare, emit compare against 0.
921 VisitWordTest(this, value, kX64Test32, &cont);
922 }
923
924
925 void InstructionSelector::VisitWord32Equal(Node* const node) {
926 Node* const user = node;
927 FlagsContinuation cont(kEqual, node);
928 Int32BinopMatcher m(user);
929 if (m.right().Is(0)) {
930 Node* const value = m.left().node();
931 if (CanCover(user, value)) {
932 switch (value->opcode()) {
933 case IrOpcode::kInt32Sub:
934 return VisitWordCompare(this, value, kX64Cmp32, &cont, false);
935 case IrOpcode::kWord32And:
936 return VisitWordCompare(this, value, kX64Test32, &cont, true);
937 default:
938 break;
939 }
940 return VisitWordTest(this, value, kX64Test32, &cont);
941 }
942 }
943 VisitWordCompare(this, node, kX64Cmp32, &cont, false);
944 }
945
946
947 void InstructionSelector::VisitInt32LessThan(Node* node) {
948 FlagsContinuation cont(kSignedLessThan, node);
949 VisitWordCompare(this, node, kX64Cmp32, &cont, false);
950 }
951
952
953 void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) {
954 FlagsContinuation cont(kSignedLessThanOrEqual, node);
955 VisitWordCompare(this, node, kX64Cmp32, &cont, false);
956 }
957
958
959 void InstructionSelector::VisitUint32LessThan(Node* node) {
960 FlagsContinuation cont(kUnsignedLessThan, node);
961 VisitWordCompare(this, node, kX64Cmp32, &cont, false);
962 }
963
964
965 void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) {
966 FlagsContinuation cont(kUnsignedLessThanOrEqual, node);
967 VisitWordCompare(this, node, kX64Cmp32, &cont, false);
968 }
969
970
971 void InstructionSelector::VisitWord64Equal(Node* const node) {
972 Node* const user = node;
973 FlagsContinuation cont(kEqual, node);
974 Int64BinopMatcher m(user);
975 if (m.right().Is(0)) {
976 Node* const value = m.left().node();
977 if (CanCover(user, value)) {
978 switch (value->opcode()) {
979 case IrOpcode::kInt64Sub:
980 return VisitWordCompare(this, value, kX64Cmp, &cont, false);
981 case IrOpcode::kWord64And:
982 return VisitWordCompare(this, value, kX64Test, &cont, true);
983 default:
984 break;
985 }
986 return VisitWordTest(this, value, kX64Test, &cont);
987 }
988 }
989 VisitWordCompare(this, node, kX64Cmp, &cont, false);
990 }
991
992
993 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
994 if (Node* ovf = node->FindProjection(1)) {
995 FlagsContinuation cont(kOverflow, ovf);
996 VisitBinop(this, node, kX64Add32, &cont);
997 }
998 FlagsContinuation cont;
999 VisitBinop(this, node, kX64Add32, &cont);
1000 }
1001
1002
1003 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
1004 if (Node* ovf = node->FindProjection(1)) {
1005 FlagsContinuation cont(kOverflow, ovf);
1006 return VisitBinop(this, node, kX64Sub32, &cont);
1007 }
1008 FlagsContinuation cont;
1009 VisitBinop(this, node, kX64Sub32, &cont);
1010 }
1011
1012
1013 void InstructionSelector::VisitInt64LessThan(Node* node) {
1014 FlagsContinuation cont(kSignedLessThan, node);
1015 VisitWordCompare(this, node, kX64Cmp, &cont, false);
1016 }
1017
1018
1019 void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) {
1020 FlagsContinuation cont(kSignedLessThanOrEqual, node);
1021 VisitWordCompare(this, node, kX64Cmp, &cont, false);
1022 }
1023
1024
1025 void InstructionSelector::VisitUint64LessThan(Node* node) {
1026 FlagsContinuation cont(kUnsignedLessThan, node);
1027 VisitWordCompare(this, node, kX64Cmp, &cont, false);
1028 }
1029
1030
1031 void InstructionSelector::VisitFloat64Equal(Node* node) {
1032 FlagsContinuation cont(kUnorderedEqual, node);
1033 VisitFloat64Compare(this, node, &cont);
1034 }
1035
1036
1037 void InstructionSelector::VisitFloat64LessThan(Node* node) {
1038 FlagsContinuation cont(kUnorderedLessThan, node);
1039 VisitFloat64Compare(this, node, &cont);
1040 }
1041
1042
1043 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
1044 FlagsContinuation cont(kUnorderedLessThanOrEqual, node);
1045 VisitFloat64Compare(this, node, &cont);
857 } 1046 }
858 1047
859 } // namespace compiler 1048 } // namespace compiler
860 } // namespace internal 1049 } // namespace internal
861 } // namespace v8 1050 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/instruction-selector.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698