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

Side by Side Diff: src/compiler/arm/instruction-selector-arm.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 | « no previous file | src/compiler/arm64/instruction-selector-arm64.cc » ('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/base/bits.h" 5 #include "src/base/bits.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 774 matching lines...) Expand 10 before | Expand all | Expand 10 after
785 g.UseFixed(node->InputAt(1), d1))->MarkAsCall(); 785 g.UseFixed(node->InputAt(1), d1))->MarkAsCall();
786 } 786 }
787 787
788 788
789 void InstructionSelector::VisitFloat64Sqrt(Node* node) { 789 void InstructionSelector::VisitFloat64Sqrt(Node* node) {
790 ArmOperandGenerator g(this); 790 ArmOperandGenerator g(this);
791 Emit(kArmVsqrtF64, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0))); 791 Emit(kArmVsqrtF64, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0)));
792 } 792 }
793 793
794 794
795 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, 795 void InstructionSelector::VisitCall(Node* node) {
796 BasicBlock* deoptimization) {
797 ArmOperandGenerator g(this); 796 ArmOperandGenerator g(this);
798 CallDescriptor* descriptor = OpParameter<CallDescriptor*>(call); 797 CallDescriptor* descriptor = OpParameter<CallDescriptor*>(node);
799 798
800 FrameStateDescriptor* frame_state_descriptor = NULL; 799 FrameStateDescriptor* frame_state_descriptor = NULL;
801 if (descriptor->NeedsFrameState()) { 800 if (descriptor->NeedsFrameState()) {
802 frame_state_descriptor = 801 frame_state_descriptor =
803 GetFrameStateDescriptor(call->InputAt(descriptor->InputCount())); 802 GetFrameStateDescriptor(node->InputAt(descriptor->InputCount()));
804 } 803 }
805 804
806 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); 805 CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
807 806
808 // Compute InstructionOperands for inputs and outputs. 807 // Compute InstructionOperands for inputs and outputs.
809 // TODO(turbofan): on ARM64 it's probably better to use the code object in a 808 // TODO(turbofan): on ARM64 it's probably better to use the code object in a
810 // register if there are multiple uses of it. Improve constant pool and the 809 // register if there are multiple uses of it. Improve constant pool and the
811 // heuristics in the register allocator for where to emit constants. 810 // heuristics in the register allocator for where to emit constants.
812 InitializeCallBuffer(call, &buffer, true, false); 811 InitializeCallBuffer(node, &buffer, true, false);
813 812
814 // TODO(dcarney): might be possible to use claim/poke instead 813 // TODO(dcarney): might be possible to use claim/poke instead
815 // Push any stack arguments. 814 // Push any stack arguments.
816 for (NodeVectorRIter input = buffer.pushed_nodes.rbegin(); 815 for (NodeVectorRIter input = buffer.pushed_nodes.rbegin();
817 input != buffer.pushed_nodes.rend(); input++) { 816 input != buffer.pushed_nodes.rend(); input++) {
818 Emit(kArmPush, NULL, g.UseRegister(*input)); 817 Emit(kArmPush, NULL, g.UseRegister(*input));
819 } 818 }
820 819
821 // Select the appropriate opcode based on the call type. 820 // Select the appropriate opcode based on the call type.
822 InstructionCode opcode; 821 InstructionCode opcode;
823 switch (descriptor->kind()) { 822 switch (descriptor->kind()) {
824 case CallDescriptor::kCallCodeObject: { 823 case CallDescriptor::kCallCodeObject: {
825 opcode = kArchCallCodeObject; 824 opcode = kArchCallCodeObject;
826 break; 825 break;
827 } 826 }
828 case CallDescriptor::kCallJSFunction: 827 case CallDescriptor::kCallJSFunction:
829 opcode = kArchCallJSFunction; 828 opcode = kArchCallJSFunction;
830 break; 829 break;
831 default: 830 default:
832 UNREACHABLE(); 831 UNREACHABLE();
833 return; 832 return;
834 } 833 }
835 opcode |= MiscField::encode(descriptor->flags()); 834 opcode |= MiscField::encode(descriptor->flags());
836 835
837 // Emit the call instruction. 836 // Emit the call instruction.
838 Instruction* call_instr = 837 Instruction* call_instr =
839 Emit(opcode, buffer.outputs.size(), &buffer.outputs.front(), 838 Emit(opcode, buffer.outputs.size(), &buffer.outputs.front(),
840 buffer.instruction_args.size(), &buffer.instruction_args.front()); 839 buffer.instruction_args.size(), &buffer.instruction_args.front());
840 call_instr->MarkAsCall();
841 }
841 842
842 call_instr->MarkAsCall(); 843
843 if (deoptimization != NULL) { 844 namespace {
844 DCHECK(continuation != NULL); 845
845 call_instr->MarkAsControl(); 846 // Shared routine for multiple float compare operations.
847 void VisitFloat64Compare(InstructionSelector* selector, Node* node,
848 FlagsContinuation* cont) {
849 ArmOperandGenerator g(selector);
850 Float64BinopMatcher m(node);
851 if (cont->IsBranch()) {
852 selector->Emit(cont->Encode(kArmVcmpF64), nullptr,
853 g.UseRegister(m.left().node()),
854 g.UseRegister(m.right().node()), g.Label(cont->true_block()),
855 g.Label(cont->false_block()))->MarkAsControl();
856 } else {
857 DCHECK(cont->IsSet());
858 selector->Emit(
859 cont->Encode(kArmVcmpF64), g.DefineAsRegister(cont->result()),
860 g.UseRegister(m.left().node()), g.UseRegister(m.right().node()));
846 } 861 }
847 } 862 }
848 863
849 864
850 void InstructionSelector::VisitInt32AddWithOverflow(Node* node, 865 // Shared routine for multiple word compare operations.
851 FlagsContinuation* cont) { 866 void VisitWordCompare(InstructionSelector* selector, Node* node,
852 VisitBinop(this, node, kArmAdd, kArmAdd, cont); 867 InstructionCode opcode, FlagsContinuation* cont,
853 } 868 bool commutative) {
854
855
856 void InstructionSelector::VisitInt32SubWithOverflow(Node* node,
857 FlagsContinuation* cont) {
858 VisitBinop(this, node, kArmSub, kArmRsb, cont);
859 }
860
861
862 // Shared routine for multiple compare operations.
863 static void VisitWordCompare(InstructionSelector* selector, Node* node,
864 InstructionCode opcode, FlagsContinuation* cont,
865 bool commutative) {
866 ArmOperandGenerator g(selector); 869 ArmOperandGenerator g(selector);
867 Int32BinopMatcher m(node); 870 Int32BinopMatcher m(node);
868 InstructionOperand* inputs[5]; 871 InstructionOperand* inputs[5];
869 size_t input_count = 0; 872 size_t input_count = 0;
870 InstructionOperand* outputs[1]; 873 InstructionOperand* outputs[1];
871 size_t output_count = 0; 874 size_t output_count = 0;
872 875
873 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(), 876 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
874 &input_count, &inputs[1])) { 877 &input_count, &inputs[1])) {
875 inputs[0] = g.UseRegister(m.left().node()); 878 inputs[0] = g.UseRegister(m.left().node());
(...skipping 20 matching lines...) Expand all
896 DCHECK_NE(0, input_count); 899 DCHECK_NE(0, input_count);
897 DCHECK_GE(arraysize(inputs), input_count); 900 DCHECK_GE(arraysize(inputs), input_count);
898 DCHECK_GE(arraysize(outputs), output_count); 901 DCHECK_GE(arraysize(outputs), output_count);
899 902
900 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, 903 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count,
901 outputs, input_count, inputs); 904 outputs, input_count, inputs);
902 if (cont->IsBranch()) instr->MarkAsControl(); 905 if (cont->IsBranch()) instr->MarkAsControl();
903 } 906 }
904 907
905 908
906 void InstructionSelector::VisitWord32Test(Node* node, FlagsContinuation* cont) { 909 void VisitWordCompare(InstructionSelector* selector, Node* node,
907 switch (node->opcode()) { 910 FlagsContinuation* cont) {
908 case IrOpcode::kInt32Add: 911 VisitWordCompare(selector, node, kArmCmp, cont, false);
909 return VisitWordCompare(this, node, kArmCmn, cont, true); 912 }
910 case IrOpcode::kInt32Sub: 913
911 return VisitWordCompare(this, node, kArmCmp, cont, false); 914
912 case IrOpcode::kWord32And: 915 void VisitWordTest(InstructionSelector* selector, Node* node,
913 return VisitWordCompare(this, node, kArmTst, cont, true); 916 FlagsContinuation* cont) {
914 case IrOpcode::kWord32Or: 917 ArmOperandGenerator g(selector);
915 return VisitBinop(this, node, kArmOrr, kArmOrr, cont);
916 case IrOpcode::kWord32Xor:
917 return VisitWordCompare(this, node, kArmTeq, cont, true);
918 case IrOpcode::kWord32Sar:
919 return VisitShift(this, node, TryMatchASR, cont);
920 case IrOpcode::kWord32Shl:
921 return VisitShift(this, node, TryMatchLSL, cont);
922 case IrOpcode::kWord32Shr:
923 return VisitShift(this, node, TryMatchLSR, cont);
924 case IrOpcode::kWord32Ror:
925 return VisitShift(this, node, TryMatchROR, cont);
926 default:
927 break;
928 }
929
930 ArmOperandGenerator g(this);
931 InstructionCode opcode = 918 InstructionCode opcode =
932 cont->Encode(kArmTst) | AddressingModeField::encode(kMode_Operand2_R); 919 cont->Encode(kArmTst) | AddressingModeField::encode(kMode_Operand2_R);
933 if (cont->IsBranch()) { 920 if (cont->IsBranch()) {
934 Emit(opcode, NULL, g.UseRegister(node), g.UseRegister(node), 921 selector->Emit(opcode, nullptr, g.UseRegister(node), g.UseRegister(node),
935 g.Label(cont->true_block()), 922 g.Label(cont->true_block()),
936 g.Label(cont->false_block()))->MarkAsControl(); 923 g.Label(cont->false_block()))->MarkAsControl();
937 } else { 924 } else {
938 Emit(opcode, g.DefineAsRegister(cont->result()), g.UseRegister(node), 925 selector->Emit(opcode, g.DefineAsRegister(cont->result()),
939 g.UseRegister(node)); 926 g.UseRegister(node), g.UseRegister(node));
940 } 927 }
941 } 928 }
942 929
943 930 } // namespace
944 void InstructionSelector::VisitWord32Compare(Node* node, 931
945 FlagsContinuation* cont) { 932
946 VisitWordCompare(this, node, kArmCmp, cont, false); 933 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
947 } 934 BasicBlock* fbranch) {
948
949
950 void InstructionSelector::VisitFloat64Compare(Node* node,
951 FlagsContinuation* cont) {
952 ArmOperandGenerator g(this); 935 ArmOperandGenerator g(this);
953 Float64BinopMatcher m(node); 936 Node* user = branch;
954 if (cont->IsBranch()) { 937 Node* value = branch->InputAt(0);
955 Emit(cont->Encode(kArmVcmpF64), NULL, g.UseRegister(m.left().node()), 938
956 g.UseRegister(m.right().node()), g.Label(cont->true_block()), 939 FlagsContinuation cont(kNotEqual, tbranch, fbranch);
957 g.Label(cont->false_block()))->MarkAsControl(); 940
958 } else { 941 // If we can fall through to the true block, invert the branch.
959 DCHECK(cont->IsSet()); 942 if (IsNextInAssemblyOrder(tbranch)) {
960 Emit(cont->Encode(kArmVcmpF64), g.DefineAsRegister(cont->result()), 943 cont.Negate();
961 g.UseRegister(m.left().node()), g.UseRegister(m.right().node())); 944 cont.SwapBlocks();
962 } 945 }
946
947 // Try to combine with comparisons against 0 by simply inverting the branch.
948 while (CanCover(user, value) && value->opcode() == IrOpcode::kWord32Equal) {
949 Int32BinopMatcher m(value);
950 if (m.right().Is(0)) {
951 user = value;
952 value = m.left().node();
953 cont.Negate();
954 } else {
955 break;
956 }
957 }
958
959 // Try to combine the branch with a comparison.
960 if (CanCover(user, value)) {
961 switch (value->opcode()) {
962 case IrOpcode::kWord32Equal:
963 cont.OverwriteAndNegateIfEqual(kEqual);
964 return VisitWordCompare(this, value, &cont);
965 case IrOpcode::kInt32LessThan:
966 cont.OverwriteAndNegateIfEqual(kSignedLessThan);
967 return VisitWordCompare(this, value, &cont);
968 case IrOpcode::kInt32LessThanOrEqual:
969 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
970 return VisitWordCompare(this, value, &cont);
971 case IrOpcode::kUint32LessThan:
972 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan);
973 return VisitWordCompare(this, value, &cont);
974 case IrOpcode::kUint32LessThanOrEqual:
975 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
976 return VisitWordCompare(this, value, &cont);
977 case IrOpcode::kFloat64Equal:
978 cont.OverwriteAndNegateIfEqual(kUnorderedEqual);
979 return VisitFloat64Compare(this, value, &cont);
980 case IrOpcode::kFloat64LessThan:
981 cont.OverwriteAndNegateIfEqual(kUnorderedLessThan);
982 return VisitFloat64Compare(this, value, &cont);
983 case IrOpcode::kFloat64LessThanOrEqual:
984 cont.OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual);
985 return VisitFloat64Compare(this, value, &cont);
986 case IrOpcode::kProjection:
987 // Check if this is the overflow output projection of an
988 // <Operation>WithOverflow node.
989 if (OpParameter<size_t>(value) == 1u) {
990 // We cannot combine the <Operation>WithOverflow with this branch
991 // unless the 0th projection (the use of the actual value of the
992 // <Operation> is either NULL, which means there's no use of the
993 // actual value, or was already defined, which means it is scheduled
994 // *AFTER* this branch).
995 Node* node = value->InputAt(0);
996 Node* result = node->FindProjection(0);
997 if (!result || IsDefined(result)) {
998 switch (node->opcode()) {
999 case IrOpcode::kInt32AddWithOverflow:
1000 cont.OverwriteAndNegateIfEqual(kOverflow);
1001 return VisitBinop(this, node, kArmAdd, kArmAdd, &cont);
1002 case IrOpcode::kInt32SubWithOverflow:
1003 cont.OverwriteAndNegateIfEqual(kOverflow);
1004 return VisitBinop(this, node, kArmSub, kArmRsb, &cont);
1005 default:
1006 break;
1007 }
1008 }
1009 }
1010 break;
1011 case IrOpcode::kInt32Add:
1012 return VisitWordCompare(this, value, kArmCmn, &cont, true);
1013 case IrOpcode::kInt32Sub:
1014 return VisitWordCompare(this, value, kArmCmp, &cont, false);
1015 case IrOpcode::kWord32And:
1016 return VisitWordCompare(this, value, kArmTst, &cont, true);
1017 case IrOpcode::kWord32Or:
1018 return VisitBinop(this, value, kArmOrr, kArmOrr, &cont);
1019 case IrOpcode::kWord32Xor:
1020 return VisitWordCompare(this, value, kArmTeq, &cont, true);
1021 case IrOpcode::kWord32Sar:
1022 return VisitShift(this, value, TryMatchASR, &cont);
1023 case IrOpcode::kWord32Shl:
1024 return VisitShift(this, value, TryMatchLSL, &cont);
1025 case IrOpcode::kWord32Shr:
1026 return VisitShift(this, value, TryMatchLSR, &cont);
1027 case IrOpcode::kWord32Ror:
1028 return VisitShift(this, value, TryMatchROR, &cont);
1029 default:
1030 break;
1031 }
1032 }
1033
1034 // Branch could not be combined with a compare, emit compare against 0.
1035 return VisitWordTest(this, value, &cont);
1036 }
1037
1038
1039 void InstructionSelector::VisitWord32Equal(Node* const node) {
1040 Node* const user = node;
1041 FlagsContinuation cont(kEqual, node);
1042 Int32BinopMatcher m(user);
1043 if (m.right().Is(0)) {
1044 Node* const value = m.left().node();
1045 if (CanCover(user, value)) {
1046 switch (value->opcode()) {
1047 case IrOpcode::kInt32Add:
1048 return VisitWordCompare(this, value, kArmCmn, &cont, true);
1049 case IrOpcode::kInt32Sub:
1050 return VisitWordCompare(this, value, kArmCmp, &cont, false);
1051 case IrOpcode::kWord32And:
1052 return VisitWordCompare(this, value, kArmTst, &cont, true);
1053 case IrOpcode::kWord32Or:
1054 return VisitBinop(this, value, kArmOrr, kArmOrr, &cont);
1055 case IrOpcode::kWord32Xor:
1056 return VisitWordCompare(this, value, kArmTeq, &cont, true);
1057 case IrOpcode::kWord32Sar:
1058 return VisitShift(this, value, TryMatchASR, &cont);
1059 case IrOpcode::kWord32Shl:
1060 return VisitShift(this, value, TryMatchLSL, &cont);
1061 case IrOpcode::kWord32Shr:
1062 return VisitShift(this, value, TryMatchLSR, &cont);
1063 case IrOpcode::kWord32Ror:
1064 return VisitShift(this, value, TryMatchROR, &cont);
1065 default:
1066 break;
1067 }
1068 return VisitWordTest(this, value, &cont);
1069 }
1070 }
1071 VisitWordCompare(this, node, &cont);
1072 }
1073
1074
1075 void InstructionSelector::VisitInt32LessThan(Node* node) {
1076 FlagsContinuation cont(kSignedLessThan, node);
1077 VisitWordCompare(this, node, &cont);
1078 }
1079
1080
1081 void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) {
1082 FlagsContinuation cont(kSignedLessThanOrEqual, node);
1083 VisitWordCompare(this, node, &cont);
1084 }
1085
1086
1087 void InstructionSelector::VisitUint32LessThan(Node* node) {
1088 FlagsContinuation cont(kUnsignedLessThan, node);
1089 VisitWordCompare(this, node, &cont);
1090 }
1091
1092
1093 void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) {
1094 FlagsContinuation cont(kUnsignedLessThanOrEqual, node);
1095 VisitWordCompare(this, node, &cont);
1096 }
1097
1098
1099 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
1100 if (Node* ovf = node->FindProjection(1)) {
1101 FlagsContinuation cont(kOverflow, ovf);
1102 return VisitBinop(this, node, kArmAdd, kArmAdd, &cont);
1103 }
1104 FlagsContinuation cont;
1105 VisitBinop(this, node, kArmAdd, kArmAdd, &cont);
1106 }
1107
1108
1109 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
1110 if (Node* ovf = node->FindProjection(1)) {
1111 FlagsContinuation cont(kOverflow, ovf);
1112 return VisitBinop(this, node, kArmSub, kArmRsb, &cont);
1113 }
1114 FlagsContinuation cont;
1115 VisitBinop(this, node, kArmSub, kArmRsb, &cont);
1116 }
1117
1118
1119 void InstructionSelector::VisitFloat64Equal(Node* node) {
1120 FlagsContinuation cont(kUnorderedEqual, node);
1121 VisitFloat64Compare(this, node, &cont);
1122 }
1123
1124
1125 void InstructionSelector::VisitFloat64LessThan(Node* node) {
1126 FlagsContinuation cont(kUnorderedLessThan, node);
1127 VisitFloat64Compare(this, node, &cont);
1128 }
1129
1130
1131 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
1132 FlagsContinuation cont(kUnorderedLessThanOrEqual, node);
1133 VisitFloat64Compare(this, node, &cont);
963 } 1134 }
964 1135
965 } // namespace compiler 1136 } // namespace compiler
966 } // namespace internal 1137 } // namespace internal
967 } // namespace v8 1138 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/compiler/arm64/instruction-selector-arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698