| 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 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 outputs[output_count++] = g.DefineSameAsFirst(node); | 392 outputs[output_count++] = g.DefineSameAsFirst(node); |
| 393 if (cont->IsSet()) { | 393 if (cont->IsSet()) { |
| 394 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 394 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
| 395 } | 395 } |
| 396 | 396 |
| 397 DCHECK_NE(0u, input_count); | 397 DCHECK_NE(0u, input_count); |
| 398 DCHECK_NE(0u, output_count); | 398 DCHECK_NE(0u, output_count); |
| 399 DCHECK_GE(arraysize(inputs), input_count); | 399 DCHECK_GE(arraysize(inputs), input_count); |
| 400 DCHECK_GE(arraysize(outputs), output_count); | 400 DCHECK_GE(arraysize(outputs), output_count); |
| 401 | 401 |
| 402 selector->Emit(cont->Encode(opcode), output_count, outputs, input_count, | 402 opcode = cont->Encode(opcode); |
| 403 inputs); | 403 if (cont->IsDeoptimize()) { |
| 404 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, |
| 405 cont->frame_state()); |
| 406 } else { |
| 407 selector->Emit(opcode, output_count, outputs, input_count, inputs); |
| 408 } |
| 404 } | 409 } |
| 405 | 410 |
| 406 | 411 |
| 407 // Shared routine for multiple binary operations. | 412 // Shared routine for multiple binary operations. |
| 408 static void VisitBinop(InstructionSelector* selector, Node* node, | 413 static void VisitBinop(InstructionSelector* selector, Node* node, |
| 409 InstructionCode opcode) { | 414 InstructionCode opcode) { |
| 410 FlagsContinuation cont; | 415 FlagsContinuation cont; |
| 411 VisitBinop(selector, node, opcode, &cont); | 416 VisitBinop(selector, node, opcode, &cont); |
| 412 } | 417 } |
| 413 | 418 |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 } | 666 } |
| 662 | 667 |
| 663 | 668 |
| 664 void InstructionSelector::VisitInt64Add(Node* node) { | 669 void InstructionSelector::VisitInt64Add(Node* node) { |
| 665 VisitBinop(this, node, kX64Add); | 670 VisitBinop(this, node, kX64Add); |
| 666 } | 671 } |
| 667 | 672 |
| 668 | 673 |
| 669 void InstructionSelector::VisitInt64AddWithOverflow(Node* node) { | 674 void InstructionSelector::VisitInt64AddWithOverflow(Node* node) { |
| 670 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 675 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
| 671 FlagsContinuation cont(kOverflow, ovf); | 676 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
| 672 VisitBinop(this, node, kX64Add, &cont); | 677 VisitBinop(this, node, kX64Add, &cont); |
| 673 } | 678 } |
| 674 FlagsContinuation cont; | 679 FlagsContinuation cont; |
| 675 VisitBinop(this, node, kX64Add, &cont); | 680 VisitBinop(this, node, kX64Add, &cont); |
| 676 } | 681 } |
| 677 | 682 |
| 678 | 683 |
| 679 void InstructionSelector::VisitInt32Sub(Node* node) { | 684 void InstructionSelector::VisitInt32Sub(Node* node) { |
| 680 X64OperandGenerator g(this); | 685 X64OperandGenerator g(this); |
| 681 Int32BinopMatcher m(node); | 686 Int32BinopMatcher m(node); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 701 if (m.left().Is(0)) { | 706 if (m.left().Is(0)) { |
| 702 Emit(kX64Neg, g.DefineSameAsFirst(node), g.UseRegister(m.right().node())); | 707 Emit(kX64Neg, g.DefineSameAsFirst(node), g.UseRegister(m.right().node())); |
| 703 } else { | 708 } else { |
| 704 VisitBinop(this, node, kX64Sub); | 709 VisitBinop(this, node, kX64Sub); |
| 705 } | 710 } |
| 706 } | 711 } |
| 707 | 712 |
| 708 | 713 |
| 709 void InstructionSelector::VisitInt64SubWithOverflow(Node* node) { | 714 void InstructionSelector::VisitInt64SubWithOverflow(Node* node) { |
| 710 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 715 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
| 711 FlagsContinuation cont(kOverflow, ovf); | 716 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
| 712 return VisitBinop(this, node, kX64Sub, &cont); | 717 return VisitBinop(this, node, kX64Sub, &cont); |
| 713 } | 718 } |
| 714 FlagsContinuation cont; | 719 FlagsContinuation cont; |
| 715 VisitBinop(this, node, kX64Sub, &cont); | 720 VisitBinop(this, node, kX64Sub, &cont); |
| 716 } | 721 } |
| 717 | 722 |
| 718 | 723 |
| 719 namespace { | 724 namespace { |
| 720 | 725 |
| 721 void VisitMul(InstructionSelector* selector, Node* node, ArchOpcode opcode) { | 726 void VisitMul(InstructionSelector* selector, Node* node, ArchOpcode opcode) { |
| (...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1349 AddressingMode addressing_mode = | 1354 AddressingMode addressing_mode = |
| 1350 g.GetEffectiveAddressMemoryOperand(left, inputs, &input_count); | 1355 g.GetEffectiveAddressMemoryOperand(left, inputs, &input_count); |
| 1351 opcode |= AddressingModeField::encode(addressing_mode); | 1356 opcode |= AddressingModeField::encode(addressing_mode); |
| 1352 opcode = cont->Encode(opcode); | 1357 opcode = cont->Encode(opcode); |
| 1353 inputs[input_count++] = right; | 1358 inputs[input_count++] = right; |
| 1354 | 1359 |
| 1355 if (cont->IsBranch()) { | 1360 if (cont->IsBranch()) { |
| 1356 inputs[input_count++] = g.Label(cont->true_block()); | 1361 inputs[input_count++] = g.Label(cont->true_block()); |
| 1357 inputs[input_count++] = g.Label(cont->false_block()); | 1362 inputs[input_count++] = g.Label(cont->false_block()); |
| 1358 selector->Emit(opcode, 0, nullptr, input_count, inputs); | 1363 selector->Emit(opcode, 0, nullptr, input_count, inputs); |
| 1364 } else if (cont->IsDeoptimize()) { |
| 1365 selector->EmitDeoptimize(opcode, 0, nullptr, input_count, inputs, |
| 1366 cont->frame_state()); |
| 1359 } else { | 1367 } else { |
| 1360 DCHECK(cont->IsSet()); | 1368 DCHECK(cont->IsSet()); |
| 1361 InstructionOperand output = g.DefineAsRegister(cont->result()); | 1369 InstructionOperand output = g.DefineAsRegister(cont->result()); |
| 1362 selector->Emit(opcode, 1, &output, input_count, inputs); | 1370 selector->Emit(opcode, 1, &output, input_count, inputs); |
| 1363 } | 1371 } |
| 1364 } | 1372 } |
| 1365 | 1373 |
| 1366 // Determines if {input} of {node} can be replaced by a memory operand. | 1374 // Determines if {input} of {node} can be replaced by a memory operand. |
| 1367 bool CanUseMemoryOperand(InstructionSelector* selector, InstructionCode opcode, | 1375 bool CanUseMemoryOperand(InstructionSelector* selector, InstructionCode opcode, |
| 1368 Node* node, Node* input) { | 1376 Node* node, Node* input) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1382 | 1390 |
| 1383 // Shared routine for multiple compare operations. | 1391 // Shared routine for multiple compare operations. |
| 1384 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1392 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
| 1385 InstructionOperand left, InstructionOperand right, | 1393 InstructionOperand left, InstructionOperand right, |
| 1386 FlagsContinuation* cont) { | 1394 FlagsContinuation* cont) { |
| 1387 X64OperandGenerator g(selector); | 1395 X64OperandGenerator g(selector); |
| 1388 opcode = cont->Encode(opcode); | 1396 opcode = cont->Encode(opcode); |
| 1389 if (cont->IsBranch()) { | 1397 if (cont->IsBranch()) { |
| 1390 selector->Emit(opcode, g.NoOutput(), left, right, | 1398 selector->Emit(opcode, g.NoOutput(), left, right, |
| 1391 g.Label(cont->true_block()), g.Label(cont->false_block())); | 1399 g.Label(cont->true_block()), g.Label(cont->false_block())); |
| 1400 } else if (cont->IsDeoptimize()) { |
| 1401 selector->EmitDeoptimize(opcode, g.NoOutput(), left, right, |
| 1402 cont->frame_state()); |
| 1392 } else { | 1403 } else { |
| 1393 DCHECK(cont->IsSet()); | 1404 DCHECK(cont->IsSet()); |
| 1394 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | 1405 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); |
| 1395 } | 1406 } |
| 1396 } | 1407 } |
| 1397 | 1408 |
| 1398 | 1409 |
| 1399 // Shared routine for multiple compare operations. | 1410 // Shared routine for multiple compare operations. |
| 1400 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1411 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
| 1401 Node* left, Node* right, FlagsContinuation* cont, | 1412 Node* left, Node* right, FlagsContinuation* cont, |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1452 LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node()); | 1463 LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node()); |
| 1453 ExternalReference js_stack_limit = | 1464 ExternalReference js_stack_limit = |
| 1454 ExternalReference::address_of_stack_limit(selector->isolate()); | 1465 ExternalReference::address_of_stack_limit(selector->isolate()); |
| 1455 if (mleft.object().Is(js_stack_limit) && mleft.index().Is(0)) { | 1466 if (mleft.object().Is(js_stack_limit) && mleft.index().Is(0)) { |
| 1456 // Compare(Load(js_stack_limit), LoadStackPointer) | 1467 // Compare(Load(js_stack_limit), LoadStackPointer) |
| 1457 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); | 1468 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); |
| 1458 InstructionCode opcode = cont->Encode(kX64StackCheck); | 1469 InstructionCode opcode = cont->Encode(kX64StackCheck); |
| 1459 if (cont->IsBranch()) { | 1470 if (cont->IsBranch()) { |
| 1460 selector->Emit(opcode, g.NoOutput(), g.Label(cont->true_block()), | 1471 selector->Emit(opcode, g.NoOutput(), g.Label(cont->true_block()), |
| 1461 g.Label(cont->false_block())); | 1472 g.Label(cont->false_block())); |
| 1473 } else if (cont->IsDeoptimize()) { |
| 1474 selector->EmitDeoptimize(opcode, 0, nullptr, 0, nullptr, |
| 1475 cont->frame_state()); |
| 1462 } else { | 1476 } else { |
| 1463 DCHECK(cont->IsSet()); | 1477 DCHECK(cont->IsSet()); |
| 1464 selector->Emit(opcode, g.DefineAsRegister(cont->result())); | 1478 selector->Emit(opcode, g.DefineAsRegister(cont->result())); |
| 1465 } | 1479 } |
| 1466 return; | 1480 return; |
| 1467 } | 1481 } |
| 1468 } | 1482 } |
| 1469 VisitWordCompare(selector, node, kX64Cmp, cont); | 1483 VisitWordCompare(selector, node, kX64Cmp, cont); |
| 1470 } | 1484 } |
| 1471 | 1485 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1492 // Shared routine for multiple float64 compare operations (inputs commuted). | 1506 // Shared routine for multiple float64 compare operations (inputs commuted). |
| 1493 void VisitFloat64Compare(InstructionSelector* selector, Node* node, | 1507 void VisitFloat64Compare(InstructionSelector* selector, Node* node, |
| 1494 FlagsContinuation* cont) { | 1508 FlagsContinuation* cont) { |
| 1495 Node* const left = node->InputAt(0); | 1509 Node* const left = node->InputAt(0); |
| 1496 Node* const right = node->InputAt(1); | 1510 Node* const right = node->InputAt(1); |
| 1497 InstructionCode const opcode = | 1511 InstructionCode const opcode = |
| 1498 selector->IsSupported(AVX) ? kAVXFloat64Cmp : kSSEFloat64Cmp; | 1512 selector->IsSupported(AVX) ? kAVXFloat64Cmp : kSSEFloat64Cmp; |
| 1499 VisitCompare(selector, opcode, right, left, cont, false); | 1513 VisitCompare(selector, opcode, right, left, cont, false); |
| 1500 } | 1514 } |
| 1501 | 1515 |
| 1502 } // namespace | 1516 // Shared routine for word comparison against zero. |
| 1503 | 1517 void VisitWordCompareZero(InstructionSelector* selector, Node* user, |
| 1504 | 1518 Node* value, FlagsContinuation* cont) { |
| 1505 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 1519 while (selector->CanCover(user, value)) { |
| 1506 BasicBlock* fbranch) { | |
| 1507 X64OperandGenerator g(this); | |
| 1508 Node* user = branch; | |
| 1509 Node* value = branch->InputAt(0); | |
| 1510 | |
| 1511 FlagsContinuation cont(kNotEqual, tbranch, fbranch); | |
| 1512 | |
| 1513 // Try to combine with comparisons against 0 by simply inverting the branch. | |
| 1514 while (CanCover(user, value) && value->opcode() == IrOpcode::kWord32Equal) { | |
| 1515 Int32BinopMatcher m(value); | |
| 1516 if (m.right().Is(0)) { | |
| 1517 user = value; | |
| 1518 value = m.left().node(); | |
| 1519 cont.Negate(); | |
| 1520 } else { | |
| 1521 break; | |
| 1522 } | |
| 1523 } | |
| 1524 | |
| 1525 // Try to combine the branch with a comparison. | |
| 1526 if (CanCover(user, value)) { | |
| 1527 switch (value->opcode()) { | 1520 switch (value->opcode()) { |
| 1528 case IrOpcode::kWord32Equal: | 1521 case IrOpcode::kWord32Equal: { |
| 1529 cont.OverwriteAndNegateIfEqual(kEqual); | 1522 // Combine with comparisons against 0 by simply inverting the |
| 1530 return VisitWordCompare(this, value, kX64Cmp32, &cont); | 1523 // continuation. |
| 1524 Int32BinopMatcher m(value); |
| 1525 if (m.right().Is(0)) { |
| 1526 user = value; |
| 1527 value = m.left().node(); |
| 1528 cont->Negate(); |
| 1529 continue; |
| 1530 } |
| 1531 cont->OverwriteAndNegateIfEqual(kEqual); |
| 1532 return VisitWordCompare(selector, value, kX64Cmp32, cont); |
| 1533 } |
| 1531 case IrOpcode::kInt32LessThan: | 1534 case IrOpcode::kInt32LessThan: |
| 1532 cont.OverwriteAndNegateIfEqual(kSignedLessThan); | 1535 cont->OverwriteAndNegateIfEqual(kSignedLessThan); |
| 1533 return VisitWordCompare(this, value, kX64Cmp32, &cont); | 1536 return VisitWordCompare(selector, value, kX64Cmp32, cont); |
| 1534 case IrOpcode::kInt32LessThanOrEqual: | 1537 case IrOpcode::kInt32LessThanOrEqual: |
| 1535 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); | 1538 cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); |
| 1536 return VisitWordCompare(this, value, kX64Cmp32, &cont); | 1539 return VisitWordCompare(selector, value, kX64Cmp32, cont); |
| 1537 case IrOpcode::kUint32LessThan: | 1540 case IrOpcode::kUint32LessThan: |
| 1538 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); | 1541 cont->OverwriteAndNegateIfEqual(kUnsignedLessThan); |
| 1539 return VisitWordCompare(this, value, kX64Cmp32, &cont); | 1542 return VisitWordCompare(selector, value, kX64Cmp32, cont); |
| 1540 case IrOpcode::kUint32LessThanOrEqual: | 1543 case IrOpcode::kUint32LessThanOrEqual: |
| 1541 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); | 1544 cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); |
| 1542 return VisitWordCompare(this, value, kX64Cmp32, &cont); | 1545 return VisitWordCompare(selector, value, kX64Cmp32, cont); |
| 1543 case IrOpcode::kWord64Equal: { | 1546 case IrOpcode::kWord64Equal: { |
| 1544 cont.OverwriteAndNegateIfEqual(kEqual); | 1547 cont->OverwriteAndNegateIfEqual(kEqual); |
| 1545 Int64BinopMatcher m(value); | 1548 Int64BinopMatcher m(value); |
| 1546 if (m.right().Is(0)) { | 1549 if (m.right().Is(0)) { |
| 1547 // Try to combine the branch with a comparison. | 1550 // Try to combine the branch with a comparison. |
| 1548 Node* const user = m.node(); | 1551 Node* const user = m.node(); |
| 1549 Node* const value = m.left().node(); | 1552 Node* const value = m.left().node(); |
| 1550 if (CanCover(user, value)) { | 1553 if (selector->CanCover(user, value)) { |
| 1551 switch (value->opcode()) { | 1554 switch (value->opcode()) { |
| 1552 case IrOpcode::kInt64Sub: | 1555 case IrOpcode::kInt64Sub: |
| 1553 return VisitWord64Compare(this, value, &cont); | 1556 return VisitWord64Compare(selector, value, cont); |
| 1554 case IrOpcode::kWord64And: | 1557 case IrOpcode::kWord64And: |
| 1555 return VisitWordCompare(this, value, kX64Test, &cont); | 1558 return VisitWordCompare(selector, value, kX64Test, cont); |
| 1556 default: | 1559 default: |
| 1557 break; | 1560 break; |
| 1558 } | 1561 } |
| 1559 } | 1562 } |
| 1560 return VisitCompareZero(this, value, kX64Cmp, &cont); | 1563 return VisitCompareZero(selector, value, kX64Cmp, cont); |
| 1561 } | 1564 } |
| 1562 return VisitWord64Compare(this, value, &cont); | 1565 return VisitWord64Compare(selector, value, cont); |
| 1563 } | 1566 } |
| 1564 case IrOpcode::kInt64LessThan: | 1567 case IrOpcode::kInt64LessThan: |
| 1565 cont.OverwriteAndNegateIfEqual(kSignedLessThan); | 1568 cont->OverwriteAndNegateIfEqual(kSignedLessThan); |
| 1566 return VisitWord64Compare(this, value, &cont); | 1569 return VisitWord64Compare(selector, value, cont); |
| 1567 case IrOpcode::kInt64LessThanOrEqual: | 1570 case IrOpcode::kInt64LessThanOrEqual: |
| 1568 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); | 1571 cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); |
| 1569 return VisitWord64Compare(this, value, &cont); | 1572 return VisitWord64Compare(selector, value, cont); |
| 1570 case IrOpcode::kUint64LessThan: | 1573 case IrOpcode::kUint64LessThan: |
| 1571 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); | 1574 cont->OverwriteAndNegateIfEqual(kUnsignedLessThan); |
| 1572 return VisitWord64Compare(this, value, &cont); | 1575 return VisitWord64Compare(selector, value, cont); |
| 1573 case IrOpcode::kUint64LessThanOrEqual: | 1576 case IrOpcode::kUint64LessThanOrEqual: |
| 1574 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); | 1577 cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); |
| 1575 return VisitWord64Compare(this, value, &cont); | 1578 return VisitWord64Compare(selector, value, cont); |
| 1576 case IrOpcode::kFloat32Equal: | 1579 case IrOpcode::kFloat32Equal: |
| 1577 cont.OverwriteAndNegateIfEqual(kUnorderedEqual); | 1580 cont->OverwriteAndNegateIfEqual(kUnorderedEqual); |
| 1578 return VisitFloat32Compare(this, value, &cont); | 1581 return VisitFloat32Compare(selector, value, cont); |
| 1579 case IrOpcode::kFloat32LessThan: | 1582 case IrOpcode::kFloat32LessThan: |
| 1580 cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThan); | 1583 cont->OverwriteAndNegateIfEqual(kUnsignedGreaterThan); |
| 1581 return VisitFloat32Compare(this, value, &cont); | 1584 return VisitFloat32Compare(selector, value, cont); |
| 1582 case IrOpcode::kFloat32LessThanOrEqual: | 1585 case IrOpcode::kFloat32LessThanOrEqual: |
| 1583 cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual); | 1586 cont->OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual); |
| 1584 return VisitFloat32Compare(this, value, &cont); | 1587 return VisitFloat32Compare(selector, value, cont); |
| 1585 case IrOpcode::kFloat64Equal: | 1588 case IrOpcode::kFloat64Equal: |
| 1586 cont.OverwriteAndNegateIfEqual(kUnorderedEqual); | 1589 cont->OverwriteAndNegateIfEqual(kUnorderedEqual); |
| 1587 return VisitFloat64Compare(this, value, &cont); | 1590 return VisitFloat64Compare(selector, value, cont); |
| 1588 case IrOpcode::kFloat64LessThan: | 1591 case IrOpcode::kFloat64LessThan: |
| 1589 cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThan); | 1592 cont->OverwriteAndNegateIfEqual(kUnsignedGreaterThan); |
| 1590 return VisitFloat64Compare(this, value, &cont); | 1593 return VisitFloat64Compare(selector, value, cont); |
| 1591 case IrOpcode::kFloat64LessThanOrEqual: | 1594 case IrOpcode::kFloat64LessThanOrEqual: |
| 1592 cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual); | 1595 cont->OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual); |
| 1593 return VisitFloat64Compare(this, value, &cont); | 1596 return VisitFloat64Compare(selector, value, cont); |
| 1594 case IrOpcode::kProjection: | 1597 case IrOpcode::kProjection: |
| 1595 // Check if this is the overflow output projection of an | 1598 // Check if this is the overflow output projection of an |
| 1596 // <Operation>WithOverflow node. | 1599 // <Operation>WithOverflow node. |
| 1597 if (ProjectionIndexOf(value->op()) == 1u) { | 1600 if (ProjectionIndexOf(value->op()) == 1u) { |
| 1598 // We cannot combine the <Operation>WithOverflow with this branch | 1601 // We cannot combine the <Operation>WithOverflow with this branch |
| 1599 // unless the 0th projection (the use of the actual value of the | 1602 // unless the 0th projection (the use of the actual value of the |
| 1600 // <Operation> is either nullptr, which means there's no use of the | 1603 // <Operation> is either nullptr, which means there's no use of the |
| 1601 // actual value, or was already defined, which means it is scheduled | 1604 // actual value, or was already defined, which means it is scheduled |
| 1602 // *AFTER* this branch). | 1605 // *AFTER* this branch). |
| 1603 Node* const node = value->InputAt(0); | 1606 Node* const node = value->InputAt(0); |
| 1604 Node* const result = NodeProperties::FindProjection(node, 0); | 1607 Node* const result = NodeProperties::FindProjection(node, 0); |
| 1605 if (result == nullptr || IsDefined(result)) { | 1608 if (result == nullptr || selector->IsDefined(result)) { |
| 1606 switch (node->opcode()) { | 1609 switch (node->opcode()) { |
| 1607 case IrOpcode::kInt32AddWithOverflow: | 1610 case IrOpcode::kInt32AddWithOverflow: |
| 1608 cont.OverwriteAndNegateIfEqual(kOverflow); | 1611 cont->OverwriteAndNegateIfEqual(kOverflow); |
| 1609 return VisitBinop(this, node, kX64Add32, &cont); | 1612 return VisitBinop(selector, node, kX64Add32, cont); |
| 1610 case IrOpcode::kInt32SubWithOverflow: | 1613 case IrOpcode::kInt32SubWithOverflow: |
| 1611 cont.OverwriteAndNegateIfEqual(kOverflow); | 1614 cont->OverwriteAndNegateIfEqual(kOverflow); |
| 1612 return VisitBinop(this, node, kX64Sub32, &cont); | 1615 return VisitBinop(selector, node, kX64Sub32, cont); |
| 1613 case IrOpcode::kInt64AddWithOverflow: | 1616 case IrOpcode::kInt64AddWithOverflow: |
| 1614 cont.OverwriteAndNegateIfEqual(kOverflow); | 1617 cont->OverwriteAndNegateIfEqual(kOverflow); |
| 1615 return VisitBinop(this, node, kX64Add, &cont); | 1618 return VisitBinop(selector, node, kX64Add, cont); |
| 1616 case IrOpcode::kInt64SubWithOverflow: | 1619 case IrOpcode::kInt64SubWithOverflow: |
| 1617 cont.OverwriteAndNegateIfEqual(kOverflow); | 1620 cont->OverwriteAndNegateIfEqual(kOverflow); |
| 1618 return VisitBinop(this, node, kX64Sub, &cont); | 1621 return VisitBinop(selector, node, kX64Sub, cont); |
| 1619 default: | 1622 default: |
| 1620 break; | 1623 break; |
| 1621 } | 1624 } |
| 1622 } | 1625 } |
| 1623 } | 1626 } |
| 1624 break; | 1627 break; |
| 1625 case IrOpcode::kInt32Sub: | 1628 case IrOpcode::kInt32Sub: |
| 1626 return VisitWordCompare(this, value, kX64Cmp32, &cont); | 1629 return VisitWordCompare(selector, value, kX64Cmp32, cont); |
| 1627 case IrOpcode::kInt64Sub: | 1630 case IrOpcode::kInt64Sub: |
| 1628 return VisitWord64Compare(this, value, &cont); | 1631 return VisitWord64Compare(selector, value, cont); |
| 1629 case IrOpcode::kWord32And: | 1632 case IrOpcode::kWord32And: |
| 1630 return VisitWordCompare(this, value, kX64Test32, &cont); | 1633 return VisitWordCompare(selector, value, kX64Test32, cont); |
| 1631 case IrOpcode::kWord64And: | 1634 case IrOpcode::kWord64And: |
| 1632 return VisitWordCompare(this, value, kX64Test, &cont); | 1635 return VisitWordCompare(selector, value, kX64Test, cont); |
| 1633 default: | 1636 default: |
| 1634 break; | 1637 break; |
| 1635 } | 1638 } |
| 1639 break; |
| 1636 } | 1640 } |
| 1637 | 1641 |
| 1638 // Branch could not be combined with a compare, emit compare against 0. | 1642 // Branch could not be combined with a compare, emit compare against 0. |
| 1639 VisitCompareZero(this, value, kX64Cmp32, &cont); | 1643 VisitCompareZero(selector, value, kX64Cmp32, cont); |
| 1640 } | 1644 } |
| 1641 | 1645 |
| 1646 } // namespace |
| 1647 |
| 1648 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
| 1649 BasicBlock* fbranch) { |
| 1650 FlagsContinuation cont(kNotEqual, tbranch, fbranch); |
| 1651 VisitWordCompareZero(this, branch, branch->InputAt(0), &cont); |
| 1652 } |
| 1653 |
| 1654 void InstructionSelector::VisitDeoptimizeIf(Node* node) { |
| 1655 FlagsContinuation cont = |
| 1656 FlagsContinuation::ForDeoptimize(kNotEqual, node->InputAt(1)); |
| 1657 VisitWordCompareZero(this, node, node->InputAt(0), &cont); |
| 1658 } |
| 1659 |
| 1660 void InstructionSelector::VisitDeoptimizeUnless(Node* node) { |
| 1661 FlagsContinuation cont = |
| 1662 FlagsContinuation::ForDeoptimize(kEqual, node->InputAt(1)); |
| 1663 VisitWordCompareZero(this, node, node->InputAt(0), &cont); |
| 1664 } |
| 1642 | 1665 |
| 1643 void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { | 1666 void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { |
| 1644 X64OperandGenerator g(this); | 1667 X64OperandGenerator g(this); |
| 1645 InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); | 1668 InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); |
| 1646 | 1669 |
| 1647 // Emit either ArchTableSwitch or ArchLookupSwitch. | 1670 // Emit either ArchTableSwitch or ArchLookupSwitch. |
| 1648 size_t table_space_cost = 4 + sw.value_range; | 1671 size_t table_space_cost = 4 + sw.value_range; |
| 1649 size_t table_time_cost = 3; | 1672 size_t table_time_cost = 3; |
| 1650 size_t lookup_space_cost = 3 + 2 * sw.case_count; | 1673 size_t lookup_space_cost = 3 + 2 * sw.case_count; |
| 1651 size_t lookup_time_cost = sw.case_count; | 1674 size_t lookup_time_cost = sw.case_count; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1666 return EmitTableSwitch(sw, index_operand); | 1689 return EmitTableSwitch(sw, index_operand); |
| 1667 } | 1690 } |
| 1668 | 1691 |
| 1669 // Generate a sequence of conditional jumps. | 1692 // Generate a sequence of conditional jumps. |
| 1670 return EmitLookupSwitch(sw, value_operand); | 1693 return EmitLookupSwitch(sw, value_operand); |
| 1671 } | 1694 } |
| 1672 | 1695 |
| 1673 | 1696 |
| 1674 void InstructionSelector::VisitWord32Equal(Node* const node) { | 1697 void InstructionSelector::VisitWord32Equal(Node* const node) { |
| 1675 Node* user = node; | 1698 Node* user = node; |
| 1676 FlagsContinuation cont(kEqual, node); | 1699 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node); |
| 1677 Int32BinopMatcher m(user); | 1700 Int32BinopMatcher m(user); |
| 1678 if (m.right().Is(0)) { | 1701 if (m.right().Is(0)) { |
| 1679 Node* value = m.left().node(); | 1702 Node* value = m.left().node(); |
| 1680 | 1703 |
| 1681 // Try to combine with comparisons against 0 by simply inverting the branch. | 1704 // Try to combine with comparisons against 0 by simply inverting the branch. |
| 1682 while (CanCover(user, value) && value->opcode() == IrOpcode::kWord32Equal) { | 1705 while (CanCover(user, value) && value->opcode() == IrOpcode::kWord32Equal) { |
| 1683 Int32BinopMatcher m(value); | 1706 Int32BinopMatcher m(value); |
| 1684 if (m.right().Is(0)) { | 1707 if (m.right().Is(0)) { |
| 1685 user = value; | 1708 user = value; |
| 1686 value = m.left().node(); | 1709 value = m.left().node(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1701 break; | 1724 break; |
| 1702 } | 1725 } |
| 1703 } | 1726 } |
| 1704 return VisitCompareZero(this, value, kX64Cmp32, &cont); | 1727 return VisitCompareZero(this, value, kX64Cmp32, &cont); |
| 1705 } | 1728 } |
| 1706 VisitWordCompare(this, node, kX64Cmp32, &cont); | 1729 VisitWordCompare(this, node, kX64Cmp32, &cont); |
| 1707 } | 1730 } |
| 1708 | 1731 |
| 1709 | 1732 |
| 1710 void InstructionSelector::VisitInt32LessThan(Node* node) { | 1733 void InstructionSelector::VisitInt32LessThan(Node* node) { |
| 1711 FlagsContinuation cont(kSignedLessThan, node); | 1734 FlagsContinuation cont = FlagsContinuation::ForSet(kSignedLessThan, node); |
| 1712 VisitWordCompare(this, node, kX64Cmp32, &cont); | 1735 VisitWordCompare(this, node, kX64Cmp32, &cont); |
| 1713 } | 1736 } |
| 1714 | 1737 |
| 1715 | 1738 |
| 1716 void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) { | 1739 void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) { |
| 1717 FlagsContinuation cont(kSignedLessThanOrEqual, node); | 1740 FlagsContinuation cont = |
| 1741 FlagsContinuation::ForSet(kSignedLessThanOrEqual, node); |
| 1718 VisitWordCompare(this, node, kX64Cmp32, &cont); | 1742 VisitWordCompare(this, node, kX64Cmp32, &cont); |
| 1719 } | 1743 } |
| 1720 | 1744 |
| 1721 | 1745 |
| 1722 void InstructionSelector::VisitUint32LessThan(Node* node) { | 1746 void InstructionSelector::VisitUint32LessThan(Node* node) { |
| 1723 FlagsContinuation cont(kUnsignedLessThan, node); | 1747 FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node); |
| 1724 VisitWordCompare(this, node, kX64Cmp32, &cont); | 1748 VisitWordCompare(this, node, kX64Cmp32, &cont); |
| 1725 } | 1749 } |
| 1726 | 1750 |
| 1727 | 1751 |
| 1728 void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) { | 1752 void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) { |
| 1729 FlagsContinuation cont(kUnsignedLessThanOrEqual, node); | 1753 FlagsContinuation cont = |
| 1754 FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node); |
| 1730 VisitWordCompare(this, node, kX64Cmp32, &cont); | 1755 VisitWordCompare(this, node, kX64Cmp32, &cont); |
| 1731 } | 1756 } |
| 1732 | 1757 |
| 1733 | 1758 |
| 1734 void InstructionSelector::VisitWord64Equal(Node* const node) { | 1759 void InstructionSelector::VisitWord64Equal(Node* const node) { |
| 1735 FlagsContinuation cont(kEqual, node); | 1760 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node); |
| 1736 Int64BinopMatcher m(node); | 1761 Int64BinopMatcher m(node); |
| 1737 if (m.right().Is(0)) { | 1762 if (m.right().Is(0)) { |
| 1738 // Try to combine the equality check with a comparison. | 1763 // Try to combine the equality check with a comparison. |
| 1739 Node* const user = m.node(); | 1764 Node* const user = m.node(); |
| 1740 Node* const value = m.left().node(); | 1765 Node* const value = m.left().node(); |
| 1741 if (CanCover(user, value)) { | 1766 if (CanCover(user, value)) { |
| 1742 switch (value->opcode()) { | 1767 switch (value->opcode()) { |
| 1743 case IrOpcode::kInt64Sub: | 1768 case IrOpcode::kInt64Sub: |
| 1744 return VisitWord64Compare(this, value, &cont); | 1769 return VisitWord64Compare(this, value, &cont); |
| 1745 case IrOpcode::kWord64And: | 1770 case IrOpcode::kWord64And: |
| 1746 return VisitWordCompare(this, value, kX64Test, &cont); | 1771 return VisitWordCompare(this, value, kX64Test, &cont); |
| 1747 default: | 1772 default: |
| 1748 break; | 1773 break; |
| 1749 } | 1774 } |
| 1750 } | 1775 } |
| 1751 } | 1776 } |
| 1752 VisitWord64Compare(this, node, &cont); | 1777 VisitWord64Compare(this, node, &cont); |
| 1753 } | 1778 } |
| 1754 | 1779 |
| 1755 | 1780 |
| 1756 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { | 1781 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { |
| 1757 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 1782 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
| 1758 FlagsContinuation cont(kOverflow, ovf); | 1783 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
| 1759 VisitBinop(this, node, kX64Add32, &cont); | 1784 VisitBinop(this, node, kX64Add32, &cont); |
| 1760 } | 1785 } |
| 1761 FlagsContinuation cont; | 1786 FlagsContinuation cont; |
| 1762 VisitBinop(this, node, kX64Add32, &cont); | 1787 VisitBinop(this, node, kX64Add32, &cont); |
| 1763 } | 1788 } |
| 1764 | 1789 |
| 1765 | 1790 |
| 1766 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { | 1791 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { |
| 1767 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 1792 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
| 1768 FlagsContinuation cont(kOverflow, ovf); | 1793 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
| 1769 return VisitBinop(this, node, kX64Sub32, &cont); | 1794 return VisitBinop(this, node, kX64Sub32, &cont); |
| 1770 } | 1795 } |
| 1771 FlagsContinuation cont; | 1796 FlagsContinuation cont; |
| 1772 VisitBinop(this, node, kX64Sub32, &cont); | 1797 VisitBinop(this, node, kX64Sub32, &cont); |
| 1773 } | 1798 } |
| 1774 | 1799 |
| 1775 | 1800 |
| 1776 void InstructionSelector::VisitInt64LessThan(Node* node) { | 1801 void InstructionSelector::VisitInt64LessThan(Node* node) { |
| 1777 FlagsContinuation cont(kSignedLessThan, node); | 1802 FlagsContinuation cont = FlagsContinuation::ForSet(kSignedLessThan, node); |
| 1778 VisitWord64Compare(this, node, &cont); | 1803 VisitWord64Compare(this, node, &cont); |
| 1779 } | 1804 } |
| 1780 | 1805 |
| 1781 | 1806 |
| 1782 void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) { | 1807 void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) { |
| 1783 FlagsContinuation cont(kSignedLessThanOrEqual, node); | 1808 FlagsContinuation cont = |
| 1809 FlagsContinuation::ForSet(kSignedLessThanOrEqual, node); |
| 1784 VisitWord64Compare(this, node, &cont); | 1810 VisitWord64Compare(this, node, &cont); |
| 1785 } | 1811 } |
| 1786 | 1812 |
| 1787 | 1813 |
| 1788 void InstructionSelector::VisitUint64LessThan(Node* node) { | 1814 void InstructionSelector::VisitUint64LessThan(Node* node) { |
| 1789 FlagsContinuation cont(kUnsignedLessThan, node); | 1815 FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node); |
| 1790 VisitWord64Compare(this, node, &cont); | 1816 VisitWord64Compare(this, node, &cont); |
| 1791 } | 1817 } |
| 1792 | 1818 |
| 1793 | 1819 |
| 1794 void InstructionSelector::VisitUint64LessThanOrEqual(Node* node) { | 1820 void InstructionSelector::VisitUint64LessThanOrEqual(Node* node) { |
| 1795 FlagsContinuation cont(kUnsignedLessThanOrEqual, node); | 1821 FlagsContinuation cont = |
| 1822 FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node); |
| 1796 VisitWord64Compare(this, node, &cont); | 1823 VisitWord64Compare(this, node, &cont); |
| 1797 } | 1824 } |
| 1798 | 1825 |
| 1799 | 1826 |
| 1800 void InstructionSelector::VisitFloat32Equal(Node* node) { | 1827 void InstructionSelector::VisitFloat32Equal(Node* node) { |
| 1801 FlagsContinuation cont(kUnorderedEqual, node); | 1828 FlagsContinuation cont = FlagsContinuation::ForSet(kUnorderedEqual, node); |
| 1802 VisitFloat32Compare(this, node, &cont); | 1829 VisitFloat32Compare(this, node, &cont); |
| 1803 } | 1830 } |
| 1804 | 1831 |
| 1805 | 1832 |
| 1806 void InstructionSelector::VisitFloat32LessThan(Node* node) { | 1833 void InstructionSelector::VisitFloat32LessThan(Node* node) { |
| 1807 FlagsContinuation cont(kUnsignedGreaterThan, node); | 1834 FlagsContinuation cont = |
| 1835 FlagsContinuation::ForSet(kUnsignedGreaterThan, node); |
| 1808 VisitFloat32Compare(this, node, &cont); | 1836 VisitFloat32Compare(this, node, &cont); |
| 1809 } | 1837 } |
| 1810 | 1838 |
| 1811 | 1839 |
| 1812 void InstructionSelector::VisitFloat32LessThanOrEqual(Node* node) { | 1840 void InstructionSelector::VisitFloat32LessThanOrEqual(Node* node) { |
| 1813 FlagsContinuation cont(kUnsignedGreaterThanOrEqual, node); | 1841 FlagsContinuation cont = |
| 1842 FlagsContinuation::ForSet(kUnsignedGreaterThanOrEqual, node); |
| 1814 VisitFloat32Compare(this, node, &cont); | 1843 VisitFloat32Compare(this, node, &cont); |
| 1815 } | 1844 } |
| 1816 | 1845 |
| 1817 | 1846 |
| 1818 void InstructionSelector::VisitFloat64Equal(Node* node) { | 1847 void InstructionSelector::VisitFloat64Equal(Node* node) { |
| 1819 FlagsContinuation cont(kUnorderedEqual, node); | 1848 FlagsContinuation cont = FlagsContinuation::ForSet(kUnorderedEqual, node); |
| 1820 VisitFloat64Compare(this, node, &cont); | 1849 VisitFloat64Compare(this, node, &cont); |
| 1821 } | 1850 } |
| 1822 | 1851 |
| 1823 | 1852 |
| 1824 void InstructionSelector::VisitFloat64LessThan(Node* node) { | 1853 void InstructionSelector::VisitFloat64LessThan(Node* node) { |
| 1825 FlagsContinuation cont(kUnsignedGreaterThan, node); | 1854 FlagsContinuation cont = |
| 1855 FlagsContinuation::ForSet(kUnsignedGreaterThan, node); |
| 1826 VisitFloat64Compare(this, node, &cont); | 1856 VisitFloat64Compare(this, node, &cont); |
| 1827 } | 1857 } |
| 1828 | 1858 |
| 1829 | 1859 |
| 1830 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { | 1860 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { |
| 1831 FlagsContinuation cont(kUnsignedGreaterThanOrEqual, node); | 1861 FlagsContinuation cont = |
| 1862 FlagsContinuation::ForSet(kUnsignedGreaterThanOrEqual, node); |
| 1832 VisitFloat64Compare(this, node, &cont); | 1863 VisitFloat64Compare(this, node, &cont); |
| 1833 } | 1864 } |
| 1834 | 1865 |
| 1835 | 1866 |
| 1836 void InstructionSelector::VisitFloat64ExtractLowWord32(Node* node) { | 1867 void InstructionSelector::VisitFloat64ExtractLowWord32(Node* node) { |
| 1837 X64OperandGenerator g(this); | 1868 X64OperandGenerator g(this); |
| 1838 Emit(kSSEFloat64ExtractLowWord32, g.DefineAsRegister(node), | 1869 Emit(kSSEFloat64ExtractLowWord32, g.DefineAsRegister(node), |
| 1839 g.Use(node->InputAt(0))); | 1870 g.Use(node->InputAt(0))); |
| 1840 } | 1871 } |
| 1841 | 1872 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1893 MachineOperatorBuilder::kFloat64RoundTruncate | | 1924 MachineOperatorBuilder::kFloat64RoundTruncate | |
| 1894 MachineOperatorBuilder::kFloat32RoundTiesEven | | 1925 MachineOperatorBuilder::kFloat32RoundTiesEven | |
| 1895 MachineOperatorBuilder::kFloat64RoundTiesEven; | 1926 MachineOperatorBuilder::kFloat64RoundTiesEven; |
| 1896 } | 1927 } |
| 1897 return flags; | 1928 return flags; |
| 1898 } | 1929 } |
| 1899 | 1930 |
| 1900 } // namespace compiler | 1931 } // namespace compiler |
| 1901 } // namespace internal | 1932 } // namespace internal |
| 1902 } // namespace v8 | 1933 } // namespace v8 |
| OLD | NEW |