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 | 7 |
8 namespace v8 { | 8 namespace v8 { |
9 namespace internal { | 9 namespace internal { |
10 namespace compiler { | 10 namespace compiler { |
(...skipping 964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
975 } else { | 975 } else { |
976 DCHECK(cont->IsSet()); | 976 DCHECK(cont->IsSet()); |
977 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | 977 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); |
978 } | 978 } |
979 } | 979 } |
980 | 980 |
981 | 981 |
982 // Shared routine for multiple word compare operations. | 982 // Shared routine for multiple word compare operations. |
983 static void VisitWordCompare(InstructionSelector* selector, Node* node, | 983 static void VisitWordCompare(InstructionSelector* selector, Node* node, |
984 InstructionCode opcode, FlagsContinuation* cont, | 984 InstructionCode opcode, FlagsContinuation* cont, |
985 bool commutative) { | 985 bool commutative, ImmediateMode immediate_mode) { |
986 Arm64OperandGenerator g(selector); | 986 Arm64OperandGenerator g(selector); |
987 Node* left = node->InputAt(0); | 987 Node* left = node->InputAt(0); |
988 Node* right = node->InputAt(1); | 988 Node* right = node->InputAt(1); |
989 | 989 |
990 // Match immediates on left or right side of comparison. | 990 // Match immediates on left or right side of comparison. |
991 if (g.CanBeImmediate(right, kArithmeticImm)) { | 991 if (g.CanBeImmediate(right, immediate_mode)) { |
992 VisitCompare(selector, opcode, g.UseRegister(left), g.UseImmediate(right), | 992 VisitCompare(selector, opcode, g.UseRegister(left), g.UseImmediate(right), |
993 cont); | 993 cont); |
994 } else if (g.CanBeImmediate(left, kArithmeticImm)) { | 994 } else if (g.CanBeImmediate(left, immediate_mode)) { |
995 if (!commutative) cont->Commute(); | 995 if (!commutative) cont->Commute(); |
996 VisitCompare(selector, opcode, g.UseRegister(right), g.UseImmediate(left), | 996 VisitCompare(selector, opcode, g.UseRegister(right), g.UseImmediate(left), |
997 cont); | 997 cont); |
998 } else { | 998 } else { |
999 VisitCompare(selector, opcode, g.UseRegister(left), g.UseRegister(right), | 999 VisitCompare(selector, opcode, g.UseRegister(left), g.UseRegister(right), |
1000 cont); | 1000 cont); |
1001 } | 1001 } |
1002 } | 1002 } |
1003 | 1003 |
1004 | 1004 |
1005 static void VisitWord32Compare(InstructionSelector* selector, Node* node, | 1005 static void VisitWord32Compare(InstructionSelector* selector, Node* node, |
1006 FlagsContinuation* cont) { | 1006 FlagsContinuation* cont) { |
1007 VisitWordCompare(selector, node, kArm64Cmp32, cont, false); | 1007 VisitWordCompare(selector, node, kArm64Cmp32, cont, false, kArithmeticImm); |
1008 } | 1008 } |
1009 | 1009 |
1010 | 1010 |
1011 static void VisitWordTest(InstructionSelector* selector, Node* node, | 1011 static void VisitWordTest(InstructionSelector* selector, Node* node, |
1012 InstructionCode opcode, FlagsContinuation* cont) { | 1012 InstructionCode opcode, FlagsContinuation* cont) { |
1013 Arm64OperandGenerator g(selector); | 1013 Arm64OperandGenerator g(selector); |
1014 VisitCompare(selector, opcode, g.UseRegister(node), g.UseRegister(node), | 1014 VisitCompare(selector, opcode, g.UseRegister(node), g.UseRegister(node), |
1015 cont); | 1015 cont); |
1016 } | 1016 } |
1017 | 1017 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1091 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); | 1091 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); |
1092 return VisitWord32Compare(this, value, &cont); | 1092 return VisitWord32Compare(this, value, &cont); |
1093 case IrOpcode::kUint32LessThan: | 1093 case IrOpcode::kUint32LessThan: |
1094 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); | 1094 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); |
1095 return VisitWord32Compare(this, value, &cont); | 1095 return VisitWord32Compare(this, value, &cont); |
1096 case IrOpcode::kUint32LessThanOrEqual: | 1096 case IrOpcode::kUint32LessThanOrEqual: |
1097 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); | 1097 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); |
1098 return VisitWord32Compare(this, value, &cont); | 1098 return VisitWord32Compare(this, value, &cont); |
1099 case IrOpcode::kWord64Equal: | 1099 case IrOpcode::kWord64Equal: |
1100 cont.OverwriteAndNegateIfEqual(kEqual); | 1100 cont.OverwriteAndNegateIfEqual(kEqual); |
1101 return VisitWordCompare(this, value, kArm64Cmp, &cont, false); | 1101 return VisitWordCompare(this, value, kArm64Cmp, &cont, false, |
| 1102 kArithmeticImm); |
1102 case IrOpcode::kInt64LessThan: | 1103 case IrOpcode::kInt64LessThan: |
1103 cont.OverwriteAndNegateIfEqual(kSignedLessThan); | 1104 cont.OverwriteAndNegateIfEqual(kSignedLessThan); |
1104 return VisitWordCompare(this, value, kArm64Cmp, &cont, false); | 1105 return VisitWordCompare(this, value, kArm64Cmp, &cont, false, |
| 1106 kArithmeticImm); |
1105 case IrOpcode::kInt64LessThanOrEqual: | 1107 case IrOpcode::kInt64LessThanOrEqual: |
1106 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); | 1108 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); |
1107 return VisitWordCompare(this, value, kArm64Cmp, &cont, false); | 1109 return VisitWordCompare(this, value, kArm64Cmp, &cont, false, |
| 1110 kArithmeticImm); |
1108 case IrOpcode::kUint64LessThan: | 1111 case IrOpcode::kUint64LessThan: |
1109 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); | 1112 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); |
1110 return VisitWordCompare(this, value, kArm64Cmp, &cont, false); | 1113 return VisitWordCompare(this, value, kArm64Cmp, &cont, false, |
| 1114 kArithmeticImm); |
1111 case IrOpcode::kFloat64Equal: | 1115 case IrOpcode::kFloat64Equal: |
1112 cont.OverwriteAndNegateIfEqual(kUnorderedEqual); | 1116 cont.OverwriteAndNegateIfEqual(kUnorderedEqual); |
1113 return VisitFloat64Compare(this, value, &cont); | 1117 return VisitFloat64Compare(this, value, &cont); |
1114 case IrOpcode::kFloat64LessThan: | 1118 case IrOpcode::kFloat64LessThan: |
1115 cont.OverwriteAndNegateIfEqual(kUnorderedLessThan); | 1119 cont.OverwriteAndNegateIfEqual(kUnorderedLessThan); |
1116 return VisitFloat64Compare(this, value, &cont); | 1120 return VisitFloat64Compare(this, value, &cont); |
1117 case IrOpcode::kFloat64LessThanOrEqual: | 1121 case IrOpcode::kFloat64LessThanOrEqual: |
1118 cont.OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual); | 1122 cont.OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual); |
1119 return VisitFloat64Compare(this, value, &cont); | 1123 return VisitFloat64Compare(this, value, &cont); |
1120 case IrOpcode::kProjection: | 1124 case IrOpcode::kProjection: |
(...skipping 17 matching lines...) Expand all Loading... |
1138 cont.OverwriteAndNegateIfEqual(kOverflow); | 1142 cont.OverwriteAndNegateIfEqual(kOverflow); |
1139 return VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, | 1143 return VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, |
1140 kArithmeticImm, &cont); | 1144 kArithmeticImm, &cont); |
1141 default: | 1145 default: |
1142 break; | 1146 break; |
1143 } | 1147 } |
1144 } | 1148 } |
1145 } | 1149 } |
1146 break; | 1150 break; |
1147 case IrOpcode::kInt32Add: | 1151 case IrOpcode::kInt32Add: |
1148 return VisitWordCompare(this, value, kArm64Cmn32, &cont, true); | 1152 return VisitWordCompare(this, value, kArm64Cmn32, &cont, true, |
| 1153 kArithmeticImm); |
1149 case IrOpcode::kInt32Sub: | 1154 case IrOpcode::kInt32Sub: |
1150 return VisitWordCompare(this, value, kArm64Cmp32, &cont, false); | 1155 return VisitWordCompare(this, value, kArm64Cmp32, &cont, false, |
| 1156 kArithmeticImm); |
1151 case IrOpcode::kWord32And: | 1157 case IrOpcode::kWord32And: |
1152 return VisitWordCompare(this, value, kArm64Tst32, &cont, true); | 1158 return VisitWordCompare(this, value, kArm64Tst32, &cont, true, |
| 1159 kLogical32Imm); |
1153 default: | 1160 default: |
1154 break; | 1161 break; |
1155 } | 1162 } |
1156 } | 1163 } |
1157 | 1164 |
1158 // Branch could not be combined with a compare, emit compare against 0. | 1165 // Branch could not be combined with a compare, emit compare against 0. |
1159 VisitWord32Test(this, value, &cont); | 1166 VisitWord32Test(this, value, &cont); |
1160 } | 1167 } |
1161 | 1168 |
1162 | 1169 |
1163 void InstructionSelector::VisitWord32Equal(Node* const node) { | 1170 void InstructionSelector::VisitWord32Equal(Node* const node) { |
1164 Node* const user = node; | 1171 Node* const user = node; |
1165 FlagsContinuation cont(kEqual, node); | 1172 FlagsContinuation cont(kEqual, node); |
1166 Int32BinopMatcher m(user); | 1173 Int32BinopMatcher m(user); |
1167 if (m.right().Is(0)) { | 1174 if (m.right().Is(0)) { |
1168 Node* const value = m.left().node(); | 1175 Node* const value = m.left().node(); |
1169 if (CanCover(user, value)) { | 1176 if (CanCover(user, value)) { |
1170 switch (value->opcode()) { | 1177 switch (value->opcode()) { |
1171 case IrOpcode::kInt32Add: | 1178 case IrOpcode::kInt32Add: |
1172 return VisitWordCompare(this, value, kArm64Cmn32, &cont, true); | 1179 return VisitWordCompare(this, value, kArm64Cmn32, &cont, true, |
| 1180 kArithmeticImm); |
1173 case IrOpcode::kInt32Sub: | 1181 case IrOpcode::kInt32Sub: |
1174 return VisitWordCompare(this, value, kArm64Cmp32, &cont, false); | 1182 return VisitWordCompare(this, value, kArm64Cmp32, &cont, false, |
| 1183 kArithmeticImm); |
1175 case IrOpcode::kWord32And: | 1184 case IrOpcode::kWord32And: |
1176 return VisitWordCompare(this, value, kArm64Tst32, &cont, true); | 1185 return VisitWordCompare(this, value, kArm64Tst32, &cont, true, |
| 1186 kLogical32Imm); |
1177 default: | 1187 default: |
1178 break; | 1188 break; |
1179 } | 1189 } |
1180 return VisitWord32Test(this, value, &cont); | 1190 return VisitWord32Test(this, value, &cont); |
1181 } | 1191 } |
1182 } | 1192 } |
1183 VisitWord32Compare(this, node, &cont); | 1193 VisitWord32Compare(this, node, &cont); |
1184 } | 1194 } |
1185 | 1195 |
1186 | 1196 |
(...skipping 23 matching lines...) Expand all Loading... |
1210 | 1220 |
1211 void InstructionSelector::VisitWord64Equal(Node* const node) { | 1221 void InstructionSelector::VisitWord64Equal(Node* const node) { |
1212 Node* const user = node; | 1222 Node* const user = node; |
1213 FlagsContinuation cont(kEqual, node); | 1223 FlagsContinuation cont(kEqual, node); |
1214 Int64BinopMatcher m(user); | 1224 Int64BinopMatcher m(user); |
1215 if (m.right().Is(0)) { | 1225 if (m.right().Is(0)) { |
1216 Node* const value = m.left().node(); | 1226 Node* const value = m.left().node(); |
1217 if (CanCover(user, value)) { | 1227 if (CanCover(user, value)) { |
1218 switch (value->opcode()) { | 1228 switch (value->opcode()) { |
1219 case IrOpcode::kWord64And: | 1229 case IrOpcode::kWord64And: |
1220 return VisitWordCompare(this, value, kArm64Tst, &cont, true); | 1230 return VisitWordCompare(this, value, kArm64Tst, &cont, true, |
| 1231 kLogical64Imm); |
1221 default: | 1232 default: |
1222 break; | 1233 break; |
1223 } | 1234 } |
1224 return VisitWord64Test(this, value, &cont); | 1235 return VisitWord64Test(this, value, &cont); |
1225 } | 1236 } |
1226 } | 1237 } |
1227 VisitWordCompare(this, node, kArm64Cmp, &cont, false); | 1238 VisitWordCompare(this, node, kArm64Cmp, &cont, false, kArithmeticImm); |
1228 } | 1239 } |
1229 | 1240 |
1230 | 1241 |
1231 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { | 1242 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { |
1232 if (Node* ovf = node->FindProjection(1)) { | 1243 if (Node* ovf = node->FindProjection(1)) { |
1233 FlagsContinuation cont(kOverflow, ovf); | 1244 FlagsContinuation cont(kOverflow, ovf); |
1234 return VisitBinop<Int32BinopMatcher>(this, node, kArm64Add32, | 1245 return VisitBinop<Int32BinopMatcher>(this, node, kArm64Add32, |
1235 kArithmeticImm, &cont); | 1246 kArithmeticImm, &cont); |
1236 } | 1247 } |
1237 FlagsContinuation cont; | 1248 FlagsContinuation cont; |
1238 VisitBinop<Int32BinopMatcher>(this, node, kArm64Add32, kArithmeticImm, &cont); | 1249 VisitBinop<Int32BinopMatcher>(this, node, kArm64Add32, kArithmeticImm, &cont); |
1239 } | 1250 } |
1240 | 1251 |
1241 | 1252 |
1242 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { | 1253 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { |
1243 if (Node* ovf = node->FindProjection(1)) { | 1254 if (Node* ovf = node->FindProjection(1)) { |
1244 FlagsContinuation cont(kOverflow, ovf); | 1255 FlagsContinuation cont(kOverflow, ovf); |
1245 return VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, | 1256 return VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, |
1246 kArithmeticImm, &cont); | 1257 kArithmeticImm, &cont); |
1247 } | 1258 } |
1248 FlagsContinuation cont; | 1259 FlagsContinuation cont; |
1249 VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, kArithmeticImm, &cont); | 1260 VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, kArithmeticImm, &cont); |
1250 } | 1261 } |
1251 | 1262 |
1252 | 1263 |
1253 void InstructionSelector::VisitInt64LessThan(Node* node) { | 1264 void InstructionSelector::VisitInt64LessThan(Node* node) { |
1254 FlagsContinuation cont(kSignedLessThan, node); | 1265 FlagsContinuation cont(kSignedLessThan, node); |
1255 VisitWordCompare(this, node, kArm64Cmp, &cont, false); | 1266 VisitWordCompare(this, node, kArm64Cmp, &cont, false, kArithmeticImm); |
1256 } | 1267 } |
1257 | 1268 |
1258 | 1269 |
1259 void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) { | 1270 void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) { |
1260 FlagsContinuation cont(kSignedLessThanOrEqual, node); | 1271 FlagsContinuation cont(kSignedLessThanOrEqual, node); |
1261 VisitWordCompare(this, node, kArm64Cmp, &cont, false); | 1272 VisitWordCompare(this, node, kArm64Cmp, &cont, false, kArithmeticImm); |
1262 } | 1273 } |
1263 | 1274 |
1264 | 1275 |
1265 void InstructionSelector::VisitUint64LessThan(Node* node) { | 1276 void InstructionSelector::VisitUint64LessThan(Node* node) { |
1266 FlagsContinuation cont(kUnsignedLessThan, node); | 1277 FlagsContinuation cont(kUnsignedLessThan, node); |
1267 VisitWordCompare(this, node, kArm64Cmp, &cont, false); | 1278 VisitWordCompare(this, node, kArm64Cmp, &cont, false, kArithmeticImm); |
1268 } | 1279 } |
1269 | 1280 |
1270 | 1281 |
1271 void InstructionSelector::VisitFloat64Equal(Node* node) { | 1282 void InstructionSelector::VisitFloat64Equal(Node* node) { |
1272 FlagsContinuation cont(kUnorderedEqual, node); | 1283 FlagsContinuation cont(kUnorderedEqual, node); |
1273 VisitFloat64Compare(this, node, &cont); | 1284 VisitFloat64Compare(this, node, &cont); |
1274 } | 1285 } |
1275 | 1286 |
1276 | 1287 |
1277 void InstructionSelector::VisitFloat64LessThan(Node* node) { | 1288 void InstructionSelector::VisitFloat64LessThan(Node* node) { |
1278 FlagsContinuation cont(kUnorderedLessThan, node); | 1289 FlagsContinuation cont(kUnorderedLessThan, node); |
1279 VisitFloat64Compare(this, node, &cont); | 1290 VisitFloat64Compare(this, node, &cont); |
1280 } | 1291 } |
1281 | 1292 |
1282 | 1293 |
1283 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { | 1294 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { |
1284 FlagsContinuation cont(kUnorderedLessThanOrEqual, node); | 1295 FlagsContinuation cont(kUnorderedLessThanOrEqual, node); |
1285 VisitFloat64Compare(this, node, &cont); | 1296 VisitFloat64Compare(this, node, &cont); |
1286 } | 1297 } |
1287 | 1298 |
1288 } // namespace compiler | 1299 } // namespace compiler |
1289 } // namespace internal | 1300 } // namespace internal |
1290 } // namespace v8 | 1301 } // namespace v8 |
OLD | NEW |