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 |