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/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 944 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
955 } | 955 } |
956 case IrOpcode::kNumberShiftRightLogical: { | 956 case IrOpcode::kNumberShiftRightLogical: { |
957 Type* rhs_type = GetUpperBound(node->InputAt(1)); | 957 Type* rhs_type = GetUpperBound(node->InputAt(1)); |
958 VisitBinop(node, UseInfo::TruncatingWord32(), | 958 VisitBinop(node, UseInfo::TruncatingWord32(), |
959 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); | 959 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); |
960 if (lower()) { | 960 if (lower()) { |
961 lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type); | 961 lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type); |
962 } | 962 } |
963 break; | 963 break; |
964 } | 964 } |
| 965 case IrOpcode::kNumberCeil: { |
| 966 VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64); |
| 967 if (lower()) DeferReplacement(node, lowering->Float64Ceil(node)); |
| 968 break; |
| 969 } |
965 case IrOpcode::kNumberFloor: { | 970 case IrOpcode::kNumberFloor: { |
966 VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64); | 971 VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64); |
967 if (lower()) DeferReplacement(node, lowering->Float64Floor(node)); | 972 if (lower()) DeferReplacement(node, lowering->Float64Floor(node)); |
968 break; | 973 break; |
969 } | 974 } |
| 975 case IrOpcode::kNumberRound: { |
| 976 VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64); |
| 977 if (lower()) DeferReplacement(node, lowering->Float64Round(node)); |
| 978 break; |
| 979 } |
| 980 case IrOpcode::kNumberTrunc: { |
| 981 VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64); |
| 982 if (lower()) DeferReplacement(node, lowering->Float64Trunc(node)); |
| 983 break; |
| 984 } |
970 case IrOpcode::kNumberToInt32: { | 985 case IrOpcode::kNumberToInt32: { |
971 // Just change representation if necessary. | 986 // Just change representation if necessary. |
972 VisitUnop(node, UseInfo::TruncatingWord32(), | 987 VisitUnop(node, UseInfo::TruncatingWord32(), |
973 MachineRepresentation::kWord32); | 988 MachineRepresentation::kWord32); |
974 if (lower()) DeferReplacement(node, node->InputAt(0)); | 989 if (lower()) DeferReplacement(node, node->InputAt(0)); |
975 break; | 990 break; |
976 } | 991 } |
977 case IrOpcode::kNumberToUint32: { | 992 case IrOpcode::kNumberToUint32: { |
978 // Just change representation if necessary. | 993 // Just change representation if necessary. |
979 VisitUnop(node, UseInfo::TruncatingWord32(), | 994 VisitUnop(node, UseInfo::TruncatingWord32(), |
(...skipping 537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1517 } | 1532 } |
1518 | 1533 |
1519 | 1534 |
1520 void SimplifiedLowering::DoStoreBuffer(Node* node) { | 1535 void SimplifiedLowering::DoStoreBuffer(Node* node) { |
1521 DCHECK_EQ(IrOpcode::kStoreBuffer, node->opcode()); | 1536 DCHECK_EQ(IrOpcode::kStoreBuffer, node->opcode()); |
1522 MachineRepresentation const rep = | 1537 MachineRepresentation const rep = |
1523 BufferAccessOf(node->op()).machine_type().representation(); | 1538 BufferAccessOf(node->op()).machine_type().representation(); |
1524 NodeProperties::ChangeOp(node, machine()->CheckedStore(rep)); | 1539 NodeProperties::ChangeOp(node, machine()->CheckedStore(rep)); |
1525 } | 1540 } |
1526 | 1541 |
| 1542 Node* SimplifiedLowering::Float64Ceil(Node* const node) { |
| 1543 Node* const one = jsgraph()->Float64Constant(1.0); |
| 1544 Node* const zero = jsgraph()->Float64Constant(0.0); |
| 1545 Node* const minus_zero = jsgraph()->Float64Constant(-0.0); |
| 1546 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0); |
| 1547 Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0); |
| 1548 Node* const input = node->InputAt(0); |
| 1549 |
| 1550 // Use fast hardware instruction if available. |
| 1551 if (machine()->Float64RoundUp().IsSupported()) { |
| 1552 return graph()->NewNode(machine()->Float64RoundUp().op(), input); |
| 1553 } |
| 1554 |
| 1555 // General case for ceil. |
| 1556 // |
| 1557 // if 0.0 < input then |
| 1558 // if 2^52 <= input then |
| 1559 // input |
| 1560 // else |
| 1561 // let temp1 = (2^52 + input) - 2^52 in |
| 1562 // if temp1 < input then |
| 1563 // temp1 + 1 |
| 1564 // else |
| 1565 // temp1 |
| 1566 // else |
| 1567 // if input == 0 then |
| 1568 // input |
| 1569 // else |
| 1570 // if input <= -2^52 then |
| 1571 // input |
| 1572 // else |
| 1573 // let temp1 = -0 - input in |
| 1574 // let temp2 = (2^52 + temp1) - 2^52 in |
| 1575 // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in |
| 1576 // -0 - temp3 |
| 1577 // |
| 1578 // Note: We do not use the Diamond helper class here, because it really hurts |
| 1579 // readability with nested diamonds. |
| 1580 |
| 1581 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input); |
| 1582 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, |
| 1583 graph()->start()); |
| 1584 |
| 1585 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); |
| 1586 Node* vtrue0; |
| 1587 { |
| 1588 Node* check1 = |
| 1589 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input); |
| 1590 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0); |
| 1591 |
| 1592 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 1593 Node* vtrue1 = input; |
| 1594 |
| 1595 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 1596 Node* vfalse1; |
| 1597 { |
| 1598 Node* temp1 = graph()->NewNode( |
| 1599 machine()->Float64Sub(), |
| 1600 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52); |
| 1601 vfalse1 = graph()->NewNode( |
| 1602 common()->Select(MachineRepresentation::kFloat64), |
| 1603 graph()->NewNode(machine()->Float64LessThan(), temp1, input), |
| 1604 graph()->NewNode(machine()->Float64Add(), temp1, one), temp1); |
| 1605 } |
| 1606 |
| 1607 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
| 1608 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
| 1609 vtrue1, vfalse1, if_true0); |
| 1610 } |
| 1611 |
| 1612 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); |
| 1613 Node* vfalse0; |
| 1614 { |
| 1615 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero); |
| 1616 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse), |
| 1617 check1, if_false0); |
| 1618 |
| 1619 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 1620 Node* vtrue1 = input; |
| 1621 |
| 1622 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 1623 Node* vfalse1; |
| 1624 { |
| 1625 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(), |
| 1626 input, minus_two_52); |
| 1627 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse), |
| 1628 check2, if_false1); |
| 1629 |
| 1630 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); |
| 1631 Node* vtrue2 = input; |
| 1632 |
| 1633 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); |
| 1634 Node* vfalse2; |
| 1635 { |
| 1636 Node* temp1 = |
| 1637 graph()->NewNode(machine()->Float64Sub(), minus_zero, input); |
| 1638 Node* temp2 = graph()->NewNode( |
| 1639 machine()->Float64Sub(), |
| 1640 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52); |
| 1641 Node* temp3 = graph()->NewNode( |
| 1642 common()->Select(MachineRepresentation::kFloat64), |
| 1643 graph()->NewNode(machine()->Float64LessThan(), temp1, temp2), |
| 1644 graph()->NewNode(machine()->Float64Sub(), temp2, one), temp2); |
| 1645 vfalse2 = graph()->NewNode(machine()->Float64Sub(), minus_zero, temp3); |
| 1646 } |
| 1647 |
| 1648 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); |
| 1649 vfalse1 = |
| 1650 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
| 1651 vtrue2, vfalse2, if_false1); |
| 1652 } |
| 1653 |
| 1654 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
| 1655 vfalse0 = |
| 1656 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
| 1657 vtrue1, vfalse1, if_false0); |
| 1658 } |
| 1659 |
| 1660 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0); |
| 1661 return graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
| 1662 vtrue0, vfalse0, merge0); |
| 1663 } |
| 1664 |
1527 Node* SimplifiedLowering::Float64Floor(Node* const node) { | 1665 Node* SimplifiedLowering::Float64Floor(Node* const node) { |
1528 Node* const one = jsgraph()->Float64Constant(1.0); | 1666 Node* const one = jsgraph()->Float64Constant(1.0); |
1529 Node* const zero = jsgraph()->Float64Constant(0.0); | 1667 Node* const zero = jsgraph()->Float64Constant(0.0); |
1530 Node* const minus_one = jsgraph()->Float64Constant(-1.0); | 1668 Node* const minus_one = jsgraph()->Float64Constant(-1.0); |
1531 Node* const minus_zero = jsgraph()->Float64Constant(-0.0); | 1669 Node* const minus_zero = jsgraph()->Float64Constant(-0.0); |
1532 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0); | 1670 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0); |
1533 Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0); | 1671 Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0); |
1534 Node* const input = node->InputAt(0); | 1672 Node* const input = node->InputAt(0); |
1535 | 1673 |
1536 // Use fast hardware instruction if available. | 1674 // Use fast hardware instruction if available. |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1643 vfalse0 = | 1781 vfalse0 = |
1644 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | 1782 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
1645 vtrue1, vfalse1, if_false0); | 1783 vtrue1, vfalse1, if_false0); |
1646 } | 1784 } |
1647 | 1785 |
1648 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | 1786 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0); |
1649 return graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | 1787 return graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
1650 vtrue0, vfalse0, merge0); | 1788 vtrue0, vfalse0, merge0); |
1651 } | 1789 } |
1652 | 1790 |
| 1791 Node* SimplifiedLowering::Float64Round(Node* const node) { |
| 1792 Node* const one = jsgraph()->Float64Constant(1.0); |
| 1793 Node* const one_half = jsgraph()->Float64Constant(0.5); |
| 1794 Node* const input = node->InputAt(0); |
| 1795 |
| 1796 // Round up towards Infinity, and adjust if the difference exceeds 0.5. |
| 1797 Node* result = Float64Ceil(node); |
| 1798 return graph()->NewNode( |
| 1799 common()->Select(MachineRepresentation::kFloat64), |
| 1800 graph()->NewNode( |
| 1801 machine()->Float64LessThanOrEqual(), |
| 1802 graph()->NewNode(machine()->Float64Sub(), result, one_half), input), |
| 1803 result, graph()->NewNode(machine()->Float64Sub(), result, one)); |
| 1804 } |
| 1805 |
| 1806 Node* SimplifiedLowering::Float64Trunc(Node* const node) { |
| 1807 Node* const one = jsgraph()->Float64Constant(1.0); |
| 1808 Node* const zero = jsgraph()->Float64Constant(0.0); |
| 1809 Node* const minus_zero = jsgraph()->Float64Constant(-0.0); |
| 1810 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0); |
| 1811 Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0); |
| 1812 Node* const input = node->InputAt(0); |
| 1813 |
| 1814 // Use fast hardware instruction if available. |
| 1815 if (machine()->Float64RoundTruncate().IsSupported()) { |
| 1816 return graph()->NewNode(machine()->Float64RoundTruncate().op(), input); |
| 1817 } |
| 1818 |
| 1819 // General case for trunc. |
| 1820 // |
| 1821 // if 0.0 < input then |
| 1822 // if 2^52 <= input then |
| 1823 // input |
| 1824 // else |
| 1825 // let temp1 = (2^52 + input) - 2^52 in |
| 1826 // if input < temp1 then |
| 1827 // temp1 - 1 |
| 1828 // else |
| 1829 // temp1 |
| 1830 // else |
| 1831 // if input == 0 then |
| 1832 // input |
| 1833 // else |
| 1834 // if input <= -2^52 then |
| 1835 // input |
| 1836 // else |
| 1837 // let temp1 = -0 - input in |
| 1838 // let temp2 = (2^52 + temp1) - 2^52 in |
| 1839 // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in |
| 1840 // -0 - temp3 |
| 1841 // |
| 1842 // Note: We do not use the Diamond helper class here, because it really hurts |
| 1843 // readability with nested diamonds. |
| 1844 |
| 1845 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input); |
| 1846 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, |
| 1847 graph()->start()); |
| 1848 |
| 1849 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); |
| 1850 Node* vtrue0; |
| 1851 { |
| 1852 Node* check1 = |
| 1853 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input); |
| 1854 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0); |
| 1855 |
| 1856 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 1857 Node* vtrue1 = input; |
| 1858 |
| 1859 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 1860 Node* vfalse1; |
| 1861 { |
| 1862 Node* temp1 = graph()->NewNode( |
| 1863 machine()->Float64Sub(), |
| 1864 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52); |
| 1865 vfalse1 = graph()->NewNode( |
| 1866 common()->Select(MachineRepresentation::kFloat64), |
| 1867 graph()->NewNode(machine()->Float64LessThan(), input, temp1), |
| 1868 graph()->NewNode(machine()->Float64Sub(), temp1, one), temp1); |
| 1869 } |
| 1870 |
| 1871 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
| 1872 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
| 1873 vtrue1, vfalse1, if_true0); |
| 1874 } |
| 1875 |
| 1876 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); |
| 1877 Node* vfalse0; |
| 1878 { |
| 1879 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero); |
| 1880 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse), |
| 1881 check1, if_false0); |
| 1882 |
| 1883 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 1884 Node* vtrue1 = input; |
| 1885 |
| 1886 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 1887 Node* vfalse1; |
| 1888 { |
| 1889 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(), |
| 1890 input, minus_two_52); |
| 1891 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse), |
| 1892 check2, if_false1); |
| 1893 |
| 1894 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); |
| 1895 Node* vtrue2 = input; |
| 1896 |
| 1897 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); |
| 1898 Node* vfalse2; |
| 1899 { |
| 1900 Node* temp1 = |
| 1901 graph()->NewNode(machine()->Float64Sub(), minus_zero, input); |
| 1902 Node* temp2 = graph()->NewNode( |
| 1903 machine()->Float64Sub(), |
| 1904 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52); |
| 1905 Node* temp3 = graph()->NewNode( |
| 1906 common()->Select(MachineRepresentation::kFloat64), |
| 1907 graph()->NewNode(machine()->Float64LessThan(), temp1, temp2), |
| 1908 graph()->NewNode(machine()->Float64Sub(), temp2, one), temp2); |
| 1909 vfalse2 = graph()->NewNode(machine()->Float64Sub(), minus_zero, temp3); |
| 1910 } |
| 1911 |
| 1912 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); |
| 1913 vfalse1 = |
| 1914 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
| 1915 vtrue2, vfalse2, if_false1); |
| 1916 } |
| 1917 |
| 1918 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
| 1919 vfalse0 = |
| 1920 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
| 1921 vtrue1, vfalse1, if_false0); |
| 1922 } |
| 1923 |
| 1924 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0); |
| 1925 return graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
| 1926 vtrue0, vfalse0, merge0); |
| 1927 } |
| 1928 |
1653 Node* SimplifiedLowering::Int32Div(Node* const node) { | 1929 Node* SimplifiedLowering::Int32Div(Node* const node) { |
1654 Int32BinopMatcher m(node); | 1930 Int32BinopMatcher m(node); |
1655 Node* const zero = jsgraph()->Int32Constant(0); | 1931 Node* const zero = jsgraph()->Int32Constant(0); |
1656 Node* const minus_one = jsgraph()->Int32Constant(-1); | 1932 Node* const minus_one = jsgraph()->Int32Constant(-1); |
1657 Node* const lhs = m.left().node(); | 1933 Node* const lhs = m.left().node(); |
1658 Node* const rhs = m.right().node(); | 1934 Node* const rhs = m.right().node(); |
1659 | 1935 |
1660 if (m.right().Is(-1)) { | 1936 if (m.right().Is(-1)) { |
1661 return graph()->NewNode(machine()->Int32Sub(), zero, lhs); | 1937 return graph()->NewNode(machine()->Int32Sub(), zero, lhs); |
1662 } else if (m.right().Is(0)) { | 1938 } else if (m.right().Is(0)) { |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1908 if (!rhs_type->Is(type_cache_.kZeroToThirtyOne)) { | 2184 if (!rhs_type->Is(type_cache_.kZeroToThirtyOne)) { |
1909 node->ReplaceInput(1, graph()->NewNode(machine()->Word32And(), rhs, | 2185 node->ReplaceInput(1, graph()->NewNode(machine()->Word32And(), rhs, |
1910 jsgraph()->Int32Constant(0x1f))); | 2186 jsgraph()->Int32Constant(0x1f))); |
1911 } | 2187 } |
1912 NodeProperties::ChangeOp(node, op); | 2188 NodeProperties::ChangeOp(node, op); |
1913 } | 2189 } |
1914 | 2190 |
1915 } // namespace compiler | 2191 } // namespace compiler |
1916 } // namespace internal | 2192 } // namespace internal |
1917 } // namespace v8 | 2193 } // namespace v8 |
OLD | NEW |