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 |