| 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 1157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1168 | 1168 |
| 1169 // default case => Float64Add/Sub | 1169 // default case => Float64Add/Sub |
| 1170 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), | 1170 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), |
| 1171 MachineRepresentation::kFloat64, Type::Number()); | 1171 MachineRepresentation::kFloat64, Type::Number()); |
| 1172 if (lower()) { | 1172 if (lower()) { |
| 1173 ChangeToPureOp(node, Float64Op(node)); | 1173 ChangeToPureOp(node, Float64Op(node)); |
| 1174 } | 1174 } |
| 1175 return; | 1175 return; |
| 1176 } | 1176 } |
| 1177 | 1177 |
| 1178 void VisitSpeculativeNumberModulus(Node* node, Truncation truncation, |
| 1179 SimplifiedLowering* lowering) { |
| 1180 // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we |
| 1181 // can only eliminate an unused speculative number operation if we know |
| 1182 // that the inputs are PlainPrimitive, which excludes everything that's |
| 1183 // might have side effects or throws during a ToNumber conversion. |
| 1184 if (BothInputsAre(node, Type::PlainPrimitive())) { |
| 1185 if (truncation.IsUnused()) return VisitUnused(node); |
| 1186 } |
| 1187 if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) && |
| 1188 (truncation.IsUsedAsWord32() || |
| 1189 NodeProperties::GetType(node)->Is(Type::Unsigned32()))) { |
| 1190 // => unsigned Uint32Mod |
| 1191 VisitWord32TruncatingBinop(node); |
| 1192 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); |
| 1193 return; |
| 1194 } |
| 1195 if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) && |
| 1196 (truncation.IsUsedAsWord32() || |
| 1197 NodeProperties::GetType(node)->Is(Type::Signed32()))) { |
| 1198 // => signed Int32Mod |
| 1199 VisitWord32TruncatingBinop(node); |
| 1200 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); |
| 1201 return; |
| 1202 } |
| 1203 |
| 1204 // Try to use type feedback. |
| 1205 NumberOperationHint hint = NumberOperationHintOf(node->op()); |
| 1206 |
| 1207 // Handle the case when no uint32 checks on inputs are necessary |
| 1208 // (but an overflow check is needed on the output). |
| 1209 if (BothInputsAreUnsigned32(node)) { |
| 1210 if (hint == NumberOperationHint::kSignedSmall || |
| 1211 hint == NumberOperationHint::kSigned32) { |
| 1212 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 1213 MachineRepresentation::kWord32, Type::Unsigned32()); |
| 1214 if (lower()) ChangeToUint32OverflowOp(node); |
| 1215 return; |
| 1216 } |
| 1217 } |
| 1218 |
| 1219 // Handle the case when no int32 checks on inputs are necessary |
| 1220 // (but an overflow check is needed on the output). |
| 1221 if (BothInputsAre(node, Type::Signed32())) { |
| 1222 // If both the inputs the feedback are int32, use the overflow op. |
| 1223 if (hint == NumberOperationHint::kSignedSmall || |
| 1224 hint == NumberOperationHint::kSigned32) { |
| 1225 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 1226 MachineRepresentation::kWord32, Type::Signed32()); |
| 1227 if (lower()) ChangeToInt32OverflowOp(node); |
| 1228 return; |
| 1229 } |
| 1230 } |
| 1231 |
| 1232 if (hint == NumberOperationHint::kSignedSmall || |
| 1233 hint == NumberOperationHint::kSigned32) { |
| 1234 // If the result is truncated, we only need to check the inputs. |
| 1235 if (truncation.IsUsedAsWord32()) { |
| 1236 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), |
| 1237 MachineRepresentation::kWord32); |
| 1238 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); |
| 1239 } else if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN())) { |
| 1240 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), |
| 1241 MachineRepresentation::kWord32, Type::Unsigned32()); |
| 1242 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); |
| 1243 } else { |
| 1244 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), |
| 1245 MachineRepresentation::kWord32, Type::Signed32()); |
| 1246 if (lower()) ChangeToInt32OverflowOp(node); |
| 1247 } |
| 1248 return; |
| 1249 } |
| 1250 |
| 1251 if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) && |
| 1252 TypeOf(node->InputAt(1))->Is(Type::Unsigned32()) && |
| 1253 (truncation.IsUsedAsWord32() || |
| 1254 NodeProperties::GetType(node)->Is(Type::Unsigned32()))) { |
| 1255 // We can only promise Float64 truncation here, as the decision is |
| 1256 // based on the feedback types of the inputs. |
| 1257 VisitBinop(node, |
| 1258 UseInfo(MachineRepresentation::kWord32, Truncation::Float64()), |
| 1259 MachineRepresentation::kWord32); |
| 1260 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); |
| 1261 return; |
| 1262 } |
| 1263 if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) && |
| 1264 TypeOf(node->InputAt(1))->Is(Type::Signed32()) && |
| 1265 (truncation.IsUsedAsWord32() || |
| 1266 NodeProperties::GetType(node)->Is(Type::Signed32()))) { |
| 1267 // We can only promise Float64 truncation here, as the decision is |
| 1268 // based on the feedback types of the inputs. |
| 1269 VisitBinop(node, |
| 1270 UseInfo(MachineRepresentation::kWord32, Truncation::Float64()), |
| 1271 MachineRepresentation::kWord32); |
| 1272 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); |
| 1273 return; |
| 1274 } |
| 1275 // default case => Float64Mod |
| 1276 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), |
| 1277 MachineRepresentation::kFloat64, Type::Number()); |
| 1278 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
| 1279 return; |
| 1280 } |
| 1281 |
| 1178 // Dispatching routine for visiting the node {node} with the usage {use}. | 1282 // Dispatching routine for visiting the node {node} with the usage {use}. |
| 1179 // Depending on the operator, propagate new usage info to the inputs. | 1283 // Depending on the operator, propagate new usage info to the inputs. |
| 1180 void VisitNode(Node* node, Truncation truncation, | 1284 void VisitNode(Node* node, Truncation truncation, |
| 1181 SimplifiedLowering* lowering) { | 1285 SimplifiedLowering* lowering) { |
| 1182 // Unconditionally eliminate unused pure nodes (only relevant if there's | 1286 // Unconditionally eliminate unused pure nodes (only relevant if there's |
| 1183 // a pure operation in between two effectful ones, where the last one | 1287 // a pure operation in between two effectful ones, where the last one |
| 1184 // is unused). | 1288 // is unused). |
| 1185 // Note: We must not do this for constants, as they are cached and we | 1289 // Note: We must not do this for constants, as they are cached and we |
| 1186 // would thus kill the cached {node} during lowering (i.e. replace all | 1290 // would thus kill the cached {node} during lowering (i.e. replace all |
| 1187 // uses with Dead), but at that point some node lowering might have | 1291 // uses with Dead), but at that point some node lowering might have |
| (...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1585 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1689 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
| 1586 return; | 1690 return; |
| 1587 } | 1691 } |
| 1588 // Checked float64 x float64 => float64 | 1692 // Checked float64 x float64 => float64 |
| 1589 DCHECK_EQ(IrOpcode::kSpeculativeNumberDivide, node->opcode()); | 1693 DCHECK_EQ(IrOpcode::kSpeculativeNumberDivide, node->opcode()); |
| 1590 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), | 1694 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), |
| 1591 MachineRepresentation::kFloat64, Type::Number()); | 1695 MachineRepresentation::kFloat64, Type::Number()); |
| 1592 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1696 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
| 1593 return; | 1697 return; |
| 1594 } | 1698 } |
| 1595 case IrOpcode::kSpeculativeNumberModulus: { | 1699 case IrOpcode::kSpeculativeNumberModulus: |
| 1596 // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we | 1700 return VisitSpeculativeNumberModulus(node, truncation, lowering); |
| 1597 // can only eliminate an unused speculative number operation if we know | |
| 1598 // that the inputs are PlainPrimitive, which excludes everything that's | |
| 1599 // might have side effects or throws during a ToNumber conversion. | |
| 1600 if (BothInputsAre(node, Type::PlainPrimitive())) { | |
| 1601 if (truncation.IsUnused()) return VisitUnused(node); | |
| 1602 } | |
| 1603 if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) && | |
| 1604 (truncation.IsUsedAsWord32() || | |
| 1605 NodeProperties::GetType(node)->Is(Type::Unsigned32()))) { | |
| 1606 // => unsigned Uint32Mod | |
| 1607 VisitWord32TruncatingBinop(node); | |
| 1608 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); | |
| 1609 return; | |
| 1610 } | |
| 1611 if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) && | |
| 1612 (truncation.IsUsedAsWord32() || | |
| 1613 NodeProperties::GetType(node)->Is(Type::Signed32()))) { | |
| 1614 // => signed Int32Mod | |
| 1615 VisitWord32TruncatingBinop(node); | |
| 1616 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | |
| 1617 return; | |
| 1618 } | |
| 1619 | |
| 1620 // Try to use type feedback. | |
| 1621 NumberOperationHint hint = NumberOperationHintOf(node->op()); | |
| 1622 | |
| 1623 // Handle the case when no uint32 checks on inputs are necessary | |
| 1624 // (but an overflow check is needed on the output). | |
| 1625 if (BothInputsAreUnsigned32(node)) { | |
| 1626 if (hint == NumberOperationHint::kSignedSmall || | |
| 1627 hint == NumberOperationHint::kSigned32) { | |
| 1628 VisitBinop(node, UseInfo::TruncatingWord32(), | |
| 1629 MachineRepresentation::kWord32, Type::Unsigned32()); | |
| 1630 if (lower()) ChangeToUint32OverflowOp(node); | |
| 1631 return; | |
| 1632 } | |
| 1633 } | |
| 1634 | |
| 1635 // Handle the case when no int32 checks on inputs are necessary | |
| 1636 // (but an overflow check is needed on the output). | |
| 1637 if (BothInputsAre(node, Type::Signed32())) { | |
| 1638 // If both the inputs the feedback are int32, use the overflow op. | |
| 1639 if (hint == NumberOperationHint::kSignedSmall || | |
| 1640 hint == NumberOperationHint::kSigned32) { | |
| 1641 VisitBinop(node, UseInfo::TruncatingWord32(), | |
| 1642 MachineRepresentation::kWord32, Type::Signed32()); | |
| 1643 if (lower()) ChangeToInt32OverflowOp(node); | |
| 1644 return; | |
| 1645 } | |
| 1646 } | |
| 1647 | |
| 1648 if (hint == NumberOperationHint::kSignedSmall || | |
| 1649 hint == NumberOperationHint::kSigned32) { | |
| 1650 // If the result is truncated, we only need to check the inputs. | |
| 1651 if (truncation.IsUsedAsWord32()) { | |
| 1652 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), | |
| 1653 MachineRepresentation::kWord32); | |
| 1654 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | |
| 1655 } else { | |
| 1656 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), | |
| 1657 MachineRepresentation::kWord32, Type::Signed32()); | |
| 1658 if (lower()) ChangeToInt32OverflowOp(node); | |
| 1659 } | |
| 1660 return; | |
| 1661 } | |
| 1662 | |
| 1663 if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) && | |
| 1664 TypeOf(node->InputAt(1))->Is(Type::Unsigned32()) && | |
| 1665 (truncation.IsUsedAsWord32() || | |
| 1666 NodeProperties::GetType(node)->Is(Type::Unsigned32()))) { | |
| 1667 // We can only promise Float64 truncation here, as the decision is | |
| 1668 // based on the feedback types of the inputs. | |
| 1669 VisitBinop(node, UseInfo(MachineRepresentation::kWord32, | |
| 1670 Truncation::Float64()), | |
| 1671 MachineRepresentation::kWord32); | |
| 1672 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); | |
| 1673 return; | |
| 1674 } | |
| 1675 if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) && | |
| 1676 TypeOf(node->InputAt(1))->Is(Type::Signed32()) && | |
| 1677 (truncation.IsUsedAsWord32() || | |
| 1678 NodeProperties::GetType(node)->Is(Type::Signed32()))) { | |
| 1679 // We can only promise Float64 truncation here, as the decision is | |
| 1680 // based on the feedback types of the inputs. | |
| 1681 VisitBinop(node, UseInfo(MachineRepresentation::kWord32, | |
| 1682 Truncation::Float64()), | |
| 1683 MachineRepresentation::kWord32); | |
| 1684 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | |
| 1685 return; | |
| 1686 } | |
| 1687 // default case => Float64Mod | |
| 1688 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), | |
| 1689 MachineRepresentation::kFloat64, Type::Number()); | |
| 1690 if (lower()) ChangeToPureOp(node, Float64Op(node)); | |
| 1691 return; | |
| 1692 } | |
| 1693 case IrOpcode::kNumberModulus: { | 1701 case IrOpcode::kNumberModulus: { |
| 1694 if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) && | 1702 if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) && |
| 1695 (truncation.IsUsedAsWord32() || | 1703 (truncation.IsUsedAsWord32() || |
| 1696 NodeProperties::GetType(node)->Is(Type::Unsigned32()))) { | 1704 NodeProperties::GetType(node)->Is(Type::Unsigned32()))) { |
| 1697 // => unsigned Uint32Mod | 1705 // => unsigned Uint32Mod |
| 1698 VisitWord32TruncatingBinop(node); | 1706 VisitWord32TruncatingBinop(node); |
| 1699 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); | 1707 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); |
| 1700 return; | 1708 return; |
| 1701 } | 1709 } |
| 1702 if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) && | 1710 if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) && |
| (...skipping 1626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3329 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 3337 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
| 3330 Operator::kNoProperties); | 3338 Operator::kNoProperties); |
| 3331 to_number_operator_.set(common()->Call(desc)); | 3339 to_number_operator_.set(common()->Call(desc)); |
| 3332 } | 3340 } |
| 3333 return to_number_operator_.get(); | 3341 return to_number_operator_.get(); |
| 3334 } | 3342 } |
| 3335 | 3343 |
| 3336 } // namespace compiler | 3344 } // namespace compiler |
| 3337 } // namespace internal | 3345 } // namespace internal |
| 3338 } // namespace v8 | 3346 } // namespace v8 |
| OLD | NEW |