Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(536)

Side by Side Diff: src/compiler/simplified-lowering.cc

Issue 2202413002: [turbofan] Improve typing rule for modulus. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Some cleanup plus use type feedback properly. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/operation-typer.cc ('k') | src/type-cache.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/operation-typer.cc ('k') | src/type-cache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698