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

Side by Side Diff: src/compiler/arm/instruction-selector-arm.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 | « no previous file | src/compiler/ia32/instruction-selector-ia32.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 882 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 DCHECK(cont->IsSet()); 893 DCHECK(cont->IsSet());
894 selector->Emit( 894 selector->Emit(
895 cont->Encode(kArmVcmpF64), g.DefineAsRegister(cont->result()), 895 cont->Encode(kArmVcmpF64), g.DefineAsRegister(cont->result()),
896 g.UseRegister(m.left().node()), g.UseRegister(m.right().node())); 896 g.UseRegister(m.left().node()), g.UseRegister(m.right().node()));
897 } 897 }
898 } 898 }
899 899
900 900
901 // Shared routine for multiple word compare operations. 901 // Shared routine for multiple word compare operations.
902 void VisitWordCompare(InstructionSelector* selector, Node* node, 902 void VisitWordCompare(InstructionSelector* selector, Node* node,
903 InstructionCode opcode, FlagsContinuation* cont, 903 InstructionCode opcode, FlagsContinuation* cont) {
904 bool commutative) {
905 ArmOperandGenerator g(selector); 904 ArmOperandGenerator g(selector);
906 Int32BinopMatcher m(node); 905 Int32BinopMatcher m(node);
907 InstructionOperand* inputs[5]; 906 InstructionOperand* inputs[5];
908 size_t input_count = 0; 907 size_t input_count = 0;
909 InstructionOperand* outputs[1]; 908 InstructionOperand* outputs[1];
910 size_t output_count = 0; 909 size_t output_count = 0;
911 910
912 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(), 911 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
913 &input_count, &inputs[1])) { 912 &input_count, &inputs[1])) {
914 inputs[0] = g.UseRegister(m.left().node()); 913 inputs[0] = g.UseRegister(m.left().node());
915 input_count++; 914 input_count++;
916 } else if (TryMatchImmediateOrShift(selector, &opcode, m.left().node(), 915 } else if (TryMatchImmediateOrShift(selector, &opcode, m.left().node(),
917 &input_count, &inputs[1])) { 916 &input_count, &inputs[1])) {
918 if (!commutative) cont->Commute(); 917 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
919 inputs[0] = g.UseRegister(m.right().node()); 918 inputs[0] = g.UseRegister(m.right().node());
920 input_count++; 919 input_count++;
921 } else { 920 } else {
922 opcode |= AddressingModeField::encode(kMode_Operand2_R); 921 opcode |= AddressingModeField::encode(kMode_Operand2_R);
923 inputs[input_count++] = g.UseRegister(m.left().node()); 922 inputs[input_count++] = g.UseRegister(m.left().node());
924 inputs[input_count++] = g.UseRegister(m.right().node()); 923 inputs[input_count++] = g.UseRegister(m.right().node());
925 } 924 }
926 925
927 if (cont->IsBranch()) { 926 if (cont->IsBranch()) {
928 inputs[input_count++] = g.Label(cont->true_block()); 927 inputs[input_count++] = g.Label(cont->true_block());
929 inputs[input_count++] = g.Label(cont->false_block()); 928 inputs[input_count++] = g.Label(cont->false_block());
930 } else { 929 } else {
931 DCHECK(cont->IsSet()); 930 DCHECK(cont->IsSet());
932 outputs[output_count++] = g.DefineAsRegister(cont->result()); 931 outputs[output_count++] = g.DefineAsRegister(cont->result());
933 } 932 }
934 933
935 DCHECK_NE(0, input_count); 934 DCHECK_NE(0, input_count);
936 DCHECK_GE(arraysize(inputs), input_count); 935 DCHECK_GE(arraysize(inputs), input_count);
937 DCHECK_GE(arraysize(outputs), output_count); 936 DCHECK_GE(arraysize(outputs), output_count);
938 937
939 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, 938 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count,
940 outputs, input_count, inputs); 939 outputs, input_count, inputs);
941 if (cont->IsBranch()) instr->MarkAsControl(); 940 if (cont->IsBranch()) instr->MarkAsControl();
942 } 941 }
943 942
944 943
945 void VisitWordCompare(InstructionSelector* selector, Node* node, 944 void VisitWordCompare(InstructionSelector* selector, Node* node,
946 FlagsContinuation* cont) { 945 FlagsContinuation* cont) {
947 VisitWordCompare(selector, node, kArmCmp, cont, false); 946 VisitWordCompare(selector, node, kArmCmp, cont);
948 } 947 }
949 948
950 949
951 void VisitWordTest(InstructionSelector* selector, Node* node, 950 // Shared routine for word comparisons against zero.
952 FlagsContinuation* cont) { 951 void VisitWordCompareZero(InstructionSelector* selector, Node* user,
953 ArmOperandGenerator g(selector); 952 Node* value, FlagsContinuation* cont) {
954 InstructionCode opcode = 953 while (selector->CanCover(user, value)) {
955 cont->Encode(kArmTst) | AddressingModeField::encode(kMode_Operand2_R);
956 if (cont->IsBranch()) {
957 selector->Emit(opcode, nullptr, g.UseRegister(node), g.UseRegister(node),
958 g.Label(cont->true_block()),
959 g.Label(cont->false_block()))->MarkAsControl();
960 } else {
961 selector->Emit(opcode, g.DefineAsRegister(cont->result()),
962 g.UseRegister(node), g.UseRegister(node));
963 }
964 }
965
966 } // namespace
967
968
969 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
970 BasicBlock* fbranch) {
971 ArmOperandGenerator g(this);
972 Node* user = branch;
973 Node* value = branch->InputAt(0);
974
975 FlagsContinuation cont(kNotEqual, tbranch, fbranch);
976
977 // If we can fall through to the true block, invert the branch.
978 if (IsNextInAssemblyOrder(tbranch)) {
979 cont.Negate();
980 cont.SwapBlocks();
981 }
982
983 // Try to combine with comparisons against 0 by simply inverting the branch.
984 while (CanCover(user, value) && value->opcode() == IrOpcode::kWord32Equal) {
985 Int32BinopMatcher m(value);
986 if (m.right().Is(0)) {
987 user = value;
988 value = m.left().node();
989 cont.Negate();
990 } else {
991 break;
992 }
993 }
994
995 // Try to combine the branch with a comparison.
996 if (CanCover(user, value)) {
997 switch (value->opcode()) { 954 switch (value->opcode()) {
998 case IrOpcode::kWord32Equal: 955 case IrOpcode::kWord32Equal: {
999 cont.OverwriteAndNegateIfEqual(kEqual); 956 // Combine with comparisons against 0 by simply inverting the
1000 return VisitWordCompare(this, value, &cont); 957 // continuation.
958 Int32BinopMatcher m(value);
959 if (m.right().Is(0)) {
960 user = value;
961 value = m.left().node();
962 cont->Negate();
963 continue;
964 }
965 cont->OverwriteAndNegateIfEqual(kEqual);
966 return VisitWordCompare(selector, value, cont);
967 }
1001 case IrOpcode::kInt32LessThan: 968 case IrOpcode::kInt32LessThan:
1002 cont.OverwriteAndNegateIfEqual(kSignedLessThan); 969 cont->OverwriteAndNegateIfEqual(kSignedLessThan);
1003 return VisitWordCompare(this, value, &cont); 970 return VisitWordCompare(selector, value, cont);
1004 case IrOpcode::kInt32LessThanOrEqual: 971 case IrOpcode::kInt32LessThanOrEqual:
1005 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); 972 cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
1006 return VisitWordCompare(this, value, &cont); 973 return VisitWordCompare(selector, value, cont);
1007 case IrOpcode::kUint32LessThan: 974 case IrOpcode::kUint32LessThan:
1008 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); 975 cont->OverwriteAndNegateIfEqual(kUnsignedLessThan);
1009 return VisitWordCompare(this, value, &cont); 976 return VisitWordCompare(selector, value, cont);
1010 case IrOpcode::kUint32LessThanOrEqual: 977 case IrOpcode::kUint32LessThanOrEqual:
1011 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); 978 cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
1012 return VisitWordCompare(this, value, &cont); 979 return VisitWordCompare(selector, value, cont);
1013 case IrOpcode::kFloat64Equal: 980 case IrOpcode::kFloat64Equal:
1014 cont.OverwriteAndNegateIfEqual(kUnorderedEqual); 981 cont->OverwriteAndNegateIfEqual(kUnorderedEqual);
1015 return VisitFloat64Compare(this, value, &cont); 982 return VisitFloat64Compare(selector, value, cont);
1016 case IrOpcode::kFloat64LessThan: 983 case IrOpcode::kFloat64LessThan:
1017 cont.OverwriteAndNegateIfEqual(kUnorderedLessThan); 984 cont->OverwriteAndNegateIfEqual(kUnorderedLessThan);
1018 return VisitFloat64Compare(this, value, &cont); 985 return VisitFloat64Compare(selector, value, cont);
1019 case IrOpcode::kFloat64LessThanOrEqual: 986 case IrOpcode::kFloat64LessThanOrEqual:
1020 cont.OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual); 987 cont->OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual);
1021 return VisitFloat64Compare(this, value, &cont); 988 return VisitFloat64Compare(selector, value, cont);
1022 case IrOpcode::kProjection: 989 case IrOpcode::kProjection:
1023 // Check if this is the overflow output projection of an 990 // Check if this is the overflow output projection of an
1024 // <Operation>WithOverflow node. 991 // <Operation>WithOverflow node.
1025 if (OpParameter<size_t>(value) == 1u) { 992 if (OpParameter<size_t>(value) == 1u) {
1026 // We cannot combine the <Operation>WithOverflow with this branch 993 // We cannot combine the <Operation>WithOverflow with this branch
1027 // unless the 0th projection (the use of the actual value of the 994 // unless the 0th projection (the use of the actual value of the
1028 // <Operation> is either NULL, which means there's no use of the 995 // <Operation> is either NULL, which means there's no use of the
1029 // actual value, or was already defined, which means it is scheduled 996 // actual value, or was already defined, which means it is scheduled
1030 // *AFTER* this branch). 997 // *AFTER* this branch).
1031 Node* node = value->InputAt(0); 998 Node* const node = value->InputAt(0);
1032 Node* result = node->FindProjection(0); 999 Node* const result = node->FindProjection(0);
1033 if (!result || IsDefined(result)) { 1000 if (!result || selector->IsDefined(result)) {
1034 switch (node->opcode()) { 1001 switch (node->opcode()) {
1035 case IrOpcode::kInt32AddWithOverflow: 1002 case IrOpcode::kInt32AddWithOverflow:
1036 cont.OverwriteAndNegateIfEqual(kOverflow); 1003 cont->OverwriteAndNegateIfEqual(kOverflow);
1037 return VisitBinop(this, node, kArmAdd, kArmAdd, &cont); 1004 return VisitBinop(selector, node, kArmAdd, kArmAdd, cont);
1038 case IrOpcode::kInt32SubWithOverflow: 1005 case IrOpcode::kInt32SubWithOverflow:
1039 cont.OverwriteAndNegateIfEqual(kOverflow); 1006 cont->OverwriteAndNegateIfEqual(kOverflow);
1040 return VisitBinop(this, node, kArmSub, kArmRsb, &cont); 1007 return VisitBinop(selector, node, kArmSub, kArmRsb, cont);
1041 default: 1008 default:
1042 break; 1009 break;
1043 } 1010 }
1044 } 1011 }
1045 } 1012 }
1046 break; 1013 break;
1047 case IrOpcode::kInt32Add: 1014 case IrOpcode::kInt32Add:
1048 return VisitWordCompare(this, value, kArmCmn, &cont, true); 1015 return VisitWordCompare(selector, value, kArmCmn, cont);
1049 case IrOpcode::kInt32Sub: 1016 case IrOpcode::kInt32Sub:
1050 return VisitWordCompare(this, value, kArmCmp, &cont, false); 1017 return VisitWordCompare(selector, value, kArmCmp, cont);
1051 case IrOpcode::kWord32And: 1018 case IrOpcode::kWord32And:
1052 return VisitWordCompare(this, value, kArmTst, &cont, true); 1019 return VisitWordCompare(selector, value, kArmTst, cont);
1053 case IrOpcode::kWord32Or: 1020 case IrOpcode::kWord32Or:
1054 return VisitBinop(this, value, kArmOrr, kArmOrr, &cont); 1021 return VisitBinop(selector, value, kArmOrr, kArmOrr, cont);
1055 case IrOpcode::kWord32Xor: 1022 case IrOpcode::kWord32Xor:
1056 return VisitWordCompare(this, value, kArmTeq, &cont, true); 1023 return VisitWordCompare(selector, value, kArmTeq, cont);
1057 case IrOpcode::kWord32Sar: 1024 case IrOpcode::kWord32Sar:
1058 return VisitShift(this, value, TryMatchASR, &cont); 1025 return VisitShift(selector, value, TryMatchASR, cont);
1059 case IrOpcode::kWord32Shl: 1026 case IrOpcode::kWord32Shl:
1060 return VisitShift(this, value, TryMatchLSL, &cont); 1027 return VisitShift(selector, value, TryMatchLSL, cont);
1061 case IrOpcode::kWord32Shr: 1028 case IrOpcode::kWord32Shr:
1062 return VisitShift(this, value, TryMatchLSR, &cont); 1029 return VisitShift(selector, value, TryMatchLSR, cont);
1063 case IrOpcode::kWord32Ror: 1030 case IrOpcode::kWord32Ror:
1064 return VisitShift(this, value, TryMatchROR, &cont); 1031 return VisitShift(selector, value, TryMatchROR, cont);
1065 default: 1032 default:
1066 break; 1033 break;
1067 } 1034 }
1035 break;
1068 } 1036 }
1069 1037
1070 // Branch could not be combined with a compare, emit compare against 0. 1038 // Continuation could not be combined with a compare, emit compare against 0.
1071 return VisitWordTest(this, value, &cont); 1039 ArmOperandGenerator g(selector);
1040 InstructionCode const opcode =
1041 cont->Encode(kArmTst) | AddressingModeField::encode(kMode_Operand2_R);
1042 InstructionOperand* const value_operand = g.UseRegister(value);
1043 if (cont->IsBranch()) {
1044 selector->Emit(opcode, nullptr, value_operand, value_operand,
1045 g.Label(cont->true_block()),
1046 g.Label(cont->false_block()))->MarkAsControl();
1047 } else {
1048 selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand,
1049 value_operand);
1050 }
1051 }
1052
1053 } // namespace
1054
1055
1056 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
1057 BasicBlock* fbranch) {
1058 FlagsContinuation cont(kNotEqual, tbranch, fbranch);
1059 if (IsNextInAssemblyOrder(tbranch)) { // We can fallthru to the true block.
1060 cont.Negate();
1061 cont.SwapBlocks();
1062 }
1063 VisitWordCompareZero(this, branch, branch->InputAt(0), &cont);
1072 } 1064 }
1073 1065
1074 1066
1075 void InstructionSelector::VisitWord32Equal(Node* const node) { 1067 void InstructionSelector::VisitWord32Equal(Node* const node) {
1076 Node* const user = node;
1077 FlagsContinuation cont(kEqual, node); 1068 FlagsContinuation cont(kEqual, node);
1078 Int32BinopMatcher m(user); 1069 Int32BinopMatcher m(node);
1079 if (m.right().Is(0)) { 1070 if (m.right().Is(0)) {
1080 Node* const value = m.left().node(); 1071 return VisitWordCompareZero(this, m.node(), m.left().node(), &cont);
1081 if (CanCover(user, value)) {
1082 switch (value->opcode()) {
1083 case IrOpcode::kInt32Add:
1084 return VisitWordCompare(this, value, kArmCmn, &cont, true);
1085 case IrOpcode::kInt32Sub:
1086 return VisitWordCompare(this, value, kArmCmp, &cont, false);
1087 case IrOpcode::kWord32And:
1088 return VisitWordCompare(this, value, kArmTst, &cont, true);
1089 case IrOpcode::kWord32Or:
1090 return VisitBinop(this, value, kArmOrr, kArmOrr, &cont);
1091 case IrOpcode::kWord32Xor:
1092 return VisitWordCompare(this, value, kArmTeq, &cont, true);
1093 case IrOpcode::kWord32Sar:
1094 return VisitShift(this, value, TryMatchASR, &cont);
1095 case IrOpcode::kWord32Shl:
1096 return VisitShift(this, value, TryMatchLSL, &cont);
1097 case IrOpcode::kWord32Shr:
1098 return VisitShift(this, value, TryMatchLSR, &cont);
1099 case IrOpcode::kWord32Ror:
1100 return VisitShift(this, value, TryMatchROR, &cont);
1101 default:
1102 break;
1103 }
1104 return VisitWordTest(this, value, &cont);
1105 }
1106 } 1072 }
1107 VisitWordCompare(this, node, &cont); 1073 VisitWordCompare(this, node, &cont);
1108 } 1074 }
1109 1075
1110 1076
1111 void InstructionSelector::VisitInt32LessThan(Node* node) { 1077 void InstructionSelector::VisitInt32LessThan(Node* node) {
1112 FlagsContinuation cont(kSignedLessThan, node); 1078 FlagsContinuation cont(kSignedLessThan, node);
1113 VisitWordCompare(this, node, &cont); 1079 VisitWordCompare(this, node, &cont);
1114 } 1080 }
1115 1081
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1165 1131
1166 1132
1167 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { 1133 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
1168 FlagsContinuation cont(kUnorderedLessThanOrEqual, node); 1134 FlagsContinuation cont(kUnorderedLessThanOrEqual, node);
1169 VisitFloat64Compare(this, node, &cont); 1135 VisitFloat64Compare(this, node, &cont);
1170 } 1136 }
1171 1137
1172 } // namespace compiler 1138 } // namespace compiler
1173 } // namespace internal 1139 } // namespace internal
1174 } // namespace v8 1140 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/compiler/ia32/instruction-selector-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698