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 |