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/base/adapters.h" | 5 #include "src/base/adapters.h" |
6 #include "src/base/bits.h" | 6 #include "src/base/bits.h" |
7 #include "src/compiler/instruction-selector-impl.h" | 7 #include "src/compiler/instruction-selector-impl.h" |
8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
10 | 10 |
(...skipping 1822 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1833 default: | 1833 default: |
1834 VisitCompare(selector, opcode, g.UseRegister(right), | 1834 VisitCompare(selector, opcode, g.UseRegister(right), |
1835 g.UseRegister(left), cont); | 1835 g.UseRegister(left), cont); |
1836 } | 1836 } |
1837 } else { | 1837 } else { |
1838 VisitCompare(selector, opcode, g.UseRegister(left), g.UseRegister(right), | 1838 VisitCompare(selector, opcode, g.UseRegister(left), g.UseRegister(right), |
1839 cont); | 1839 cont); |
1840 } | 1840 } |
1841 } | 1841 } |
1842 | 1842 |
| 1843 bool IsNodeUnsigned(Node* n) { |
| 1844 NodeMatcher m(n); |
| 1845 |
| 1846 if (m.IsLoad()) { |
| 1847 LoadRepresentation load_rep = LoadRepresentationOf(n->op()); |
| 1848 return load_rep.IsUnsigned(); |
| 1849 } else if (m.IsUnalignedLoad()) { |
| 1850 UnalignedLoadRepresentation load_rep = |
| 1851 UnalignedLoadRepresentationOf(n->op()); |
| 1852 return load_rep.IsUnsigned(); |
| 1853 } else { |
| 1854 return m.IsUint32Div() || m.IsUint32LessThan() || |
| 1855 m.IsUint32LessThanOrEqual() || m.IsUint32Mod() || |
| 1856 m.IsUint32MulHigh() || m.IsChangeFloat64ToUint32() || |
| 1857 m.IsTruncateFloat64ToUint32() || m.IsTruncateFloat32ToUint32(); |
| 1858 } |
| 1859 } |
| 1860 |
| 1861 // Shared routine for multiple word compare operations. |
| 1862 void VisitFullWord32Compare(InstructionSelector* selector, Node* node, |
| 1863 InstructionCode opcode, FlagsContinuation* cont) { |
| 1864 Mips64OperandGenerator g(selector); |
| 1865 InstructionOperand leftOp = g.TempRegister(); |
| 1866 InstructionOperand rightOp = g.TempRegister(); |
| 1867 |
| 1868 selector->Emit(kMips64Dshl, leftOp, g.UseRegister(node->InputAt(0)), |
| 1869 g.TempImmediate(32)); |
| 1870 selector->Emit(kMips64Dshl, rightOp, g.UseRegister(node->InputAt(1)), |
| 1871 g.TempImmediate(32)); |
| 1872 |
| 1873 VisitCompare(selector, opcode, leftOp, rightOp, cont); |
| 1874 } |
| 1875 |
| 1876 void VisitOptimizedWord32Compare(InstructionSelector* selector, Node* node, |
| 1877 InstructionCode opcode, |
| 1878 FlagsContinuation* cont) { |
| 1879 if (FLAG_debug_code) { |
| 1880 Mips64OperandGenerator g(selector); |
| 1881 InstructionOperand leftOp = g.TempRegister(); |
| 1882 InstructionOperand rightOp = g.TempRegister(); |
| 1883 InstructionOperand optimizedResult = g.TempRegister(); |
| 1884 InstructionOperand fullResult = g.TempRegister(); |
| 1885 FlagsCondition condition = cont->condition(); |
| 1886 InstructionCode testOpcode = opcode | |
| 1887 FlagsConditionField::encode(condition) | |
| 1888 FlagsModeField::encode(kFlags_set); |
| 1889 |
| 1890 selector->Emit(testOpcode, optimizedResult, g.UseRegister(node->InputAt(0)), |
| 1891 g.UseRegister(node->InputAt(1))); |
| 1892 |
| 1893 selector->Emit(kMips64Dshl, leftOp, g.UseRegister(node->InputAt(0)), |
| 1894 g.TempImmediate(32)); |
| 1895 selector->Emit(kMips64Dshl, rightOp, g.UseRegister(node->InputAt(1)), |
| 1896 g.TempImmediate(32)); |
| 1897 selector->Emit(testOpcode, fullResult, leftOp, rightOp); |
| 1898 |
| 1899 selector->Emit( |
| 1900 kMips64AssertEqual, g.NoOutput(), optimizedResult, fullResult, |
| 1901 g.TempImmediate(BailoutReason::kUnsupportedNonPrimitiveCompare)); |
| 1902 } |
| 1903 |
| 1904 VisitWordCompare(selector, node, opcode, cont, false); |
| 1905 } |
| 1906 |
| 1907 void VisitWord32Compare(InstructionSelector* selector, Node* node, |
| 1908 FlagsContinuation* cont) { |
| 1909 // MIPS64 doesn't support Word32 compare instructions. Instead it relies |
| 1910 // that the values in registers are correctly sign-extended and uses |
| 1911 // Word64 comparison instead. This behavior is correct in most cases, |
| 1912 // but doesn't work when comparing signed with unsigned operands. |
| 1913 // We could simulate full Word32 compare in all cases but this would |
| 1914 // create an unnecessary overhead since unsigned integers are rarely |
| 1915 // used in JavaScript. |
| 1916 // The solution proposed here tries to match a comparison of signed |
| 1917 // with unsigned operand, and perform full Word32Compare only |
| 1918 // in those cases. Unfortunately, the solution is not complete because |
| 1919 // it might skip cases where Word32 full compare is needed, so |
| 1920 // basically it is a hack. |
| 1921 if (IsNodeUnsigned(node->InputAt(0)) != IsNodeUnsigned(node->InputAt(1))) { |
| 1922 VisitFullWord32Compare(selector, node, kMips64Cmp, cont); |
| 1923 } else { |
| 1924 VisitOptimizedWord32Compare(selector, node, kMips64Cmp, cont); |
| 1925 } |
| 1926 } |
| 1927 |
1843 | 1928 |
1844 void VisitWord32Compare(InstructionSelector* selector, Node* node, | |
1845 FlagsContinuation* cont) { | |
1846 VisitWordCompare(selector, node, kMips64Cmp, cont, false); | |
1847 } | |
1848 | |
1849 | |
1850 void VisitWord64Compare(InstructionSelector* selector, Node* node, | 1929 void VisitWord64Compare(InstructionSelector* selector, Node* node, |
1851 FlagsContinuation* cont) { | 1930 FlagsContinuation* cont) { |
1852 VisitWordCompare(selector, node, kMips64Cmp, cont, false); | 1931 VisitWordCompare(selector, node, kMips64Cmp, cont, false); |
1853 } | 1932 } |
1854 | 1933 |
1855 | 1934 |
1856 | 1935 |
1857 void EmitWordCompareZero(InstructionSelector* selector, Node* value, | 1936 void EmitWordCompareZero(InstructionSelector* selector, Node* value, |
1858 FlagsContinuation* cont) { | 1937 FlagsContinuation* cont) { |
1859 Mips64OperandGenerator g(selector); | 1938 Mips64OperandGenerator g(selector); |
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2331 } else { | 2410 } else { |
2332 DCHECK(kArchVariant == kMips64r2); | 2411 DCHECK(kArchVariant == kMips64r2); |
2333 return MachineOperatorBuilder::AlignmentRequirements:: | 2412 return MachineOperatorBuilder::AlignmentRequirements:: |
2334 NoUnalignedAccessSupport(); | 2413 NoUnalignedAccessSupport(); |
2335 } | 2414 } |
2336 } | 2415 } |
2337 | 2416 |
2338 } // namespace compiler | 2417 } // namespace compiler |
2339 } // namespace internal | 2418 } // namespace internal |
2340 } // namespace v8 | 2419 } // namespace v8 |
OLD | NEW |