| 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 <algorithm> | 5 #include <algorithm> |
| 6 | 6 |
| 7 #include "src/compiler/instruction-selector-impl.h" | 7 #include "src/compiler/instruction-selector-impl.h" |
| 8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
| 9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
| 10 | 10 |
| (...skipping 969 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 980 // Emit the call instruction. | 980 // Emit the call instruction. |
| 981 InstructionOperand* first_output = | 981 InstructionOperand* first_output = |
| 982 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL; | 982 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL; |
| 983 Instruction* call_instr = | 983 Instruction* call_instr = |
| 984 Emit(opcode, buffer.outputs.size(), first_output, | 984 Emit(opcode, buffer.outputs.size(), first_output, |
| 985 buffer.instruction_args.size(), &buffer.instruction_args.front()); | 985 buffer.instruction_args.size(), &buffer.instruction_args.front()); |
| 986 call_instr->MarkAsCall(); | 986 call_instr->MarkAsCall(); |
| 987 } | 987 } |
| 988 | 988 |
| 989 | 989 |
| 990 namespace { |
| 991 |
| 990 // Shared routine for multiple compare operations. | 992 // Shared routine for multiple compare operations. |
| 991 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 993 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
| 992 InstructionOperand left, InstructionOperand right, | 994 InstructionOperand left, InstructionOperand right, |
| 993 FlagsContinuation* cont) { | 995 FlagsContinuation* cont) { |
| 994 X64OperandGenerator g(selector); | 996 X64OperandGenerator g(selector); |
| 995 opcode = cont->Encode(opcode); | 997 opcode = cont->Encode(opcode); |
| 996 if (cont->IsBranch()) { | 998 if (cont->IsBranch()) { |
| 997 selector->Emit(opcode, g.NoOutput(), left, right, | 999 selector->Emit(opcode, g.NoOutput(), left, right, |
| 998 g.Label(cont->true_block()), | 1000 g.Label(cont->true_block()), |
| 999 g.Label(cont->false_block()))->MarkAsControl(); | 1001 g.Label(cont->false_block()))->MarkAsControl(); |
| 1000 } else { | 1002 } else { |
| 1001 DCHECK(cont->IsSet()); | 1003 DCHECK(cont->IsSet()); |
| 1002 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | 1004 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); |
| 1003 } | 1005 } |
| 1004 } | 1006 } |
| 1005 | 1007 |
| 1006 | 1008 |
| 1007 // Shared routine for multiple compare operations. | 1009 // Shared routine for multiple compare operations. |
| 1008 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1010 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
| 1009 Node* left, Node* right, FlagsContinuation* cont, | 1011 Node* left, Node* right, FlagsContinuation* cont, |
| 1010 bool commutative) { | 1012 bool commutative) { |
| 1011 X64OperandGenerator g(selector); | 1013 X64OperandGenerator g(selector); |
| 1012 if (commutative && g.CanBeBetterLeftOperand(right)) { | 1014 if (commutative && g.CanBeBetterLeftOperand(right)) { |
| 1013 std::swap(left, right); | 1015 std::swap(left, right); |
| 1014 } | 1016 } |
| 1015 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont); | 1017 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont); |
| 1016 } | 1018 } |
| 1017 | 1019 |
| 1018 | 1020 |
| 1019 // Shared routine for multiple word compare operations. | 1021 // Shared routine for multiple word compare operations. |
| 1020 static void VisitWordCompare(InstructionSelector* selector, Node* node, | 1022 void VisitWordCompare(InstructionSelector* selector, Node* node, |
| 1021 InstructionCode opcode, FlagsContinuation* cont) { | 1023 InstructionCode opcode, FlagsContinuation* cont) { |
| 1022 X64OperandGenerator g(selector); | 1024 X64OperandGenerator g(selector); |
| 1023 Node* const left = node->InputAt(0); | 1025 Node* const left = node->InputAt(0); |
| 1024 Node* const right = node->InputAt(1); | 1026 Node* const right = node->InputAt(1); |
| 1025 | 1027 |
| 1026 // Match immediates on left or right side of comparison. | 1028 // Match immediates on left or right side of comparison. |
| 1027 if (g.CanBeImmediate(right)) { | 1029 if (g.CanBeImmediate(right)) { |
| 1028 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont); | 1030 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont); |
| 1029 } else if (g.CanBeImmediate(left)) { | 1031 } else if (g.CanBeImmediate(left)) { |
| 1030 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); | 1032 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); |
| 1031 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont); | 1033 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont); |
| 1032 } else { | 1034 } else { |
| 1033 VisitCompare(selector, opcode, left, right, cont, | 1035 VisitCompare(selector, opcode, left, right, cont, |
| 1034 node->op()->HasProperty(Operator::kCommutative)); | 1036 node->op()->HasProperty(Operator::kCommutative)); |
| 1035 } | 1037 } |
| 1036 } | 1038 } |
| 1037 | 1039 |
| 1038 | 1040 |
| 1041 // Shared routine for 64-bit word comparison operations. |
| 1042 void VisitWord64Compare(InstructionSelector* selector, Node* node, |
| 1043 FlagsContinuation* cont) { |
| 1044 X64OperandGenerator g(selector); |
| 1045 Int64BinopMatcher m(node); |
| 1046 if (m.left().IsLoad() && m.right().IsLoadStackPointer()) { |
| 1047 LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node()); |
| 1048 ExternalReference js_stack_limit = |
| 1049 ExternalReference::address_of_stack_limit(selector->isolate()); |
| 1050 if (mleft.object().Is(js_stack_limit) && mleft.index().Is(0)) { |
| 1051 // Compare(Load(js_stack_limit), LoadStackPointer) |
| 1052 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); |
| 1053 InstructionCode opcode = cont->Encode(kX64StackCheck); |
| 1054 if (cont->IsBranch()) { |
| 1055 selector->Emit(opcode, g.NoOutput(), g.Label(cont->true_block()), |
| 1056 g.Label(cont->false_block()))->MarkAsControl(); |
| 1057 } else { |
| 1058 DCHECK(cont->IsSet()); |
| 1059 selector->Emit(opcode, g.DefineAsRegister(cont->result())); |
| 1060 } |
| 1061 return; |
| 1062 } |
| 1063 } |
| 1064 VisitWordCompare(selector, node, kX64Cmp, cont); |
| 1065 } |
| 1066 |
| 1067 |
| 1039 // Shared routine for comparison with zero. | 1068 // Shared routine for comparison with zero. |
| 1040 static void VisitCompareZero(InstructionSelector* selector, Node* node, | 1069 void VisitCompareZero(InstructionSelector* selector, Node* node, |
| 1041 InstructionCode opcode, FlagsContinuation* cont) { | 1070 InstructionCode opcode, FlagsContinuation* cont) { |
| 1042 X64OperandGenerator g(selector); | 1071 X64OperandGenerator g(selector); |
| 1043 VisitCompare(selector, opcode, g.Use(node), g.TempImmediate(0), cont); | 1072 VisitCompare(selector, opcode, g.Use(node), g.TempImmediate(0), cont); |
| 1044 } | 1073 } |
| 1045 | 1074 |
| 1046 | 1075 |
| 1047 // Shared routine for multiple float64 compare operations (inputs commuted). | 1076 // Shared routine for multiple float64 compare operations (inputs commuted). |
| 1048 static void VisitFloat64Compare(InstructionSelector* selector, Node* node, | 1077 void VisitFloat64Compare(InstructionSelector* selector, Node* node, |
| 1049 FlagsContinuation* cont) { | 1078 FlagsContinuation* cont) { |
| 1050 Node* const left = node->InputAt(0); | 1079 Node* const left = node->InputAt(0); |
| 1051 Node* const right = node->InputAt(1); | 1080 Node* const right = node->InputAt(1); |
| 1052 VisitCompare(selector, kSSEFloat64Cmp, right, left, cont, false); | 1081 VisitCompare(selector, kSSEFloat64Cmp, right, left, cont, false); |
| 1053 } | 1082 } |
| 1054 | 1083 |
| 1084 } // namespace |
| 1085 |
| 1055 | 1086 |
| 1056 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 1087 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
| 1057 BasicBlock* fbranch) { | 1088 BasicBlock* fbranch) { |
| 1058 X64OperandGenerator g(this); | 1089 X64OperandGenerator g(this); |
| 1059 Node* user = branch; | 1090 Node* user = branch; |
| 1060 Node* value = branch->InputAt(0); | 1091 Node* value = branch->InputAt(0); |
| 1061 | 1092 |
| 1062 FlagsContinuation cont(kNotEqual, tbranch, fbranch); | 1093 FlagsContinuation cont(kNotEqual, tbranch, fbranch); |
| 1063 | 1094 |
| 1064 // Try to combine with comparisons against 0 by simply inverting the branch. | 1095 // Try to combine with comparisons against 0 by simply inverting the branch. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1086 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); | 1117 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); |
| 1087 return VisitWordCompare(this, value, kX64Cmp32, &cont); | 1118 return VisitWordCompare(this, value, kX64Cmp32, &cont); |
| 1088 case IrOpcode::kUint32LessThan: | 1119 case IrOpcode::kUint32LessThan: |
| 1089 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); | 1120 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); |
| 1090 return VisitWordCompare(this, value, kX64Cmp32, &cont); | 1121 return VisitWordCompare(this, value, kX64Cmp32, &cont); |
| 1091 case IrOpcode::kUint32LessThanOrEqual: | 1122 case IrOpcode::kUint32LessThanOrEqual: |
| 1092 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); | 1123 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); |
| 1093 return VisitWordCompare(this, value, kX64Cmp32, &cont); | 1124 return VisitWordCompare(this, value, kX64Cmp32, &cont); |
| 1094 case IrOpcode::kWord64Equal: | 1125 case IrOpcode::kWord64Equal: |
| 1095 cont.OverwriteAndNegateIfEqual(kEqual); | 1126 cont.OverwriteAndNegateIfEqual(kEqual); |
| 1096 return VisitWordCompare(this, value, kX64Cmp, &cont); | 1127 return VisitWord64Compare(this, value, &cont); |
| 1097 case IrOpcode::kInt64LessThan: | 1128 case IrOpcode::kInt64LessThan: |
| 1098 cont.OverwriteAndNegateIfEqual(kSignedLessThan); | 1129 cont.OverwriteAndNegateIfEqual(kSignedLessThan); |
| 1099 return VisitWordCompare(this, value, kX64Cmp, &cont); | 1130 return VisitWord64Compare(this, value, &cont); |
| 1100 case IrOpcode::kInt64LessThanOrEqual: | 1131 case IrOpcode::kInt64LessThanOrEqual: |
| 1101 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); | 1132 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); |
| 1102 return VisitWordCompare(this, value, kX64Cmp, &cont); | 1133 return VisitWord64Compare(this, value, &cont); |
| 1103 case IrOpcode::kUint64LessThan: | 1134 case IrOpcode::kUint64LessThan: |
| 1104 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); | 1135 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); |
| 1105 return VisitWordCompare(this, value, kX64Cmp, &cont); | 1136 return VisitWord64Compare(this, value, &cont); |
| 1106 case IrOpcode::kFloat64Equal: | 1137 case IrOpcode::kFloat64Equal: |
| 1107 cont.OverwriteAndNegateIfEqual(kUnorderedEqual); | 1138 cont.OverwriteAndNegateIfEqual(kUnorderedEqual); |
| 1108 return VisitFloat64Compare(this, value, &cont); | 1139 return VisitFloat64Compare(this, value, &cont); |
| 1109 case IrOpcode::kFloat64LessThan: | 1140 case IrOpcode::kFloat64LessThan: |
| 1110 cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThan); | 1141 cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThan); |
| 1111 return VisitFloat64Compare(this, value, &cont); | 1142 return VisitFloat64Compare(this, value, &cont); |
| 1112 case IrOpcode::kFloat64LessThanOrEqual: | 1143 case IrOpcode::kFloat64LessThanOrEqual: |
| 1113 cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual); | 1144 cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual); |
| 1114 return VisitFloat64Compare(this, value, &cont); | 1145 return VisitFloat64Compare(this, value, &cont); |
| 1115 case IrOpcode::kProjection: | 1146 case IrOpcode::kProjection: |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1133 return VisitBinop(this, node, kX64Sub32, &cont); | 1164 return VisitBinop(this, node, kX64Sub32, &cont); |
| 1134 default: | 1165 default: |
| 1135 break; | 1166 break; |
| 1136 } | 1167 } |
| 1137 } | 1168 } |
| 1138 } | 1169 } |
| 1139 break; | 1170 break; |
| 1140 case IrOpcode::kInt32Sub: | 1171 case IrOpcode::kInt32Sub: |
| 1141 return VisitWordCompare(this, value, kX64Cmp32, &cont); | 1172 return VisitWordCompare(this, value, kX64Cmp32, &cont); |
| 1142 case IrOpcode::kInt64Sub: | 1173 case IrOpcode::kInt64Sub: |
| 1143 return VisitWordCompare(this, value, kX64Cmp, &cont); | 1174 return VisitWord64Compare(this, value, &cont); |
| 1144 case IrOpcode::kWord32And: | 1175 case IrOpcode::kWord32And: |
| 1145 return VisitWordCompare(this, value, kX64Test32, &cont); | 1176 return VisitWordCompare(this, value, kX64Test32, &cont); |
| 1146 case IrOpcode::kWord64And: | 1177 case IrOpcode::kWord64And: |
| 1147 return VisitWordCompare(this, value, kX64Test, &cont); | 1178 return VisitWordCompare(this, value, kX64Test, &cont); |
| 1148 default: | 1179 default: |
| 1149 break; | 1180 break; |
| 1150 } | 1181 } |
| 1151 } | 1182 } |
| 1152 | 1183 |
| 1153 // Branch could not be combined with a compare, emit compare against 0. | 1184 // Branch could not be combined with a compare, emit compare against 0. |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1295 cont.Negate(); | 1326 cont.Negate(); |
| 1296 } else { | 1327 } else { |
| 1297 break; | 1328 break; |
| 1298 } | 1329 } |
| 1299 } | 1330 } |
| 1300 | 1331 |
| 1301 // Try to combine the branch with a comparison. | 1332 // Try to combine the branch with a comparison. |
| 1302 if (CanCover(user, value)) { | 1333 if (CanCover(user, value)) { |
| 1303 switch (value->opcode()) { | 1334 switch (value->opcode()) { |
| 1304 case IrOpcode::kInt64Sub: | 1335 case IrOpcode::kInt64Sub: |
| 1305 return VisitWordCompare(this, value, kX64Cmp, &cont); | 1336 return VisitWord64Compare(this, value, &cont); |
| 1306 case IrOpcode::kWord64And: | 1337 case IrOpcode::kWord64And: |
| 1307 return VisitWordCompare(this, value, kX64Test, &cont); | 1338 return VisitWordCompare(this, value, kX64Test, &cont); |
| 1308 default: | 1339 default: |
| 1309 break; | 1340 break; |
| 1310 } | 1341 } |
| 1311 } | 1342 } |
| 1312 return VisitCompareZero(this, value, kX64Cmp, &cont); | 1343 return VisitCompareZero(this, value, kX64Cmp, &cont); |
| 1313 } | 1344 } |
| 1314 VisitWordCompare(this, node, kX64Cmp, &cont); | 1345 VisitWord64Compare(this, node, &cont); |
| 1315 } | 1346 } |
| 1316 | 1347 |
| 1317 | 1348 |
| 1318 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { | 1349 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { |
| 1319 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 1350 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
| 1320 FlagsContinuation cont(kOverflow, ovf); | 1351 FlagsContinuation cont(kOverflow, ovf); |
| 1321 VisitBinop(this, node, kX64Add32, &cont); | 1352 VisitBinop(this, node, kX64Add32, &cont); |
| 1322 } | 1353 } |
| 1323 FlagsContinuation cont; | 1354 FlagsContinuation cont; |
| 1324 VisitBinop(this, node, kX64Add32, &cont); | 1355 VisitBinop(this, node, kX64Add32, &cont); |
| 1325 } | 1356 } |
| 1326 | 1357 |
| 1327 | 1358 |
| 1328 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { | 1359 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { |
| 1329 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 1360 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
| 1330 FlagsContinuation cont(kOverflow, ovf); | 1361 FlagsContinuation cont(kOverflow, ovf); |
| 1331 return VisitBinop(this, node, kX64Sub32, &cont); | 1362 return VisitBinop(this, node, kX64Sub32, &cont); |
| 1332 } | 1363 } |
| 1333 FlagsContinuation cont; | 1364 FlagsContinuation cont; |
| 1334 VisitBinop(this, node, kX64Sub32, &cont); | 1365 VisitBinop(this, node, kX64Sub32, &cont); |
| 1335 } | 1366 } |
| 1336 | 1367 |
| 1337 | 1368 |
| 1338 void InstructionSelector::VisitInt64LessThan(Node* node) { | 1369 void InstructionSelector::VisitInt64LessThan(Node* node) { |
| 1339 FlagsContinuation cont(kSignedLessThan, node); | 1370 FlagsContinuation cont(kSignedLessThan, node); |
| 1340 VisitWordCompare(this, node, kX64Cmp, &cont); | 1371 VisitWord64Compare(this, node, &cont); |
| 1341 } | 1372 } |
| 1342 | 1373 |
| 1343 | 1374 |
| 1344 void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) { | 1375 void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) { |
| 1345 FlagsContinuation cont(kSignedLessThanOrEqual, node); | 1376 FlagsContinuation cont(kSignedLessThanOrEqual, node); |
| 1346 VisitWordCompare(this, node, kX64Cmp, &cont); | 1377 VisitWord64Compare(this, node, &cont); |
| 1347 } | 1378 } |
| 1348 | 1379 |
| 1349 | 1380 |
| 1350 void InstructionSelector::VisitUint64LessThan(Node* node) { | 1381 void InstructionSelector::VisitUint64LessThan(Node* node) { |
| 1351 FlagsContinuation cont(kUnsignedLessThan, node); | 1382 FlagsContinuation cont(kUnsignedLessThan, node); |
| 1352 VisitWordCompare(this, node, kX64Cmp, &cont); | 1383 VisitWord64Compare(this, node, &cont); |
| 1353 } | 1384 } |
| 1354 | 1385 |
| 1355 | 1386 |
| 1356 void InstructionSelector::VisitFloat64Equal(Node* node) { | 1387 void InstructionSelector::VisitFloat64Equal(Node* node) { |
| 1357 FlagsContinuation cont(kUnorderedEqual, node); | 1388 FlagsContinuation cont(kUnorderedEqual, node); |
| 1358 VisitFloat64Compare(this, node, &cont); | 1389 VisitFloat64Compare(this, node, &cont); |
| 1359 } | 1390 } |
| 1360 | 1391 |
| 1361 | 1392 |
| 1362 void InstructionSelector::VisitFloat64LessThan(Node* node) { | 1393 void InstructionSelector::VisitFloat64LessThan(Node* node) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1417 flags |= MachineOperatorBuilder::kFloat64Floor | | 1448 flags |= MachineOperatorBuilder::kFloat64Floor | |
| 1418 MachineOperatorBuilder::kFloat64Ceil | | 1449 MachineOperatorBuilder::kFloat64Ceil | |
| 1419 MachineOperatorBuilder::kFloat64RoundTruncate; | 1450 MachineOperatorBuilder::kFloat64RoundTruncate; |
| 1420 } | 1451 } |
| 1421 return flags; | 1452 return flags; |
| 1422 } | 1453 } |
| 1423 | 1454 |
| 1424 } // namespace compiler | 1455 } // namespace compiler |
| 1425 } // namespace internal | 1456 } // namespace internal |
| 1426 } // namespace v8 | 1457 } // namespace v8 |
| OLD | NEW |