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/base/adapters.h" | 7 #include "src/base/adapters.h" |
8 #include "src/compiler/instruction-selector-impl.h" | 8 #include "src/compiler/instruction-selector-impl.h" |
9 #include "src/compiler/node-matchers.h" | 9 #include "src/compiler/node-matchers.h" |
10 #include "src/compiler/node-properties.h" | 10 #include "src/compiler/node-properties.h" |
(...skipping 1310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1321 } | 1321 } |
1322 } | 1322 } |
1323 } | 1323 } |
1324 | 1324 |
1325 | 1325 |
1326 bool InstructionSelector::IsTailCallAddressImmediate() { return true; } | 1326 bool InstructionSelector::IsTailCallAddressImmediate() { return true; } |
1327 | 1327 |
1328 | 1328 |
1329 namespace { | 1329 namespace { |
1330 | 1330 |
| 1331 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
| 1332 size_t left_operands_count, InstructionOperand* left_operands, |
| 1333 InstructionOperand right, FlagsContinuation* cont) { |
| 1334 DCHECK(left_operands_count > 0 && left_operands_count <= 3); |
| 1335 X64OperandGenerator g(selector); |
| 1336 opcode = cont->Encode(opcode); |
| 1337 int input_count = 0; |
| 1338 InstructionOperand inputs[6]; |
| 1339 do { |
| 1340 inputs[input_count] = left_operands[input_count]; |
| 1341 } while (++input_count < left_operands_count); |
| 1342 inputs[input_count++] = right; |
| 1343 |
| 1344 if (cont->IsBranch()) { |
| 1345 inputs[input_count++] = g.Label(cont->true_block()); |
| 1346 inputs[input_count++] = g.Label(cont->false_block()); |
| 1347 selector->Emit(opcode, 0, nullptr, input_count, inputs); |
| 1348 } else { |
| 1349 DCHECK(cont->IsSet()); |
| 1350 InstructionOperand output = g.DefineAsRegister(cont->result()); |
| 1351 selector->Emit(opcode, 1, &output, input_count, inputs); |
| 1352 } |
| 1353 } |
| 1354 |
| 1355 // Determines if `input' of `node' can be replaced by a memory operand. |
| 1356 bool CanUseMemOp(InstructionCode opcode, Node* node, Node* input) { |
| 1357 if (input->opcode() == IrOpcode::kLoad && input->OwnedBy(node)) { |
| 1358 MachineRepresentation rep = |
| 1359 LoadRepresentationOf(input->op()).representation(); |
| 1360 if (rep == MachineRepresentation::kWord64 || |
| 1361 rep == MachineRepresentation::kTagged) { |
| 1362 return opcode == kX64Cmp || opcode == kX64Test; |
| 1363 } else if (rep == MachineRepresentation::kWord32) { |
| 1364 return opcode == kX64Cmp32 || opcode == kX64Test32; |
| 1365 } |
| 1366 } |
| 1367 return false; |
| 1368 } |
| 1369 |
1331 // Shared routine for multiple compare operations. | 1370 // Shared routine for multiple compare operations. |
1332 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1371 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
1333 InstructionOperand left, InstructionOperand right, | 1372 InstructionOperand left, InstructionOperand right, |
1334 FlagsContinuation* cont) { | 1373 FlagsContinuation* cont) { |
1335 X64OperandGenerator g(selector); | 1374 VisitCompare(selector, opcode, 1, &left, right, cont); |
1336 opcode = cont->Encode(opcode); | |
1337 if (cont->IsBranch()) { | |
1338 selector->Emit(opcode, g.NoOutput(), left, right, | |
1339 g.Label(cont->true_block()), g.Label(cont->false_block())); | |
1340 } else { | |
1341 DCHECK(cont->IsSet()); | |
1342 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | |
1343 } | |
1344 } | 1375 } |
1345 | 1376 |
1346 | 1377 |
1347 // Shared routine for multiple compare operations. | 1378 // Shared routine for multiple compare operations. |
1348 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1379 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
1349 Node* left, Node* right, FlagsContinuation* cont, | 1380 Node* left, Node* right, FlagsContinuation* cont, |
1350 bool commutative) { | 1381 bool commutative, Node* node = nullptr) { |
1351 X64OperandGenerator g(selector); | 1382 X64OperandGenerator g(selector); |
1352 if (commutative && g.CanBeBetterLeftOperand(right)) { | 1383 if (commutative && g.CanBeBetterLeftOperand(right)) { |
1353 std::swap(left, right); | 1384 std::swap(left, right); |
1354 } | 1385 } |
1355 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont); | 1386 if (node && CanUseMemOp(opcode, node, left)) { |
| 1387 size_t left_operands_count = 0; |
| 1388 InstructionOperand left_operands[4]; |
| 1389 AddressingMode addressing_mode = g.GetEffectiveAddressMemoryOperand( |
| 1390 left, left_operands, &left_operands_count); |
| 1391 opcode |= AddressingModeField::encode(addressing_mode); |
| 1392 VisitCompare(selector, opcode, left_operands_count, left_operands, |
| 1393 g.Use(right), cont); |
| 1394 } else { |
| 1395 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont); |
| 1396 } |
1356 } | 1397 } |
1357 | 1398 |
1358 | 1399 |
1359 // Shared routine for multiple word compare operations. | 1400 // Shared routine for multiple word compare operations. |
1360 void VisitWordCompare(InstructionSelector* selector, Node* node, | 1401 void VisitWordCompare(InstructionSelector* selector, Node* node, |
1361 InstructionCode opcode, FlagsContinuation* cont) { | 1402 InstructionCode opcode, FlagsContinuation* cont) { |
1362 X64OperandGenerator g(selector); | 1403 X64OperandGenerator g(selector); |
1363 Node* const left = node->InputAt(0); | 1404 Node* left = node->InputAt(0); |
1364 Node* const right = node->InputAt(1); | 1405 Node* right = node->InputAt(1); |
1365 | 1406 |
1366 // Match immediates on left or right side of comparison. | 1407 if (!g.CanBeImmediate(right) && g.CanBeImmediate(left)) { |
| 1408 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); |
| 1409 std::swap(left, right); |
| 1410 } |
| 1411 |
| 1412 // Match immediates on right side of comparison. |
1367 if (g.CanBeImmediate(right)) { | 1413 if (g.CanBeImmediate(right)) { |
1368 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont); | 1414 if (CanUseMemOp(opcode, node, left)) { |
1369 } else if (g.CanBeImmediate(left)) { | 1415 size_t left_operands_count = 0; |
1370 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); | 1416 InstructionOperand left_operands[4]; |
1371 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont); | 1417 AddressingMode addressing_mode = g.GetEffectiveAddressMemoryOperand( |
| 1418 left, left_operands, &left_operands_count); |
| 1419 opcode |= AddressingModeField::encode(addressing_mode); |
| 1420 VisitCompare(selector, opcode, left_operands_count, left_operands, |
| 1421 g.UseImmediate(right), cont); |
| 1422 } else { |
| 1423 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont); |
| 1424 } |
1372 } else { | 1425 } else { |
1373 VisitCompare(selector, opcode, left, right, cont, | 1426 VisitCompare(selector, opcode, left, right, cont, |
1374 node->op()->HasProperty(Operator::kCommutative)); | 1427 node->op()->HasProperty(Operator::kCommutative), node); |
1375 } | 1428 } |
1376 } | 1429 } |
1377 | 1430 |
1378 | |
1379 // Shared routine for 64-bit word comparison operations. | 1431 // Shared routine for 64-bit word comparison operations. |
1380 void VisitWord64Compare(InstructionSelector* selector, Node* node, | 1432 void VisitWord64Compare(InstructionSelector* selector, Node* node, |
1381 FlagsContinuation* cont) { | 1433 FlagsContinuation* cont) { |
1382 X64OperandGenerator g(selector); | 1434 X64OperandGenerator g(selector); |
1383 Int64BinopMatcher m(node); | 1435 Int64BinopMatcher m(node); |
1384 if (m.left().IsLoad() && m.right().IsLoadStackPointer()) { | 1436 if (m.left().IsLoad() && m.right().IsLoadStackPointer()) { |
1385 LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node()); | 1437 LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node()); |
1386 ExternalReference js_stack_limit = | 1438 ExternalReference js_stack_limit = |
1387 ExternalReference::address_of_stack_limit(selector->isolate()); | 1439 ExternalReference::address_of_stack_limit(selector->isolate()); |
1388 if (mleft.object().Is(js_stack_limit) && mleft.index().Is(0)) { | 1440 if (mleft.object().Is(js_stack_limit) && mleft.index().Is(0)) { |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1826 MachineOperatorBuilder::kFloat64RoundTruncate | | 1878 MachineOperatorBuilder::kFloat64RoundTruncate | |
1827 MachineOperatorBuilder::kFloat32RoundTiesEven | | 1879 MachineOperatorBuilder::kFloat32RoundTiesEven | |
1828 MachineOperatorBuilder::kFloat64RoundTiesEven; | 1880 MachineOperatorBuilder::kFloat64RoundTiesEven; |
1829 } | 1881 } |
1830 return flags; | 1882 return flags; |
1831 } | 1883 } |
1832 | 1884 |
1833 } // namespace compiler | 1885 } // namespace compiler |
1834 } // namespace internal | 1886 } // namespace internal |
1835 } // namespace v8 | 1887 } // namespace v8 |
OLD | NEW |