| 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 |