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 "src/compiler/simplified-lowering.h" | 5 #include "src/compiler/simplified-lowering.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "src/address-map.h" | 9 #include "src/address-map.h" |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
670 bool BothInputsAreUnsigned32(Node* node) { | 670 bool BothInputsAreUnsigned32(Node* node) { |
671 return BothInputsAre(node, Type::Unsigned32()); | 671 return BothInputsAre(node, Type::Unsigned32()); |
672 } | 672 } |
673 | 673 |
674 bool BothInputsAre(Node* node, Type* type) { | 674 bool BothInputsAre(Node* node, Type* type) { |
675 DCHECK_EQ(2, node->op()->ValueInputCount()); | 675 DCHECK_EQ(2, node->op()->ValueInputCount()); |
676 return GetUpperBound(node->InputAt(0))->Is(type) && | 676 return GetUpperBound(node->InputAt(0))->Is(type) && |
677 GetUpperBound(node->InputAt(1))->Is(type); | 677 GetUpperBound(node->InputAt(1))->Is(type); |
678 } | 678 } |
679 | 679 |
| 680 bool OneInputCannotBe(Node* node, Type* type) { |
| 681 DCHECK_EQ(2, node->op()->ValueInputCount()); |
| 682 return !GetUpperBound(node->InputAt(0))->Maybe(type) || |
| 683 !GetUpperBound(node->InputAt(1))->Maybe(type); |
| 684 } |
| 685 |
680 void ConvertInput(Node* node, int index, UseInfo use) { | 686 void ConvertInput(Node* node, int index, UseInfo use) { |
681 Node* input = node->InputAt(index); | 687 Node* input = node->InputAt(index); |
682 // In the change phase, insert a change before the use if necessary. | 688 // In the change phase, insert a change before the use if necessary. |
683 if (use.representation() == MachineRepresentation::kNone) | 689 if (use.representation() == MachineRepresentation::kNone) |
684 return; // No input requirement on the use. | 690 return; // No input requirement on the use. |
685 DCHECK_NOT_NULL(input); | 691 DCHECK_NOT_NULL(input); |
686 NodeInfo* input_info = GetInfo(input); | 692 NodeInfo* input_info = GetInfo(input); |
687 MachineRepresentation input_rep = input_info->representation(); | 693 MachineRepresentation input_rep = input_info->representation(); |
688 if (input_rep != use.representation() || | 694 if (input_rep != use.representation() || |
689 use.type_check() != TypeCheckKind::kNone) { | 695 use.type_check() != TypeCheckKind::kNone) { |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1120 | 1126 |
1121 void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation, | 1127 void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation, |
1122 SimplifiedLowering* lowering) { | 1128 SimplifiedLowering* lowering) { |
1123 // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we can | 1129 // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we can |
1124 // only eliminate an unused speculative number operation if we know that | 1130 // only eliminate an unused speculative number operation if we know that |
1125 // the inputs are PlainPrimitive, which excludes everything that's might | 1131 // the inputs are PlainPrimitive, which excludes everything that's might |
1126 // have side effects or throws during a ToNumber conversion. | 1132 // have side effects or throws during a ToNumber conversion. |
1127 if (BothInputsAre(node, Type::PlainPrimitive())) { | 1133 if (BothInputsAre(node, Type::PlainPrimitive())) { |
1128 if (truncation.IsUnused()) return VisitUnused(node); | 1134 if (truncation.IsUnused()) return VisitUnused(node); |
1129 } | 1135 } |
1130 if (BothInputsAre(node, type_cache_.kSigned32OrMinusZero) && | 1136 if (BothInputsAre(node, Type::Signed32OrMinusZero()) && |
1131 NodeProperties::GetType(node)->Is(Type::Signed32())) { | 1137 NodeProperties::GetType(node)->Is(Type::Signed32())) { |
1132 // int32 + int32 = int32 ==> signed Int32Add/Sub | 1138 // int32 + int32 = int32 ==> signed Int32Add/Sub |
1133 VisitInt32Binop(node); | 1139 VisitInt32Binop(node); |
1134 if (lower()) ChangeToPureOp(node, Int32Op(node)); | 1140 if (lower()) ChangeToPureOp(node, Int32Op(node)); |
1135 return; | 1141 return; |
1136 } | 1142 } |
1137 | 1143 |
1138 // Use truncation if available. | 1144 // Use truncation if available. |
1139 if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) && | 1145 if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) && |
1140 truncation.IsUsedAsWord32()) { | 1146 truncation.IsUsedAsWord32()) { |
1141 // safe-int + safe-int = x (truncated to int32) | 1147 // safe-int + safe-int = x (truncated to int32) |
1142 // => signed Int32Add/Sub (truncated) | 1148 // => signed Int32Add/Sub (truncated) |
1143 VisitWord32TruncatingBinop(node); | 1149 VisitWord32TruncatingBinop(node); |
1144 if (lower()) ChangeToPureOp(node, Int32Op(node)); | 1150 if (lower()) ChangeToPureOp(node, Int32Op(node)); |
1145 return; | 1151 return; |
1146 } | 1152 } |
1147 | 1153 |
1148 // Try to use type feedback. | 1154 // Try to use type feedback. |
1149 BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); | 1155 BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); |
1150 | 1156 |
1151 // Handle the case when no int32 checks on inputs are necessary | 1157 // Handle the case when no int32 checks on inputs are necessary |
1152 // (but an overflow check is needed on the output). | 1158 // (but an overflow check is needed on the output). |
1153 if (BothInputsAre(node, Type::Signed32()) || | 1159 if (BothInputsAre(node, Type::Signed32()) || |
1154 (BothInputsAre(node, type_cache_.kSigned32OrMinusZero) && | 1160 (BothInputsAre(node, Type::Signed32OrMinusZero()) && |
1155 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger))) { | 1161 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger))) { |
1156 // If both the inputs the feedback are int32, use the overflow op. | 1162 // If both the inputs the feedback are int32, use the overflow op. |
1157 if (hint == BinaryOperationHints::kSignedSmall || | 1163 if (hint == BinaryOperationHints::kSignedSmall || |
1158 hint == BinaryOperationHints::kSigned32) { | 1164 hint == BinaryOperationHints::kSigned32) { |
1159 VisitBinop(node, UseInfo::TruncatingWord32(), | 1165 VisitBinop(node, UseInfo::TruncatingWord32(), |
1160 MachineRepresentation::kWord32, Type::Signed32()); | 1166 MachineRepresentation::kWord32, Type::Signed32()); |
1161 if (lower()) ChangeToInt32OverflowOp(node); | 1167 if (lower()) ChangeToInt32OverflowOp(node); |
1162 return; | 1168 return; |
1163 } | 1169 } |
1164 } | 1170 } |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1283 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant()); | 1289 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant()); |
1284 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); | 1290 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); |
1285 } | 1291 } |
1286 } else { | 1292 } else { |
1287 // No input representation requirement; adapt during lowering. | 1293 // No input representation requirement; adapt during lowering. |
1288 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool()); | 1294 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool()); |
1289 SetOutput(node, MachineRepresentation::kBit); | 1295 SetOutput(node, MachineRepresentation::kBit); |
1290 } | 1296 } |
1291 return; | 1297 return; |
1292 } | 1298 } |
1293 case IrOpcode::kNumberEqual: | 1299 case IrOpcode::kNumberEqual: { |
| 1300 Type* const lhs_type = TypeOf(node->InputAt(0)); |
| 1301 Type* const rhs_type = TypeOf(node->InputAt(1)); |
| 1302 // Number comparisons reduce to integer comparisons for integer inputs. |
| 1303 if ((lhs_type->Is(Type::Unsigned32()) && |
| 1304 rhs_type->Is(Type::Unsigned32())) || |
| 1305 (lhs_type->Is(Type::Unsigned32OrMinusZeroOrNaN()) && |
| 1306 rhs_type->Is(Type::Unsigned32OrMinusZeroOrNaN()) && |
| 1307 OneInputCannotBe(node, type_cache_.kZeroish))) { |
| 1308 // => unsigned Int32Cmp |
| 1309 VisitUint32Cmp(node); |
| 1310 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); |
| 1311 return; |
| 1312 } |
| 1313 if ((lhs_type->Is(Type::Signed32()) && |
| 1314 rhs_type->Is(Type::Signed32())) || |
| 1315 (lhs_type->Is(Type::Signed32OrMinusZeroOrNaN()) && |
| 1316 rhs_type->Is(Type::Signed32OrMinusZeroOrNaN()) && |
| 1317 OneInputCannotBe(node, type_cache_.kZeroish))) { |
| 1318 // => signed Int32Cmp |
| 1319 VisitInt32Cmp(node); |
| 1320 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
| 1321 return; |
| 1322 } |
| 1323 // => Float64Cmp |
| 1324 VisitFloat64Cmp(node); |
| 1325 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
| 1326 return; |
| 1327 } |
1294 case IrOpcode::kNumberLessThan: | 1328 case IrOpcode::kNumberLessThan: |
1295 case IrOpcode::kNumberLessThanOrEqual: { | 1329 case IrOpcode::kNumberLessThanOrEqual: { |
1296 // Number comparisons reduce to integer comparisons for integer inputs. | 1330 // Number comparisons reduce to integer comparisons for integer inputs. |
1297 if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) && | 1331 if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) && |
1298 TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) { | 1332 TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) { |
1299 // => unsigned Int32Cmp | 1333 // => unsigned Int32Cmp |
1300 VisitUint32Cmp(node); | 1334 VisitUint32Cmp(node); |
1301 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); | 1335 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); |
1302 } else if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) && | 1336 } else if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) && |
1303 TypeOf(node->InputAt(1))->Is(Type::Signed32())) { | 1337 TypeOf(node->InputAt(1))->Is(Type::Signed32())) { |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1573 return; | 1607 return; |
1574 } | 1608 } |
1575 case IrOpcode::kSpeculativeNumberModulus: { | 1609 case IrOpcode::kSpeculativeNumberModulus: { |
1576 // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we | 1610 // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we |
1577 // can only eliminate an unused speculative number operation if we know | 1611 // can only eliminate an unused speculative number operation if we know |
1578 // that the inputs are PlainPrimitive, which excludes everything that's | 1612 // that the inputs are PlainPrimitive, which excludes everything that's |
1579 // might have side effects or throws during a ToNumber conversion. | 1613 // might have side effects or throws during a ToNumber conversion. |
1580 if (BothInputsAre(node, Type::PlainPrimitive())) { | 1614 if (BothInputsAre(node, Type::PlainPrimitive())) { |
1581 if (truncation.IsUnused()) return VisitUnused(node); | 1615 if (truncation.IsUnused()) return VisitUnused(node); |
1582 } | 1616 } |
1583 if (BothInputsAreUnsigned32(node) && truncation.IsUsedAsWord32()) { | 1617 if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) && |
| 1618 (truncation.IsUsedAsWord32() || |
| 1619 NodeProperties::GetType(node)->Is(Type::Unsigned32()))) { |
1584 // => unsigned Uint32Mod | 1620 // => unsigned Uint32Mod |
1585 VisitWord32TruncatingBinop(node); | 1621 VisitWord32TruncatingBinop(node); |
1586 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); | 1622 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); |
1587 return; | 1623 return; |
1588 } | 1624 } |
1589 if (BothInputsAreSigned32(node)) { | 1625 if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) && |
1590 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { | 1626 (truncation.IsUsedAsWord32() || |
1591 // => signed Int32Mod | 1627 NodeProperties::GetType(node)->Is(Type::Signed32()))) { |
1592 VisitInt32Binop(node); | 1628 // => signed Int32Mod |
1593 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | 1629 VisitWord32TruncatingBinop(node); |
1594 return; | 1630 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); |
1595 } | 1631 return; |
1596 if (truncation.IsUsedAsWord32()) { | |
1597 // => signed Int32Mod | |
1598 VisitWord32TruncatingBinop(node); | |
1599 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | |
1600 return; | |
1601 } | |
1602 } | 1632 } |
1603 | 1633 |
1604 // Try to use type feedback. | 1634 // Try to use type feedback. |
1605 BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); | 1635 BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); |
1606 | 1636 |
1607 // Handle the case when no uint32 checks on inputs are necessary | 1637 // Handle the case when no uint32 checks on inputs are necessary |
1608 // (but an overflow check is needed on the output). | 1638 // (but an overflow check is needed on the output). |
1609 if (BothInputsAreUnsigned32(node)) { | 1639 if (BothInputsAreUnsigned32(node)) { |
1610 if (hint == BinaryOperationHints::kSignedSmall || | 1640 if (hint == BinaryOperationHints::kSignedSmall || |
1611 hint == BinaryOperationHints::kSigned32) { | 1641 hint == BinaryOperationHints::kSigned32) { |
(...skipping 25 matching lines...) Expand all Loading... |
1637 MachineRepresentation::kWord32); | 1667 MachineRepresentation::kWord32); |
1638 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | 1668 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); |
1639 } else { | 1669 } else { |
1640 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), | 1670 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), |
1641 MachineRepresentation::kWord32, Type::Signed32()); | 1671 MachineRepresentation::kWord32, Type::Signed32()); |
1642 if (lower()) ChangeToInt32OverflowOp(node); | 1672 if (lower()) ChangeToInt32OverflowOp(node); |
1643 } | 1673 } |
1644 return; | 1674 return; |
1645 } | 1675 } |
1646 | 1676 |
| 1677 if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) && |
| 1678 TypeOf(node->InputAt(1))->Is(Type::Unsigned32()) && |
| 1679 (truncation.IsUsedAsWord32() || |
| 1680 NodeProperties::GetType(node)->Is(Type::Unsigned32()))) { |
| 1681 // We can only promise Float64 truncation here, as the decision is |
| 1682 // based on the feedback types of the inputs. |
| 1683 VisitBinop(node, UseInfo(MachineRepresentation::kWord32, |
| 1684 Truncation::Float64()), |
| 1685 MachineRepresentation::kWord32); |
| 1686 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); |
| 1687 return; |
| 1688 } |
| 1689 if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) && |
| 1690 TypeOf(node->InputAt(1))->Is(Type::Signed32()) && |
| 1691 (truncation.IsUsedAsWord32() || |
| 1692 NodeProperties::GetType(node)->Is(Type::Signed32()))) { |
| 1693 // We can only promise Float64 truncation here, as the decision is |
| 1694 // based on the feedback types of the inputs. |
| 1695 VisitBinop(node, UseInfo(MachineRepresentation::kWord32, |
| 1696 Truncation::Float64()), |
| 1697 MachineRepresentation::kWord32); |
| 1698 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); |
| 1699 return; |
| 1700 } |
1647 // default case => Float64Mod | 1701 // default case => Float64Mod |
1648 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), | 1702 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), |
1649 MachineRepresentation::kFloat64, Type::Number()); | 1703 MachineRepresentation::kFloat64, Type::Number()); |
1650 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1704 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
1651 return; | 1705 return; |
1652 } | 1706 } |
1653 case IrOpcode::kNumberModulus: { | 1707 case IrOpcode::kNumberModulus: { |
1654 if (BothInputsAreUnsigned32(node) && truncation.IsUsedAsWord32()) { | 1708 if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) && |
| 1709 (truncation.IsUsedAsWord32() || |
| 1710 NodeProperties::GetType(node)->Is(Type::Unsigned32()))) { |
1655 // => unsigned Uint32Mod | 1711 // => unsigned Uint32Mod |
1656 VisitWord32TruncatingBinop(node); | 1712 VisitWord32TruncatingBinop(node); |
1657 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); | 1713 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); |
1658 return; | 1714 return; |
1659 } | 1715 } |
1660 if (BothInputsAreSigned32(node)) { | 1716 if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) && |
1661 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { | 1717 (truncation.IsUsedAsWord32() || |
1662 // => signed Int32Mod | 1718 NodeProperties::GetType(node)->Is(Type::Signed32()))) { |
1663 VisitInt32Binop(node); | 1719 // => signed Int32Mod |
1664 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | 1720 VisitWord32TruncatingBinop(node); |
1665 return; | 1721 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); |
1666 } | 1722 return; |
1667 if (truncation.IsUsedAsWord32()) { | |
1668 // => signed Int32Mod | |
1669 VisitWord32TruncatingBinop(node); | |
1670 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | |
1671 return; | |
1672 } | |
1673 } | 1723 } |
1674 // => Float64Mod | 1724 if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) && |
| 1725 TypeOf(node->InputAt(1))->Is(Type::Unsigned32()) && |
| 1726 (truncation.IsUsedAsWord32() || |
| 1727 NodeProperties::GetType(node)->Is(Type::Unsigned32()))) { |
| 1728 // We can only promise Float64 truncation here, as the decision is |
| 1729 // based on the feedback types of the inputs. |
| 1730 VisitBinop(node, UseInfo(MachineRepresentation::kWord32, |
| 1731 Truncation::Float64()), |
| 1732 MachineRepresentation::kWord32); |
| 1733 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); |
| 1734 return; |
| 1735 } |
| 1736 if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) && |
| 1737 TypeOf(node->InputAt(1))->Is(Type::Signed32()) && |
| 1738 (truncation.IsUsedAsWord32() || |
| 1739 NodeProperties::GetType(node)->Is(Type::Signed32()))) { |
| 1740 // We can only promise Float64 truncation here, as the decision is |
| 1741 // based on the feedback types of the inputs. |
| 1742 VisitBinop(node, UseInfo(MachineRepresentation::kWord32, |
| 1743 Truncation::Float64()), |
| 1744 MachineRepresentation::kWord32); |
| 1745 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); |
| 1746 return; |
| 1747 } |
| 1748 // default case => Float64Mod |
1675 VisitFloat64Binop(node); | 1749 VisitFloat64Binop(node); |
1676 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1750 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
1677 return; | 1751 return; |
1678 } | 1752 } |
1679 case IrOpcode::kNumberBitwiseOr: | 1753 case IrOpcode::kNumberBitwiseOr: |
1680 case IrOpcode::kNumberBitwiseXor: | 1754 case IrOpcode::kNumberBitwiseXor: |
1681 case IrOpcode::kNumberBitwiseAnd: { | 1755 case IrOpcode::kNumberBitwiseAnd: { |
1682 VisitInt32Binop(node); | 1756 VisitInt32Binop(node); |
1683 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 1757 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
1684 return; | 1758 return; |
(...skipping 1957 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3642 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 3716 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
3643 Operator::kNoProperties); | 3717 Operator::kNoProperties); |
3644 to_number_operator_.set(common()->Call(desc)); | 3718 to_number_operator_.set(common()->Call(desc)); |
3645 } | 3719 } |
3646 return to_number_operator_.get(); | 3720 return to_number_operator_.get(); |
3647 } | 3721 } |
3648 | 3722 |
3649 } // namespace compiler | 3723 } // namespace compiler |
3650 } // namespace internal | 3724 } // namespace internal |
3651 } // namespace v8 | 3725 } // namespace v8 |
OLD | NEW |