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 <limits> | 5 #include <limits> |
6 | 6 |
7 #include "src/compiler/access-builder.h" | 7 #include "src/compiler/access-builder.h" |
8 #include "src/compiler/change-lowering.h" | 8 #include "src/compiler/change-lowering.h" |
9 #include "src/compiler/control-builders.h" | 9 #include "src/compiler/control-builders.h" |
10 #include "src/compiler/generic-node-inl.h" | 10 #include "src/compiler/generic-node-inl.h" |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
51 void LowerAllNodes() { | 51 void LowerAllNodes() { |
52 this->End(); | 52 this->End(); |
53 lowering.LowerAllNodes(); | 53 lowering.LowerAllNodes(); |
54 } | 54 } |
55 | 55 |
56 void LowerAllNodesAndLowerChanges() { | 56 void LowerAllNodesAndLowerChanges() { |
57 this->End(); | 57 this->End(); |
58 typer.Run(jsgraph.graph(), MaybeHandle<Context>()); | 58 typer.Run(jsgraph.graph(), MaybeHandle<Context>()); |
59 lowering.LowerAllNodes(); | 59 lowering.LowerAllNodes(); |
60 | 60 |
61 { | |
62 FILE* dot_file = fopen("/tmp/test-lowered.dot", "w+"); | |
Michael Starzinger
2014/10/08 09:01:28
Looks like a left-over, let's drop it again.
titzer
2014/10/08 09:12:29
Done.
| |
63 OFStream dot_of(dot_file); | |
64 dot_of << AsDOT(*jsgraph.graph()); | |
65 fclose(dot_file); | |
66 } | |
67 | |
61 Zone* zone = this->zone(); | 68 Zone* zone = this->zone(); |
62 CompilationInfo info(zone->isolate(), zone); | 69 CompilationInfo info(zone->isolate(), zone); |
63 Linkage linkage( | 70 Linkage linkage( |
64 &info, Linkage::GetSimplifiedCDescriptor(zone, this->machine_sig_)); | 71 &info, Linkage::GetSimplifiedCDescriptor(zone, this->machine_sig_)); |
65 ChangeLowering lowering(&jsgraph, &linkage); | 72 ChangeLowering lowering(&jsgraph, &linkage); |
66 GraphReducer reducer(this->graph()); | 73 GraphReducer reducer(this->graph()); |
67 reducer.AddReducer(&lowering); | 74 reducer.AddReducer(&lowering); |
68 reducer.ReduceGraph(); | 75 reducer.ReduceGraph(); |
69 Verifier::Run(this->graph()); | 76 Verifier::Run(this->graph()); |
70 } | 77 } |
(...skipping 1499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1570 if (x <= Smi::kMinValue) continue; | 1577 if (x <= Smi::kMinValue) continue; |
1571 if (x >= Smi::kMaxValue) continue; | 1578 if (x >= Smi::kMaxValue) continue; |
1572 Handle<HeapNumber> expected = t.factory()->NewHeapNumber(x); | 1579 Handle<HeapNumber> expected = t.factory()->NewHeapNumber(x); |
1573 Object* result = t.Call(*num); | 1580 Object* result = t.Call(*num); |
1574 CHECK(expected->SameValue(result)); | 1581 CHECK(expected->SameValue(result)); |
1575 } | 1582 } |
1576 } | 1583 } |
1577 } | 1584 } |
1578 | 1585 |
1579 | 1586 |
1587 TEST(NumberMultiply_TruncatingToInt32) { | |
1588 int32_t constants[] = {-100, -10, -1, 0, 1, 100, 1000}; | |
1589 | |
1590 for (size_t i = 0; i < arraysize(constants); i++) { | |
1591 TestingGraph t(Type::Signed32()); | |
1592 Node* k = t.jsgraph.Constant(constants[i]); | |
1593 Node* mul = t.graph()->NewNode(t.simplified()->NumberMultiply(), t.p0, k); | |
1594 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), mul); | |
1595 t.Return(trunc); | |
1596 t.Lower(); | |
1597 | |
1598 CHECK_EQ(IrOpcode::kInt32Mul, mul->opcode()); | |
1599 } | |
1600 } | |
1601 | |
1602 | |
1603 TEST(RunNumberMultiply_TruncatingToInt32) { | |
1604 int32_t constants[] = {-100, -10, -1, 0, 1, 100, 1000, 3000999}; | |
1605 | |
1606 for (size_t i = 0; i < arraysize(constants); i++) { | |
1607 double k = static_cast<double>(constants[i]); | |
1608 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | |
1609 Node* num = t.NumberToInt32(t.Parameter(0)); | |
1610 Node* mul = t.NumberMultiply(num, t.jsgraph.Constant(k)); | |
1611 Node* trunc = t.NumberToInt32(mul); | |
1612 t.Return(trunc); | |
1613 | |
1614 if (Pipeline::SupportedTarget()) { | |
1615 t.LowerAllNodesAndLowerChanges(); | |
1616 t.GenerateCode(); | |
1617 | |
1618 FOR_INT32_INPUTS(i) { | |
1619 Handle<HeapNumber> num = t.factory()->NewHeapNumber(*i); | |
1620 int32_t x = DoubleToInt32(static_cast<double>(*i) * k); | |
1621 Handle<HeapNumber> expected = | |
1622 t.factory()->NewHeapNumber(static_cast<double>(x)); | |
1623 Object* result = t.Call(*num); | |
1624 CHECK(expected->SameValue(result)); | |
1625 } | |
1626 } | |
1627 } | |
1628 } | |
1629 | |
1630 | |
1631 TEST(RunNumberMultiply_TruncatingToUint32) { | |
1632 uint32_t constants[] = {0, 1, 2, 3, 4, 100, 1000, 1024, 2048, 3000999}; | |
1633 | |
1634 for (size_t i = 0; i < arraysize(constants); i++) { | |
1635 double k = static_cast<double>(constants[i]); | |
1636 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | |
1637 Node* num = t.NumberToUint32(t.Parameter(0)); | |
1638 Node* mul = t.NumberMultiply(num, t.jsgraph.Constant(k)); | |
1639 Node* trunc = t.NumberToUint32(mul); | |
1640 t.Return(trunc); | |
1641 | |
1642 if (Pipeline::SupportedTarget()) { | |
1643 t.LowerAllNodesAndLowerChanges(); | |
1644 t.GenerateCode(); | |
1645 | |
1646 FOR_UINT32_INPUTS(i) { | |
1647 Handle<HeapNumber> num = | |
1648 t.factory()->NewHeapNumber(static_cast<double>(*i)); | |
1649 uint32_t x = DoubleToUint32(static_cast<double>(*i) * k); | |
1650 Handle<HeapNumber> expected = | |
1651 t.factory()->NewHeapNumber(static_cast<double>(x)); | |
1652 Object* result = t.Call(*num); | |
1653 CHECK(expected->SameValue(result)); | |
1654 } | |
1655 } | |
1656 } | |
1657 } | |
1658 | |
1659 | |
1580 TEST(RunNumberDivide_2_TruncatingToUint32) { | 1660 TEST(RunNumberDivide_2_TruncatingToUint32) { |
1581 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | 1661 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
1582 Node* num = t.NumberToUint32(t.Parameter(0)); | 1662 Node* num = t.NumberToUint32(t.Parameter(0)); |
1583 Node* div = t.NumberDivide(num, t.jsgraph.Constant(2)); | 1663 Node* div = t.NumberDivide(num, t.jsgraph.Constant(2)); |
1584 Node* trunc = t.NumberToUint32(div); | 1664 Node* trunc = t.NumberToUint32(div); |
1585 t.Return(trunc); | 1665 t.Return(trunc); |
1586 | 1666 |
1587 if (Pipeline::SupportedTarget()) { | 1667 if (Pipeline::SupportedTarget()) { |
1588 t.LowerAllNodesAndLowerChanges(); | 1668 t.LowerAllNodesAndLowerChanges(); |
1589 { | |
1590 FILE* dot_file = fopen("/tmp/test.dot", "w+"); | |
1591 OFStream dot_of(dot_file); | |
1592 dot_of << AsDOT(*t.jsgraph.graph()); | |
1593 fclose(dot_file); | |
1594 } | |
1595 t.GenerateCode(); | 1669 t.GenerateCode(); |
1596 | 1670 |
1597 FOR_UINT32_INPUTS(i) { | 1671 FOR_UINT32_INPUTS(i) { |
1598 Handle<HeapNumber> num = | 1672 Handle<HeapNumber> num = |
1599 t.factory()->NewHeapNumber(static_cast<double>(*i)); | 1673 t.factory()->NewHeapNumber(static_cast<double>(*i)); |
1600 uint32_t x = *i / 2; | 1674 uint32_t x = DoubleToUint32(static_cast<double>(*i / 2.0)); |
1601 // TODO(titzer): make calls to NewHeapNumber work in cctests. | 1675 // TODO(titzer): make calls to NewHeapNumber work in cctests. |
1602 if (x >= static_cast<uint32_t>(Smi::kMaxValue)) continue; | 1676 if (x >= static_cast<uint32_t>(Smi::kMaxValue)) continue; |
1603 Handle<HeapNumber> expected = | 1677 Handle<HeapNumber> expected = |
1604 t.factory()->NewHeapNumber(static_cast<double>(x)); | 1678 t.factory()->NewHeapNumber(static_cast<double>(x)); |
1605 Object* result = t.Call(*num); | 1679 Object* result = t.Call(*num); |
1606 CHECK(expected->SameValue(result)); | 1680 CHECK(expected->SameValue(result)); |
1607 } | 1681 } |
1608 } | 1682 } |
1609 } | 1683 } |
1684 | |
1685 | |
1686 TEST(NumberMultiply_ConstantOutOfRange) { | |
1687 TestingGraph t(Type::Signed32()); | |
1688 Node* k = t.jsgraph.Constant(1000000023); | |
1689 Node* mul = t.graph()->NewNode(t.simplified()->NumberMultiply(), t.p0, k); | |
1690 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), mul); | |
1691 t.Return(trunc); | |
1692 t.Lower(); | |
1693 | |
1694 CHECK_EQ(IrOpcode::kFloat64Mul, mul->opcode()); | |
1695 } | |
1696 | |
1697 | |
1698 TEST(NumberMultiply_NonTruncating) { | |
1699 TestingGraph t(Type::Signed32()); | |
1700 Node* k = t.jsgraph.Constant(111); | |
1701 Node* mul = t.graph()->NewNode(t.simplified()->NumberMultiply(), t.p0, k); | |
1702 t.Return(mul); | |
1703 t.Lower(); | |
1704 | |
1705 CHECK_EQ(IrOpcode::kFloat64Mul, mul->opcode()); | |
1706 } | |
1707 | |
1708 | |
1709 TEST(NumberDivide_TruncatingToInt32) { | |
1710 int32_t constants[] = {-100, -10, 1, 4, 100, 1000}; | |
1711 | |
1712 for (size_t i = 0; i < arraysize(constants); i++) { | |
1713 TestingGraph t(Type::Signed32()); | |
1714 Node* k = t.jsgraph.Constant(constants[i]); | |
1715 Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k); | |
1716 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), div); | |
1717 t.Return(trunc); | |
1718 t.Lower(); | |
1719 | |
1720 CHECK_EQ(IrOpcode::kInt32Div, div->opcode()); | |
1721 } | |
1722 } | |
1723 | |
1724 | |
1725 TEST(RunNumberDivide_TruncatingToInt32) { | |
1726 int32_t constants[] = {-100, -10, -1, 1, 2, 100, 1000, 1024, 2048}; | |
1727 | |
1728 for (size_t i = 0; i < arraysize(constants); i++) { | |
1729 int32_t k = constants[i]; | |
1730 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | |
1731 Node* num = t.NumberToInt32(t.Parameter(0)); | |
1732 Node* div = t.NumberDivide(num, t.jsgraph.Constant(k)); | |
1733 Node* trunc = t.NumberToInt32(div); | |
1734 t.Return(trunc); | |
1735 | |
1736 if (Pipeline::SupportedTarget()) { | |
1737 t.LowerAllNodesAndLowerChanges(); | |
1738 t.GenerateCode(); | |
1739 | |
1740 FOR_INT32_INPUTS(i) { | |
1741 if (*i == INT_MAX) continue; // exclude max int. | |
1742 Handle<HeapNumber> num = t.factory()->NewHeapNumber(*i); | |
1743 int32_t x = DoubleToInt32(static_cast<double>(*i) / k); | |
1744 Handle<HeapNumber> expected = t.factory()->NewHeapNumber(x); | |
1745 Object* result = t.Call(*num); | |
1746 CHECK(expected->SameValue(result)); | |
1747 } | |
1748 } | |
1749 } | |
1750 } | |
1751 | |
1752 | |
1753 TEST(NumberDivide_TruncatingToUint32) { | |
1754 double constants[] = {1, 3, 100, 1000, 100998348}; | |
1755 | |
1756 for (size_t i = 0; i < arraysize(constants); i++) { | |
1757 TestingGraph t(Type::Unsigned32()); | |
1758 Node* k = t.jsgraph.Constant(constants[i]); | |
1759 Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k); | |
1760 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), div); | |
1761 t.Return(trunc); | |
1762 t.Lower(); | |
1763 | |
1764 CHECK_EQ(IrOpcode::kUint32Div, div->opcode()); | |
1765 } | |
1766 } | |
1767 | |
1768 | |
1769 TEST(RunNumberDivide_TruncatingToUint32) { | |
1770 uint32_t constants[] = {100, 10, 1, 1, 2, 4, 1000, 1024, 2048}; | |
1771 | |
1772 for (size_t i = 0; i < arraysize(constants); i++) { | |
1773 uint32_t k = constants[i]; | |
1774 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | |
1775 Node* num = t.NumberToUint32(t.Parameter(0)); | |
1776 Node* div = t.NumberDivide(num, t.jsgraph.Constant(static_cast<double>(k))); | |
1777 Node* trunc = t.NumberToUint32(div); | |
1778 t.Return(trunc); | |
1779 | |
1780 if (Pipeline::SupportedTarget()) { | |
1781 t.LowerAllNodesAndLowerChanges(); | |
1782 t.GenerateCode(); | |
1783 | |
1784 FOR_UINT32_INPUTS(i) { | |
1785 Handle<HeapNumber> num = | |
1786 t.factory()->NewHeapNumber(static_cast<double>(*i)); | |
1787 Handle<HeapNumber> expected = | |
1788 t.factory()->NewHeapNumber(static_cast<double>(*i / k)); | |
1789 Object* result = t.Call(*num); | |
1790 CHECK(expected->SameValue(result)); | |
1791 } | |
1792 } | |
1793 } | |
1794 } | |
1795 | |
1796 | |
1797 TEST(NumberDivide_BadConstants) { | |
1798 int32_t constants[] = {-1, 0}; | |
1799 | |
1800 for (size_t i = 0; i < arraysize(constants); i++) { | |
1801 TestingGraph t(Type::Signed32()); | |
1802 Node* k = t.jsgraph.Constant(constants[i]); | |
1803 Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k); | |
1804 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), div); | |
1805 t.Return(trunc); | |
1806 t.Lower(); | |
1807 | |
1808 CHECK_EQ(IrOpcode::kFloat64Div, div->opcode()); | |
1809 } | |
1810 | |
1811 { | |
1812 TestingGraph t(Type::Unsigned32()); | |
1813 Node* k = t.jsgraph.Constant(0); | |
1814 Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k); | |
1815 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), div); | |
1816 t.Return(trunc); | |
1817 t.Lower(); | |
1818 | |
1819 CHECK_EQ(IrOpcode::kFloat64Div, div->opcode()); | |
1820 } | |
1821 } | |
1822 | |
1823 | |
1824 TEST(NumberModulus_TruncatingToInt32) { | |
1825 int32_t constants[] = {-100, -10, 1, 4, 100, 1000}; | |
1826 | |
1827 for (size_t i = 0; i < arraysize(constants); i++) { | |
1828 TestingGraph t(Type::Signed32()); | |
1829 Node* k = t.jsgraph.Constant(constants[i]); | |
1830 Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k); | |
1831 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), mod); | |
1832 t.Return(trunc); | |
1833 t.Lower(); | |
1834 | |
1835 CHECK_EQ(IrOpcode::kInt32Mod, mod->opcode()); | |
1836 } | |
1837 } | |
1838 | |
1839 | |
1840 TEST(RunNumberModulus_TruncatingToInt32) { | |
1841 int32_t constants[] = {-100, -10, -1, 1, 2, 100, 1000, 1024, 2048}; | |
1842 | |
1843 for (size_t i = 0; i < arraysize(constants); i++) { | |
1844 int32_t k = constants[i]; | |
1845 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | |
1846 Node* num = t.NumberToInt32(t.Parameter(0)); | |
1847 Node* mod = t.NumberModulus(num, t.jsgraph.Constant(k)); | |
1848 Node* trunc = t.NumberToInt32(mod); | |
1849 t.Return(trunc); | |
1850 | |
1851 if (Pipeline::SupportedTarget()) { | |
1852 t.LowerAllNodesAndLowerChanges(); | |
1853 t.GenerateCode(); | |
1854 | |
1855 FOR_INT32_INPUTS(i) { | |
1856 if (*i == INT_MAX) continue; // exclude max int. | |
1857 Handle<HeapNumber> num = t.factory()->NewHeapNumber(*i); | |
1858 int32_t x = DoubleToInt32(std::fmod(static_cast<double>(*i), k)); | |
1859 Handle<HeapNumber> expected = t.factory()->NewHeapNumber(x); | |
1860 Object* result = t.Call(*num); | |
1861 CHECK(expected->SameValue(result)); | |
1862 } | |
1863 } | |
1864 } | |
1865 } | |
1866 | |
1867 | |
1868 TEST(NumberModulus_TruncatingToUint32) { | |
1869 double constants[] = {1, 3, 100, 1000, 100998348}; | |
1870 | |
1871 for (size_t i = 0; i < arraysize(constants); i++) { | |
1872 TestingGraph t(Type::Unsigned32()); | |
1873 Node* k = t.jsgraph.Constant(constants[i]); | |
1874 Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k); | |
1875 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), mod); | |
1876 t.Return(trunc); | |
1877 t.Lower(); | |
1878 | |
1879 CHECK_EQ(IrOpcode::kUint32Mod, mod->opcode()); | |
1880 } | |
1881 } | |
1882 | |
1883 | |
1884 TEST(RunNumberModulus_TruncatingToUint32) { | |
1885 uint32_t constants[] = {1, 2, 100, 1000, 1024, 2048}; | |
1886 | |
1887 for (size_t i = 0; i < arraysize(constants); i++) { | |
1888 uint32_t k = constants[i]; | |
1889 SimplifiedLoweringTester<Object*> t(kMachAnyTagged); | |
1890 Node* num = t.NumberToUint32(t.Parameter(0)); | |
1891 Node* mod = | |
1892 t.NumberModulus(num, t.jsgraph.Constant(static_cast<double>(k))); | |
1893 Node* trunc = t.NumberToUint32(mod); | |
1894 t.Return(trunc); | |
1895 | |
1896 if (Pipeline::SupportedTarget()) { | |
1897 t.LowerAllNodesAndLowerChanges(); | |
1898 t.GenerateCode(); | |
1899 | |
1900 FOR_UINT32_INPUTS(i) { | |
1901 Handle<HeapNumber> num = | |
1902 t.factory()->NewHeapNumber(static_cast<double>(*i)); | |
1903 Handle<HeapNumber> expected = | |
1904 t.factory()->NewHeapNumber(static_cast<double>(*i % k)); | |
1905 Object* result = t.Call(*num); | |
1906 CHECK(expected->SameValue(result)); | |
1907 } | |
1908 } | |
1909 } | |
1910 } | |
1911 | |
1912 | |
1913 TEST(NumberModulus_Int32) { | |
1914 int32_t constants[] = {-100, -10, 1, 4, 100, 1000}; | |
1915 | |
1916 for (size_t i = 0; i < arraysize(constants); i++) { | |
1917 TestingGraph t(Type::Signed32()); | |
1918 Node* k = t.jsgraph.Constant(constants[i]); | |
1919 Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k); | |
1920 t.Return(mod); | |
1921 t.Lower(); | |
1922 | |
1923 CHECK_EQ(IrOpcode::kFloat64Mod, mod->opcode()); // Pesky -0 behavior. | |
1924 } | |
1925 } | |
1926 | |
1927 | |
1928 TEST(NumberModulus_Uint32) { | |
1929 double constants[] = {1, 3, 100, 1000, 100998348}; | |
1930 | |
1931 for (size_t i = 0; i < arraysize(constants); i++) { | |
1932 TestingGraph t(Type::Unsigned32()); | |
1933 Node* k = t.jsgraph.Constant(constants[i]); | |
1934 Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k); | |
1935 t.Return(mod); | |
1936 t.Lower(); | |
1937 | |
1938 CHECK_EQ(IrOpcode::kUint32Mod, mod->opcode()); | |
1939 } | |
1940 } | |
1941 | |
1942 | |
1943 TEST(NumberModulus_BadConstants) { | |
1944 int32_t constants[] = {-1, 0}; | |
1945 | |
1946 for (size_t i = 0; i < arraysize(constants); i++) { | |
1947 TestingGraph t(Type::Signed32()); | |
1948 Node* k = t.jsgraph.Constant(constants[i]); | |
1949 Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k); | |
1950 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), mod); | |
1951 t.Return(trunc); | |
1952 t.Lower(); | |
1953 | |
1954 CHECK_EQ(IrOpcode::kFloat64Mod, mod->opcode()); | |
1955 } | |
1956 | |
1957 { | |
1958 TestingGraph t(Type::Unsigned32()); | |
1959 Node* k = t.jsgraph.Constant(0); | |
1960 Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k); | |
1961 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), mod); | |
1962 t.Return(trunc); | |
1963 t.Lower(); | |
1964 | |
1965 CHECK_EQ(IrOpcode::kFloat64Mod, mod->opcode()); | |
1966 } | |
1967 } | |
OLD | NEW |