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/instruction-selector-impl.h" | 5 #include "src/compiler/instruction-selector-impl.h" |
6 #include "src/compiler/node-matchers.h" | 6 #include "src/compiler/node-matchers.h" |
7 #include "src/compiler/node-properties.h" | 7 #include "src/compiler/node-properties.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 | 282 |
283 if (cont->IsSet()) { | 283 if (cont->IsSet()) { |
284 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 284 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
285 } | 285 } |
286 | 286 |
287 DCHECK_NE(0u, input_count); | 287 DCHECK_NE(0u, input_count); |
288 DCHECK((output_count != 0) || is_cmp); | 288 DCHECK((output_count != 0) || is_cmp); |
289 DCHECK_GE(arraysize(inputs), input_count); | 289 DCHECK_GE(arraysize(inputs), input_count); |
290 DCHECK_GE(arraysize(outputs), output_count); | 290 DCHECK_GE(arraysize(outputs), output_count); |
291 | 291 |
292 selector->Emit(cont->Encode(opcode), output_count, outputs, input_count, | 292 opcode = cont->Encode(opcode); |
293 inputs); | 293 if (cont->IsDeoptimize()) { |
| 294 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, |
| 295 cont->frame_state()); |
| 296 } else { |
| 297 selector->Emit(opcode, output_count, outputs, input_count, inputs); |
| 298 } |
294 } | 299 } |
295 | 300 |
296 | 301 |
297 // Shared routine for multiple binary operations. | 302 // Shared routine for multiple binary operations. |
298 template <typename Matcher> | 303 template <typename Matcher> |
299 void VisitBinop(InstructionSelector* selector, Node* node, ArchOpcode opcode, | 304 void VisitBinop(InstructionSelector* selector, Node* node, ArchOpcode opcode, |
300 ImmediateMode operand_mode) { | 305 ImmediateMode operand_mode) { |
301 FlagsContinuation cont; | 306 FlagsContinuation cont; |
302 VisitBinop<Matcher>(selector, node, opcode, operand_mode, &cont); | 307 VisitBinop<Matcher>(selector, node, opcode, operand_mode, &cont); |
303 } | 308 } |
(...skipping 1363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1667 | 1672 |
1668 // Shared routine for multiple compare operations. | 1673 // Shared routine for multiple compare operations. |
1669 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1674 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
1670 InstructionOperand left, InstructionOperand right, | 1675 InstructionOperand left, InstructionOperand right, |
1671 FlagsContinuation* cont) { | 1676 FlagsContinuation* cont) { |
1672 Arm64OperandGenerator g(selector); | 1677 Arm64OperandGenerator g(selector); |
1673 opcode = cont->Encode(opcode); | 1678 opcode = cont->Encode(opcode); |
1674 if (cont->IsBranch()) { | 1679 if (cont->IsBranch()) { |
1675 selector->Emit(opcode, g.NoOutput(), left, right, | 1680 selector->Emit(opcode, g.NoOutput(), left, right, |
1676 g.Label(cont->true_block()), g.Label(cont->false_block())); | 1681 g.Label(cont->true_block()), g.Label(cont->false_block())); |
| 1682 } else if (cont->IsDeoptimize()) { |
| 1683 selector->EmitDeoptimize(opcode, g.NoOutput(), left, right, |
| 1684 cont->frame_state()); |
1677 } else { | 1685 } else { |
1678 DCHECK(cont->IsSet()); | 1686 DCHECK(cont->IsSet()); |
1679 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | 1687 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); |
1680 } | 1688 } |
1681 } | 1689 } |
1682 | 1690 |
1683 | 1691 |
1684 // Shared routine for multiple word compare operations. | 1692 // Shared routine for multiple word compare operations. |
1685 void VisitWordCompare(InstructionSelector* selector, Node* node, | 1693 void VisitWordCompare(InstructionSelector* selector, Node* node, |
1686 InstructionCode opcode, FlagsContinuation* cont, | 1694 InstructionCode opcode, FlagsContinuation* cont, |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1782 } else if (m.left().Is(0.0)) { | 1790 } else if (m.left().Is(0.0)) { |
1783 cont->Commute(); | 1791 cont->Commute(); |
1784 VisitCompare(selector, kArm64Float64Cmp, g.UseRegister(m.right().node()), | 1792 VisitCompare(selector, kArm64Float64Cmp, g.UseRegister(m.right().node()), |
1785 g.UseImmediate(m.left().node()), cont); | 1793 g.UseImmediate(m.left().node()), cont); |
1786 } else { | 1794 } else { |
1787 VisitCompare(selector, kArm64Float64Cmp, g.UseRegister(m.left().node()), | 1795 VisitCompare(selector, kArm64Float64Cmp, g.UseRegister(m.left().node()), |
1788 g.UseRegister(m.right().node()), cont); | 1796 g.UseRegister(m.right().node()), cont); |
1789 } | 1797 } |
1790 } | 1798 } |
1791 | 1799 |
1792 } // namespace | 1800 void VisitWordCompareZero(InstructionSelector* selector, Node* user, |
1793 | 1801 Node* value, FlagsContinuation* cont) { |
1794 | 1802 Arm64OperandGenerator g(selector); |
1795 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 1803 while (selector->CanCover(user, value)) { |
1796 BasicBlock* fbranch) { | |
1797 OperandGenerator g(this); | |
1798 Node* user = branch; | |
1799 Node* value = branch->InputAt(0); | |
1800 | |
1801 FlagsContinuation cont(kNotEqual, tbranch, fbranch); | |
1802 | |
1803 // Try to combine with comparisons against 0 by simply inverting the branch. | |
1804 while (CanCover(user, value) && value->opcode() == IrOpcode::kWord32Equal) { | |
1805 Int32BinopMatcher m(value); | |
1806 if (m.right().Is(0)) { | |
1807 user = value; | |
1808 value = m.left().node(); | |
1809 cont.Negate(); | |
1810 } else { | |
1811 break; | |
1812 } | |
1813 } | |
1814 | |
1815 // Try to combine the branch with a comparison. | |
1816 if (CanCover(user, value)) { | |
1817 switch (value->opcode()) { | 1804 switch (value->opcode()) { |
1818 case IrOpcode::kWord32Equal: | 1805 case IrOpcode::kWord32Equal: { |
1819 cont.OverwriteAndNegateIfEqual(kEqual); | 1806 Int32BinopMatcher m(value); |
1820 return VisitWord32Compare(this, value, &cont); | 1807 if (m.right().Is(0)) { |
| 1808 user = value; |
| 1809 value = m.left().node(); |
| 1810 cont->Negate(); |
| 1811 continue; |
| 1812 } |
| 1813 cont->OverwriteAndNegateIfEqual(kEqual); |
| 1814 return VisitWord32Compare(selector, value, cont); |
| 1815 } |
1821 case IrOpcode::kInt32LessThan: | 1816 case IrOpcode::kInt32LessThan: |
1822 cont.OverwriteAndNegateIfEqual(kSignedLessThan); | 1817 cont->OverwriteAndNegateIfEqual(kSignedLessThan); |
1823 return VisitWord32Compare(this, value, &cont); | 1818 return VisitWord32Compare(selector, value, cont); |
1824 case IrOpcode::kInt32LessThanOrEqual: | 1819 case IrOpcode::kInt32LessThanOrEqual: |
1825 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); | 1820 cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); |
1826 return VisitWord32Compare(this, value, &cont); | 1821 return VisitWord32Compare(selector, value, cont); |
1827 case IrOpcode::kUint32LessThan: | 1822 case IrOpcode::kUint32LessThan: |
1828 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); | 1823 cont->OverwriteAndNegateIfEqual(kUnsignedLessThan); |
1829 return VisitWord32Compare(this, value, &cont); | 1824 return VisitWord32Compare(selector, value, cont); |
1830 case IrOpcode::kUint32LessThanOrEqual: | 1825 case IrOpcode::kUint32LessThanOrEqual: |
1831 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); | 1826 cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); |
1832 return VisitWord32Compare(this, value, &cont); | 1827 return VisitWord32Compare(selector, value, cont); |
1833 case IrOpcode::kWord64Equal: | 1828 case IrOpcode::kWord64Equal: |
1834 cont.OverwriteAndNegateIfEqual(kEqual); | 1829 cont->OverwriteAndNegateIfEqual(kEqual); |
1835 return VisitWordCompare(this, value, kArm64Cmp, &cont, false, | 1830 return VisitWordCompare(selector, value, kArm64Cmp, cont, false, |
1836 kArithmeticImm); | 1831 kArithmeticImm); |
1837 case IrOpcode::kInt64LessThan: | 1832 case IrOpcode::kInt64LessThan: |
1838 cont.OverwriteAndNegateIfEqual(kSignedLessThan); | 1833 cont->OverwriteAndNegateIfEqual(kSignedLessThan); |
1839 return VisitWordCompare(this, value, kArm64Cmp, &cont, false, | 1834 return VisitWordCompare(selector, value, kArm64Cmp, cont, false, |
1840 kArithmeticImm); | 1835 kArithmeticImm); |
1841 case IrOpcode::kInt64LessThanOrEqual: | 1836 case IrOpcode::kInt64LessThanOrEqual: |
1842 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); | 1837 cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); |
1843 return VisitWordCompare(this, value, kArm64Cmp, &cont, false, | 1838 return VisitWordCompare(selector, value, kArm64Cmp, cont, false, |
1844 kArithmeticImm); | 1839 kArithmeticImm); |
1845 case IrOpcode::kUint64LessThan: | 1840 case IrOpcode::kUint64LessThan: |
1846 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); | 1841 cont->OverwriteAndNegateIfEqual(kUnsignedLessThan); |
1847 return VisitWordCompare(this, value, kArm64Cmp, &cont, false, | 1842 return VisitWordCompare(selector, value, kArm64Cmp, cont, false, |
1848 kArithmeticImm); | 1843 kArithmeticImm); |
1849 case IrOpcode::kUint64LessThanOrEqual: | 1844 case IrOpcode::kUint64LessThanOrEqual: |
1850 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); | 1845 cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); |
1851 return VisitWordCompare(this, value, kArm64Cmp, &cont, false, | 1846 return VisitWordCompare(selector, value, kArm64Cmp, cont, false, |
1852 kArithmeticImm); | 1847 kArithmeticImm); |
1853 case IrOpcode::kFloat32Equal: | 1848 case IrOpcode::kFloat32Equal: |
1854 cont.OverwriteAndNegateIfEqual(kEqual); | 1849 cont->OverwriteAndNegateIfEqual(kEqual); |
1855 return VisitFloat32Compare(this, value, &cont); | 1850 return VisitFloat32Compare(selector, value, cont); |
1856 case IrOpcode::kFloat32LessThan: | 1851 case IrOpcode::kFloat32LessThan: |
1857 cont.OverwriteAndNegateIfEqual(kFloatLessThan); | 1852 cont->OverwriteAndNegateIfEqual(kFloatLessThan); |
1858 return VisitFloat32Compare(this, value, &cont); | 1853 return VisitFloat32Compare(selector, value, cont); |
1859 case IrOpcode::kFloat32LessThanOrEqual: | 1854 case IrOpcode::kFloat32LessThanOrEqual: |
1860 cont.OverwriteAndNegateIfEqual(kFloatLessThanOrEqual); | 1855 cont->OverwriteAndNegateIfEqual(kFloatLessThanOrEqual); |
1861 return VisitFloat32Compare(this, value, &cont); | 1856 return VisitFloat32Compare(selector, value, cont); |
1862 case IrOpcode::kFloat64Equal: | 1857 case IrOpcode::kFloat64Equal: |
1863 cont.OverwriteAndNegateIfEqual(kEqual); | 1858 cont->OverwriteAndNegateIfEqual(kEqual); |
1864 return VisitFloat64Compare(this, value, &cont); | 1859 return VisitFloat64Compare(selector, value, cont); |
1865 case IrOpcode::kFloat64LessThan: | 1860 case IrOpcode::kFloat64LessThan: |
1866 cont.OverwriteAndNegateIfEqual(kFloatLessThan); | 1861 cont->OverwriteAndNegateIfEqual(kFloatLessThan); |
1867 return VisitFloat64Compare(this, value, &cont); | 1862 return VisitFloat64Compare(selector, value, cont); |
1868 case IrOpcode::kFloat64LessThanOrEqual: | 1863 case IrOpcode::kFloat64LessThanOrEqual: |
1869 cont.OverwriteAndNegateIfEqual(kFloatLessThanOrEqual); | 1864 cont->OverwriteAndNegateIfEqual(kFloatLessThanOrEqual); |
1870 return VisitFloat64Compare(this, value, &cont); | 1865 return VisitFloat64Compare(selector, value, cont); |
1871 case IrOpcode::kProjection: | 1866 case IrOpcode::kProjection: |
1872 // Check if this is the overflow output projection of an | 1867 // Check if this is the overflow output projection of an |
1873 // <Operation>WithOverflow node. | 1868 // <Operation>WithOverflow node. |
1874 if (ProjectionIndexOf(value->op()) == 1u) { | 1869 if (ProjectionIndexOf(value->op()) == 1u) { |
1875 // We cannot combine the <Operation>WithOverflow with this branch | 1870 // We cannot combine the <Operation>WithOverflow with this branch |
1876 // unless the 0th projection (the use of the actual value of the | 1871 // unless the 0th projection (the use of the actual value of the |
1877 // <Operation> is either nullptr, which means there's no use of the | 1872 // <Operation> is either nullptr, which means there's no use of the |
1878 // actual value, or was already defined, which means it is scheduled | 1873 // actual value, or was already defined, which means it is scheduled |
1879 // *AFTER* this branch). | 1874 // *AFTER* this branch). |
1880 Node* const node = value->InputAt(0); | 1875 Node* const node = value->InputAt(0); |
1881 Node* const result = NodeProperties::FindProjection(node, 0); | 1876 Node* const result = NodeProperties::FindProjection(node, 0); |
1882 if (result == nullptr || IsDefined(result)) { | 1877 if (result == nullptr || selector->IsDefined(result)) { |
1883 switch (node->opcode()) { | 1878 switch (node->opcode()) { |
1884 case IrOpcode::kInt32AddWithOverflow: | 1879 case IrOpcode::kInt32AddWithOverflow: |
1885 cont.OverwriteAndNegateIfEqual(kOverflow); | 1880 cont->OverwriteAndNegateIfEqual(kOverflow); |
1886 return VisitBinop<Int32BinopMatcher>(this, node, kArm64Add32, | 1881 return VisitBinop<Int32BinopMatcher>( |
1887 kArithmeticImm, &cont); | 1882 selector, node, kArm64Add32, kArithmeticImm, cont); |
1888 case IrOpcode::kInt32SubWithOverflow: | 1883 case IrOpcode::kInt32SubWithOverflow: |
1889 cont.OverwriteAndNegateIfEqual(kOverflow); | 1884 cont->OverwriteAndNegateIfEqual(kOverflow); |
1890 return VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, | 1885 return VisitBinop<Int32BinopMatcher>( |
1891 kArithmeticImm, &cont); | 1886 selector, node, kArm64Sub32, kArithmeticImm, cont); |
1892 case IrOpcode::kInt64AddWithOverflow: | 1887 case IrOpcode::kInt64AddWithOverflow: |
1893 cont.OverwriteAndNegateIfEqual(kOverflow); | 1888 cont->OverwriteAndNegateIfEqual(kOverflow); |
1894 return VisitBinop<Int64BinopMatcher>(this, node, kArm64Add, | 1889 return VisitBinop<Int64BinopMatcher>(selector, node, kArm64Add, |
1895 kArithmeticImm, &cont); | 1890 kArithmeticImm, cont); |
1896 case IrOpcode::kInt64SubWithOverflow: | 1891 case IrOpcode::kInt64SubWithOverflow: |
1897 cont.OverwriteAndNegateIfEqual(kOverflow); | 1892 cont->OverwriteAndNegateIfEqual(kOverflow); |
1898 return VisitBinop<Int64BinopMatcher>(this, node, kArm64Sub, | 1893 return VisitBinop<Int64BinopMatcher>(selector, node, kArm64Sub, |
1899 kArithmeticImm, &cont); | 1894 kArithmeticImm, cont); |
1900 default: | 1895 default: |
1901 break; | 1896 break; |
1902 } | 1897 } |
1903 } | 1898 } |
1904 } | 1899 } |
1905 break; | 1900 break; |
1906 case IrOpcode::kInt32Add: | 1901 case IrOpcode::kInt32Add: |
1907 return VisitWordCompare(this, value, kArm64Cmn32, &cont, true, | 1902 return VisitWordCompare(selector, value, kArm64Cmn32, cont, true, |
1908 kArithmeticImm); | 1903 kArithmeticImm); |
1909 case IrOpcode::kInt32Sub: | 1904 case IrOpcode::kInt32Sub: |
1910 return VisitWord32Compare(this, value, &cont); | 1905 return VisitWord32Compare(selector, value, cont); |
1911 case IrOpcode::kWord32And: { | 1906 case IrOpcode::kWord32And: { |
1912 Int32BinopMatcher m(value); | 1907 Int32BinopMatcher m(value); |
1913 if (m.right().HasValue() && | 1908 if (cont->IsBranch() && m.right().HasValue() && |
1914 (base::bits::CountPopulation32(m.right().Value()) == 1)) { | 1909 (base::bits::CountPopulation32(m.right().Value()) == 1)) { |
1915 // If the mask has only one bit set, we can use tbz/tbnz. | 1910 // If the mask has only one bit set, we can use tbz/tbnz. |
1916 DCHECK((cont.condition() == kEqual) || | 1911 DCHECK((cont->condition() == kEqual) || |
1917 (cont.condition() == kNotEqual)); | 1912 (cont->condition() == kNotEqual)); |
1918 Emit(cont.Encode(kArm64TestAndBranch32), g.NoOutput(), | 1913 selector->Emit( |
1919 g.UseRegister(m.left().node()), | 1914 cont->Encode(kArm64TestAndBranch32), g.NoOutput(), |
1920 g.TempImmediate( | 1915 g.UseRegister(m.left().node()), |
1921 base::bits::CountTrailingZeros32(m.right().Value())), | 1916 g.TempImmediate( |
1922 g.Label(cont.true_block()), g.Label(cont.false_block())); | 1917 base::bits::CountTrailingZeros32(m.right().Value())), |
| 1918 g.Label(cont->true_block()), g.Label(cont->false_block())); |
1923 return; | 1919 return; |
1924 } | 1920 } |
1925 return VisitWordCompare(this, value, kArm64Tst32, &cont, true, | 1921 return VisitWordCompare(selector, value, kArm64Tst32, cont, true, |
1926 kLogical32Imm); | 1922 kLogical32Imm); |
1927 } | 1923 } |
1928 case IrOpcode::kWord64And: { | 1924 case IrOpcode::kWord64And: { |
1929 Int64BinopMatcher m(value); | 1925 Int64BinopMatcher m(value); |
1930 if (m.right().HasValue() && | 1926 if (cont->IsBranch() && m.right().HasValue() && |
1931 (base::bits::CountPopulation64(m.right().Value()) == 1)) { | 1927 (base::bits::CountPopulation64(m.right().Value()) == 1)) { |
1932 // If the mask has only one bit set, we can use tbz/tbnz. | 1928 // If the mask has only one bit set, we can use tbz/tbnz. |
1933 DCHECK((cont.condition() == kEqual) || | 1929 DCHECK((cont->condition() == kEqual) || |
1934 (cont.condition() == kNotEqual)); | 1930 (cont->condition() == kNotEqual)); |
1935 Emit(cont.Encode(kArm64TestAndBranch), g.NoOutput(), | 1931 selector->Emit( |
1936 g.UseRegister(m.left().node()), | 1932 cont->Encode(kArm64TestAndBranch), g.NoOutput(), |
1937 g.TempImmediate( | 1933 g.UseRegister(m.left().node()), |
1938 base::bits::CountTrailingZeros64(m.right().Value())), | 1934 g.TempImmediate( |
1939 g.Label(cont.true_block()), g.Label(cont.false_block())); | 1935 base::bits::CountTrailingZeros64(m.right().Value())), |
| 1936 g.Label(cont->true_block()), g.Label(cont->false_block())); |
1940 return; | 1937 return; |
1941 } | 1938 } |
1942 return VisitWordCompare(this, value, kArm64Tst, &cont, true, | 1939 return VisitWordCompare(selector, value, kArm64Tst, cont, true, |
1943 kLogical64Imm); | 1940 kLogical64Imm); |
1944 } | 1941 } |
1945 default: | 1942 default: |
1946 break; | 1943 break; |
1947 } | 1944 } |
| 1945 break; |
1948 } | 1946 } |
1949 | 1947 |
1950 // Branch could not be combined with a compare, compare against 0 and branch. | 1948 // Branch could not be combined with a compare, compare against 0 and branch. |
1951 Emit(cont.Encode(kArm64CompareAndBranch32), g.NoOutput(), | 1949 if (cont->IsBranch()) { |
1952 g.UseRegister(value), g.Label(cont.true_block()), | 1950 selector->Emit(cont->Encode(kArm64CompareAndBranch32), g.NoOutput(), |
1953 g.Label(cont.false_block())); | 1951 g.UseRegister(value), g.Label(cont->true_block()), |
| 1952 g.Label(cont->false_block())); |
| 1953 } else { |
| 1954 DCHECK(cont->IsDeoptimize()); |
| 1955 selector->EmitDeoptimize(cont->Encode(kArm64Tst32), g.NoOutput(), |
| 1956 g.UseRegister(value), g.UseRegister(value), |
| 1957 cont->frame_state()); |
| 1958 } |
1954 } | 1959 } |
1955 | 1960 |
| 1961 } // namespace |
| 1962 |
| 1963 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
| 1964 BasicBlock* fbranch) { |
| 1965 FlagsContinuation cont(kNotEqual, tbranch, fbranch); |
| 1966 VisitWordCompareZero(this, branch, branch->InputAt(0), &cont); |
| 1967 } |
| 1968 |
| 1969 void InstructionSelector::VisitDeoptimizeIf(Node* node) { |
| 1970 FlagsContinuation cont = |
| 1971 FlagsContinuation::ForDeoptimize(kNotEqual, node->InputAt(1)); |
| 1972 VisitWordCompareZero(this, node, node->InputAt(0), &cont); |
| 1973 } |
| 1974 |
| 1975 void InstructionSelector::VisitDeoptimizeUnless(Node* node) { |
| 1976 FlagsContinuation cont = |
| 1977 FlagsContinuation::ForDeoptimize(kEqual, node->InputAt(1)); |
| 1978 VisitWordCompareZero(this, node, node->InputAt(0), &cont); |
| 1979 } |
1956 | 1980 |
1957 void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { | 1981 void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { |
1958 Arm64OperandGenerator g(this); | 1982 Arm64OperandGenerator g(this); |
1959 InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); | 1983 InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); |
1960 | 1984 |
1961 // Emit either ArchTableSwitch or ArchLookupSwitch. | 1985 // Emit either ArchTableSwitch or ArchLookupSwitch. |
1962 size_t table_space_cost = 4 + sw.value_range; | 1986 size_t table_space_cost = 4 + sw.value_range; |
1963 size_t table_time_cost = 3; | 1987 size_t table_time_cost = 3; |
1964 size_t lookup_space_cost = 3 + 2 * sw.case_count; | 1988 size_t lookup_space_cost = 3 + 2 * sw.case_count; |
1965 size_t lookup_time_cost = sw.case_count; | 1989 size_t lookup_time_cost = sw.case_count; |
(...skipping 11 matching lines...) Expand all Loading... |
1977 return EmitTableSwitch(sw, index_operand); | 2001 return EmitTableSwitch(sw, index_operand); |
1978 } | 2002 } |
1979 | 2003 |
1980 // Generate a sequence of conditional jumps. | 2004 // Generate a sequence of conditional jumps. |
1981 return EmitLookupSwitch(sw, value_operand); | 2005 return EmitLookupSwitch(sw, value_operand); |
1982 } | 2006 } |
1983 | 2007 |
1984 | 2008 |
1985 void InstructionSelector::VisitWord32Equal(Node* const node) { | 2009 void InstructionSelector::VisitWord32Equal(Node* const node) { |
1986 Node* const user = node; | 2010 Node* const user = node; |
1987 FlagsContinuation cont(kEqual, node); | 2011 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node); |
1988 Int32BinopMatcher m(user); | 2012 Int32BinopMatcher m(user); |
1989 if (m.right().Is(0)) { | 2013 if (m.right().Is(0)) { |
1990 Node* const value = m.left().node(); | 2014 Node* const value = m.left().node(); |
1991 if (CanCover(user, value)) { | 2015 if (CanCover(user, value)) { |
1992 switch (value->opcode()) { | 2016 switch (value->opcode()) { |
1993 case IrOpcode::kInt32Add: | 2017 case IrOpcode::kInt32Add: |
1994 return VisitWordCompare(this, value, kArm64Cmn32, &cont, true, | 2018 return VisitWordCompare(this, value, kArm64Cmn32, &cont, true, |
1995 kArithmeticImm); | 2019 kArithmeticImm); |
1996 case IrOpcode::kInt32Sub: | 2020 case IrOpcode::kInt32Sub: |
1997 return VisitWordCompare(this, value, kArm64Cmp32, &cont, false, | 2021 return VisitWordCompare(this, value, kArm64Cmp32, &cont, false, |
(...skipping 13 matching lines...) Expand all Loading... |
2011 break; | 2035 break; |
2012 } | 2036 } |
2013 return VisitWord32Test(this, value, &cont); | 2037 return VisitWord32Test(this, value, &cont); |
2014 } | 2038 } |
2015 } | 2039 } |
2016 VisitWord32Compare(this, node, &cont); | 2040 VisitWord32Compare(this, node, &cont); |
2017 } | 2041 } |
2018 | 2042 |
2019 | 2043 |
2020 void InstructionSelector::VisitInt32LessThan(Node* node) { | 2044 void InstructionSelector::VisitInt32LessThan(Node* node) { |
2021 FlagsContinuation cont(kSignedLessThan, node); | 2045 FlagsContinuation cont = FlagsContinuation::ForSet(kSignedLessThan, node); |
2022 VisitWord32Compare(this, node, &cont); | 2046 VisitWord32Compare(this, node, &cont); |
2023 } | 2047 } |
2024 | 2048 |
2025 | 2049 |
2026 void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) { | 2050 void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) { |
2027 FlagsContinuation cont(kSignedLessThanOrEqual, node); | 2051 FlagsContinuation cont = |
| 2052 FlagsContinuation::ForSet(kSignedLessThanOrEqual, node); |
2028 VisitWord32Compare(this, node, &cont); | 2053 VisitWord32Compare(this, node, &cont); |
2029 } | 2054 } |
2030 | 2055 |
2031 | 2056 |
2032 void InstructionSelector::VisitUint32LessThan(Node* node) { | 2057 void InstructionSelector::VisitUint32LessThan(Node* node) { |
2033 FlagsContinuation cont(kUnsignedLessThan, node); | 2058 FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node); |
2034 VisitWord32Compare(this, node, &cont); | 2059 VisitWord32Compare(this, node, &cont); |
2035 } | 2060 } |
2036 | 2061 |
2037 | 2062 |
2038 void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) { | 2063 void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) { |
2039 FlagsContinuation cont(kUnsignedLessThanOrEqual, node); | 2064 FlagsContinuation cont = |
| 2065 FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node); |
2040 VisitWord32Compare(this, node, &cont); | 2066 VisitWord32Compare(this, node, &cont); |
2041 } | 2067 } |
2042 | 2068 |
2043 | 2069 |
2044 void InstructionSelector::VisitWord64Equal(Node* const node) { | 2070 void InstructionSelector::VisitWord64Equal(Node* const node) { |
2045 Node* const user = node; | 2071 Node* const user = node; |
2046 FlagsContinuation cont(kEqual, node); | 2072 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node); |
2047 Int64BinopMatcher m(user); | 2073 Int64BinopMatcher m(user); |
2048 if (m.right().Is(0)) { | 2074 if (m.right().Is(0)) { |
2049 Node* const value = m.left().node(); | 2075 Node* const value = m.left().node(); |
2050 if (CanCover(user, value)) { | 2076 if (CanCover(user, value)) { |
2051 switch (value->opcode()) { | 2077 switch (value->opcode()) { |
2052 case IrOpcode::kWord64And: | 2078 case IrOpcode::kWord64And: |
2053 return VisitWordCompare(this, value, kArm64Tst, &cont, true, | 2079 return VisitWordCompare(this, value, kArm64Tst, &cont, true, |
2054 kLogical64Imm); | 2080 kLogical64Imm); |
2055 default: | 2081 default: |
2056 break; | 2082 break; |
2057 } | 2083 } |
2058 return VisitWord64Test(this, value, &cont); | 2084 return VisitWord64Test(this, value, &cont); |
2059 } | 2085 } |
2060 } | 2086 } |
2061 VisitWordCompare(this, node, kArm64Cmp, &cont, false, kArithmeticImm); | 2087 VisitWordCompare(this, node, kArm64Cmp, &cont, false, kArithmeticImm); |
2062 } | 2088 } |
2063 | 2089 |
2064 | 2090 |
2065 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { | 2091 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { |
2066 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 2092 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
2067 FlagsContinuation cont(kOverflow, ovf); | 2093 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
2068 return VisitBinop<Int32BinopMatcher>(this, node, kArm64Add32, | 2094 return VisitBinop<Int32BinopMatcher>(this, node, kArm64Add32, |
2069 kArithmeticImm, &cont); | 2095 kArithmeticImm, &cont); |
2070 } | 2096 } |
2071 FlagsContinuation cont; | 2097 FlagsContinuation cont; |
2072 VisitBinop<Int32BinopMatcher>(this, node, kArm64Add32, kArithmeticImm, &cont); | 2098 VisitBinop<Int32BinopMatcher>(this, node, kArm64Add32, kArithmeticImm, &cont); |
2073 } | 2099 } |
2074 | 2100 |
2075 | 2101 |
2076 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { | 2102 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { |
2077 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 2103 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
2078 FlagsContinuation cont(kOverflow, ovf); | 2104 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
2079 return VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, | 2105 return VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, |
2080 kArithmeticImm, &cont); | 2106 kArithmeticImm, &cont); |
2081 } | 2107 } |
2082 FlagsContinuation cont; | 2108 FlagsContinuation cont; |
2083 VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, kArithmeticImm, &cont); | 2109 VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, kArithmeticImm, &cont); |
2084 } | 2110 } |
2085 | 2111 |
2086 | 2112 |
2087 void InstructionSelector::VisitInt64AddWithOverflow(Node* node) { | 2113 void InstructionSelector::VisitInt64AddWithOverflow(Node* node) { |
2088 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 2114 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
2089 FlagsContinuation cont(kOverflow, ovf); | 2115 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
2090 return VisitBinop<Int64BinopMatcher>(this, node, kArm64Add, kArithmeticImm, | 2116 return VisitBinop<Int64BinopMatcher>(this, node, kArm64Add, kArithmeticImm, |
2091 &cont); | 2117 &cont); |
2092 } | 2118 } |
2093 FlagsContinuation cont; | 2119 FlagsContinuation cont; |
2094 VisitBinop<Int64BinopMatcher>(this, node, kArm64Add, kArithmeticImm, &cont); | 2120 VisitBinop<Int64BinopMatcher>(this, node, kArm64Add, kArithmeticImm, &cont); |
2095 } | 2121 } |
2096 | 2122 |
2097 | 2123 |
2098 void InstructionSelector::VisitInt64SubWithOverflow(Node* node) { | 2124 void InstructionSelector::VisitInt64SubWithOverflow(Node* node) { |
2099 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 2125 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
2100 FlagsContinuation cont(kOverflow, ovf); | 2126 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
2101 return VisitBinop<Int64BinopMatcher>(this, node, kArm64Sub, kArithmeticImm, | 2127 return VisitBinop<Int64BinopMatcher>(this, node, kArm64Sub, kArithmeticImm, |
2102 &cont); | 2128 &cont); |
2103 } | 2129 } |
2104 FlagsContinuation cont; | 2130 FlagsContinuation cont; |
2105 VisitBinop<Int64BinopMatcher>(this, node, kArm64Sub, kArithmeticImm, &cont); | 2131 VisitBinop<Int64BinopMatcher>(this, node, kArm64Sub, kArithmeticImm, &cont); |
2106 } | 2132 } |
2107 | 2133 |
2108 | 2134 |
2109 void InstructionSelector::VisitInt64LessThan(Node* node) { | 2135 void InstructionSelector::VisitInt64LessThan(Node* node) { |
2110 FlagsContinuation cont(kSignedLessThan, node); | 2136 FlagsContinuation cont = FlagsContinuation::ForSet(kSignedLessThan, node); |
2111 VisitWordCompare(this, node, kArm64Cmp, &cont, false, kArithmeticImm); | 2137 VisitWordCompare(this, node, kArm64Cmp, &cont, false, kArithmeticImm); |
2112 } | 2138 } |
2113 | 2139 |
2114 | 2140 |
2115 void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) { | 2141 void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) { |
2116 FlagsContinuation cont(kSignedLessThanOrEqual, node); | 2142 FlagsContinuation cont = |
| 2143 FlagsContinuation::ForSet(kSignedLessThanOrEqual, node); |
2117 VisitWordCompare(this, node, kArm64Cmp, &cont, false, kArithmeticImm); | 2144 VisitWordCompare(this, node, kArm64Cmp, &cont, false, kArithmeticImm); |
2118 } | 2145 } |
2119 | 2146 |
2120 | 2147 |
2121 void InstructionSelector::VisitUint64LessThan(Node* node) { | 2148 void InstructionSelector::VisitUint64LessThan(Node* node) { |
2122 FlagsContinuation cont(kUnsignedLessThan, node); | 2149 FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node); |
2123 VisitWordCompare(this, node, kArm64Cmp, &cont, false, kArithmeticImm); | 2150 VisitWordCompare(this, node, kArm64Cmp, &cont, false, kArithmeticImm); |
2124 } | 2151 } |
2125 | 2152 |
2126 | 2153 |
2127 void InstructionSelector::VisitUint64LessThanOrEqual(Node* node) { | 2154 void InstructionSelector::VisitUint64LessThanOrEqual(Node* node) { |
2128 FlagsContinuation cont(kUnsignedLessThanOrEqual, node); | 2155 FlagsContinuation cont = |
| 2156 FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node); |
2129 VisitWordCompare(this, node, kArm64Cmp, &cont, false, kArithmeticImm); | 2157 VisitWordCompare(this, node, kArm64Cmp, &cont, false, kArithmeticImm); |
2130 } | 2158 } |
2131 | 2159 |
2132 | 2160 |
2133 void InstructionSelector::VisitFloat32Equal(Node* node) { | 2161 void InstructionSelector::VisitFloat32Equal(Node* node) { |
2134 FlagsContinuation cont(kEqual, node); | 2162 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node); |
2135 VisitFloat32Compare(this, node, &cont); | 2163 VisitFloat32Compare(this, node, &cont); |
2136 } | 2164 } |
2137 | 2165 |
2138 | 2166 |
2139 void InstructionSelector::VisitFloat32LessThan(Node* node) { | 2167 void InstructionSelector::VisitFloat32LessThan(Node* node) { |
2140 FlagsContinuation cont(kFloatLessThan, node); | 2168 FlagsContinuation cont = FlagsContinuation::ForSet(kFloatLessThan, node); |
2141 VisitFloat32Compare(this, node, &cont); | 2169 VisitFloat32Compare(this, node, &cont); |
2142 } | 2170 } |
2143 | 2171 |
2144 | 2172 |
2145 void InstructionSelector::VisitFloat32LessThanOrEqual(Node* node) { | 2173 void InstructionSelector::VisitFloat32LessThanOrEqual(Node* node) { |
2146 FlagsContinuation cont(kFloatLessThanOrEqual, node); | 2174 FlagsContinuation cont = |
| 2175 FlagsContinuation::ForSet(kFloatLessThanOrEqual, node); |
2147 VisitFloat32Compare(this, node, &cont); | 2176 VisitFloat32Compare(this, node, &cont); |
2148 } | 2177 } |
2149 | 2178 |
2150 | 2179 |
2151 void InstructionSelector::VisitFloat64Equal(Node* node) { | 2180 void InstructionSelector::VisitFloat64Equal(Node* node) { |
2152 FlagsContinuation cont(kEqual, node); | 2181 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node); |
2153 VisitFloat64Compare(this, node, &cont); | 2182 VisitFloat64Compare(this, node, &cont); |
2154 } | 2183 } |
2155 | 2184 |
2156 | 2185 |
2157 void InstructionSelector::VisitFloat64LessThan(Node* node) { | 2186 void InstructionSelector::VisitFloat64LessThan(Node* node) { |
2158 FlagsContinuation cont(kFloatLessThan, node); | 2187 FlagsContinuation cont = FlagsContinuation::ForSet(kFloatLessThan, node); |
2159 VisitFloat64Compare(this, node, &cont); | 2188 VisitFloat64Compare(this, node, &cont); |
2160 } | 2189 } |
2161 | 2190 |
2162 | 2191 |
2163 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { | 2192 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { |
2164 FlagsContinuation cont(kFloatLessThanOrEqual, node); | 2193 FlagsContinuation cont = |
| 2194 FlagsContinuation::ForSet(kFloatLessThanOrEqual, node); |
2165 VisitFloat64Compare(this, node, &cont); | 2195 VisitFloat64Compare(this, node, &cont); |
2166 } | 2196 } |
2167 | 2197 |
2168 | 2198 |
2169 void InstructionSelector::VisitFloat64ExtractLowWord32(Node* node) { | 2199 void InstructionSelector::VisitFloat64ExtractLowWord32(Node* node) { |
2170 Arm64OperandGenerator g(this); | 2200 Arm64OperandGenerator g(this); |
2171 Emit(kArm64Float64ExtractLowWord32, g.DefineAsRegister(node), | 2201 Emit(kArm64Float64ExtractLowWord32, g.DefineAsRegister(node), |
2172 g.UseRegister(node->InputAt(0))); | 2202 g.UseRegister(node->InputAt(0))); |
2173 } | 2203 } |
2174 | 2204 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2234 MachineOperatorBuilder::kWord32ShiftIsSafe | | 2264 MachineOperatorBuilder::kWord32ShiftIsSafe | |
2235 MachineOperatorBuilder::kInt32DivIsSafe | | 2265 MachineOperatorBuilder::kInt32DivIsSafe | |
2236 MachineOperatorBuilder::kUint32DivIsSafe | | 2266 MachineOperatorBuilder::kUint32DivIsSafe | |
2237 MachineOperatorBuilder::kWord32ReverseBits | | 2267 MachineOperatorBuilder::kWord32ReverseBits | |
2238 MachineOperatorBuilder::kWord64ReverseBits; | 2268 MachineOperatorBuilder::kWord64ReverseBits; |
2239 } | 2269 } |
2240 | 2270 |
2241 } // namespace compiler | 2271 } // namespace compiler |
2242 } // namespace internal | 2272 } // namespace internal |
2243 } // namespace v8 | 2273 } // namespace v8 |
OLD | NEW |