Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: src/compiler/arm64/instruction-selector-arm64.cc

Issue 2022073002: [turbofan] ARM64: Match 64 bit compare with zero and branch (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 1842 matching lines...) Expand 10 before | Expand all | Expand 10 after
1853 FlagsContinuation* cont) { 1853 FlagsContinuation* cont) {
1854 VisitWordTest(selector, node, kArm64Tst32, cont); 1854 VisitWordTest(selector, node, kArm64Tst32, cont);
1855 } 1855 }
1856 1856
1857 1857
1858 void VisitWord64Test(InstructionSelector* selector, Node* node, 1858 void VisitWord64Test(InstructionSelector* selector, Node* node,
1859 FlagsContinuation* cont) { 1859 FlagsContinuation* cont) {
1860 VisitWordTest(selector, node, kArm64Tst, cont); 1860 VisitWordTest(selector, node, kArm64Tst, cont);
1861 } 1861 }
1862 1862
1863 template <typename Matcher, ArchOpcode kOpcode>
1864 bool TryEmitTestAndBranch(InstructionSelector* selector, Node* node,
1865 FlagsContinuation* cont) {
1866 Arm64OperandGenerator g(selector);
1867 Matcher m(node);
1868 if (cont->IsBranch() && m.right().HasValue() &&
1869 (base::bits::CountPopulation(m.right().Value()) == 1)) {
1870 // If the mask has only one bit set, we can use tbz/tbnz.
1871 DCHECK((cont->condition() == kEqual) || (cont->condition() == kNotEqual));
1872 selector->Emit(
1873 cont->Encode(kOpcode), g.NoOutput(), g.UseRegister(m.left().node()),
1874 g.TempImmediate(base::bits::CountTrailingZeros(m.right().Value())),
1875 g.Label(cont->true_block()), g.Label(cont->false_block()));
1876 return true;
1877 }
1878 return false;
1879 }
1863 1880
1864 // Shared routine for multiple float32 compare operations. 1881 // Shared routine for multiple float32 compare operations.
1865 void VisitFloat32Compare(InstructionSelector* selector, Node* node, 1882 void VisitFloat32Compare(InstructionSelector* selector, Node* node,
1866 FlagsContinuation* cont) { 1883 FlagsContinuation* cont) {
1867 Arm64OperandGenerator g(selector); 1884 Arm64OperandGenerator g(selector);
1868 Float32BinopMatcher m(node); 1885 Float32BinopMatcher m(node);
1869 if (m.right().Is(0.0f)) { 1886 if (m.right().Is(0.0f)) {
1870 VisitCompare(selector, kArm64Float32Cmp, g.UseRegister(m.left().node()), 1887 VisitCompare(selector, kArm64Float32Cmp, g.UseRegister(m.left().node()),
1871 g.UseImmediate(m.right().node()), cont); 1888 g.UseImmediate(m.right().node()), cont);
1872 } else if (m.left().Is(0.0f)) { 1889 } else if (m.left().Is(0.0f)) {
(...skipping 24 matching lines...) Expand all
1897 g.UseRegister(m.right().node()), cont); 1914 g.UseRegister(m.right().node()), cont);
1898 } 1915 }
1899 } 1916 }
1900 1917
1901 void VisitWordCompareZero(InstructionSelector* selector, Node* user, 1918 void VisitWordCompareZero(InstructionSelector* selector, Node* user,
1902 Node* value, FlagsContinuation* cont) { 1919 Node* value, FlagsContinuation* cont) {
1903 Arm64OperandGenerator g(selector); 1920 Arm64OperandGenerator g(selector);
1904 while (selector->CanCover(user, value)) { 1921 while (selector->CanCover(user, value)) {
1905 switch (value->opcode()) { 1922 switch (value->opcode()) {
1906 case IrOpcode::kWord32Equal: { 1923 case IrOpcode::kWord32Equal: {
1924 // Combine with comparisons against 0 by simply inverting the
1925 // continuation.
1907 Int32BinopMatcher m(value); 1926 Int32BinopMatcher m(value);
1908 if (m.right().Is(0)) { 1927 if (m.right().Is(0)) {
1909 user = value; 1928 user = value;
1910 value = m.left().node(); 1929 value = m.left().node();
1911 cont->Negate(); 1930 cont->Negate();
1912 continue; 1931 continue;
1913 } 1932 }
1914 cont->OverwriteAndNegateIfEqual(kEqual); 1933 cont->OverwriteAndNegateIfEqual(kEqual);
1915 return VisitWord32Compare(selector, value, cont); 1934 return VisitWord32Compare(selector, value, cont);
1916 } 1935 }
1917 case IrOpcode::kInt32LessThan: 1936 case IrOpcode::kInt32LessThan:
1918 cont->OverwriteAndNegateIfEqual(kSignedLessThan); 1937 cont->OverwriteAndNegateIfEqual(kSignedLessThan);
1919 return VisitWord32Compare(selector, value, cont); 1938 return VisitWord32Compare(selector, value, cont);
1920 case IrOpcode::kInt32LessThanOrEqual: 1939 case IrOpcode::kInt32LessThanOrEqual:
1921 cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); 1940 cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
1922 return VisitWord32Compare(selector, value, cont); 1941 return VisitWord32Compare(selector, value, cont);
1923 case IrOpcode::kUint32LessThan: 1942 case IrOpcode::kUint32LessThan:
1924 cont->OverwriteAndNegateIfEqual(kUnsignedLessThan); 1943 cont->OverwriteAndNegateIfEqual(kUnsignedLessThan);
1925 return VisitWord32Compare(selector, value, cont); 1944 return VisitWord32Compare(selector, value, cont);
1926 case IrOpcode::kUint32LessThanOrEqual: 1945 case IrOpcode::kUint32LessThanOrEqual:
1927 cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); 1946 cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
1928 return VisitWord32Compare(selector, value, cont); 1947 return VisitWord32Compare(selector, value, cont);
1929 case IrOpcode::kWord64Equal: 1948 case IrOpcode::kWord64Equal: {
1930 cont->OverwriteAndNegateIfEqual(kEqual); 1949 cont->OverwriteAndNegateIfEqual(kEqual);
1950 Int64BinopMatcher m(value);
1951 if (m.right().Is(0)) {
1952 Node* const left = m.left().node();
1953 if (selector->CanCover(value, left) &&
1954 left->opcode() == IrOpcode::kWord64And) {
1955 // Attempt to merge the Word64Equal(Word64And(x, y), 0) comparison
1956 // into a tbz/tbnz instruction.
1957 if (TryEmitTestAndBranch<Uint64BinopMatcher, kArm64TestAndBranch>(
1958 selector, left, cont)) {
1959 return;
1960 }
1961 return VisitWordCompare(selector, left, kArm64Tst, cont, true,
1962 kLogical64Imm);
1963 }
1964 // Merge the Word64Equal(x, 0) comparison into a cbz instruction.
1965 if (cont->IsBranch()) {
1966 selector->Emit(cont->Encode(kArm64CompareAndBranch), g.NoOutput(),
1967 g.UseRegister(left), g.Label(cont->true_block()),
1968 g.Label(cont->false_block()));
1969 return;
1970 }
1971 }
1931 return VisitWordCompare(selector, value, kArm64Cmp, cont, false, 1972 return VisitWordCompare(selector, value, kArm64Cmp, cont, false,
1932 kArithmeticImm); 1973 kArithmeticImm);
1974 }
1933 case IrOpcode::kInt64LessThan: 1975 case IrOpcode::kInt64LessThan:
1934 cont->OverwriteAndNegateIfEqual(kSignedLessThan); 1976 cont->OverwriteAndNegateIfEqual(kSignedLessThan);
1935 return VisitWordCompare(selector, value, kArm64Cmp, cont, false, 1977 return VisitWordCompare(selector, value, kArm64Cmp, cont, false,
1936 kArithmeticImm); 1978 kArithmeticImm);
1937 case IrOpcode::kInt64LessThanOrEqual: 1979 case IrOpcode::kInt64LessThanOrEqual:
1938 cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); 1980 cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
1939 return VisitWordCompare(selector, value, kArm64Cmp, cont, false, 1981 return VisitWordCompare(selector, value, kArm64Cmp, cont, false,
1940 kArithmeticImm); 1982 kArithmeticImm);
1941 case IrOpcode::kUint64LessThan: 1983 case IrOpcode::kUint64LessThan:
1942 cont->OverwriteAndNegateIfEqual(kUnsignedLessThan); 1984 cont->OverwriteAndNegateIfEqual(kUnsignedLessThan);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1997 break; 2039 break;
1998 } 2040 }
1999 } 2041 }
2000 } 2042 }
2001 break; 2043 break;
2002 case IrOpcode::kInt32Add: 2044 case IrOpcode::kInt32Add:
2003 return VisitWordCompare(selector, value, kArm64Cmn32, cont, true, 2045 return VisitWordCompare(selector, value, kArm64Cmn32, cont, true,
2004 kArithmeticImm); 2046 kArithmeticImm);
2005 case IrOpcode::kInt32Sub: 2047 case IrOpcode::kInt32Sub:
2006 return VisitWord32Compare(selector, value, cont); 2048 return VisitWord32Compare(selector, value, cont);
2007 case IrOpcode::kWord32And: { 2049 case IrOpcode::kWord32And:
2008 Int32BinopMatcher m(value); 2050 if (TryEmitTestAndBranch<Uint32BinopMatcher, kArm64TestAndBranch32>(
2009 if (cont->IsBranch() && m.right().HasValue() && 2051 selector, value, cont)) {
2010 (base::bits::CountPopulation32(m.right().Value()) == 1)) {
2011 // If the mask has only one bit set, we can use tbz/tbnz.
2012 DCHECK((cont->condition() == kEqual) ||
2013 (cont->condition() == kNotEqual));
2014 selector->Emit(
2015 cont->Encode(kArm64TestAndBranch32), g.NoOutput(),
2016 g.UseRegister(m.left().node()),
2017 g.TempImmediate(
2018 base::bits::CountTrailingZeros32(m.right().Value())),
2019 g.Label(cont->true_block()), g.Label(cont->false_block()));
2020 return; 2052 return;
2021 } 2053 }
2022 return VisitWordCompare(selector, value, kArm64Tst32, cont, true, 2054 return VisitWordCompare(selector, value, kArm64Tst32, cont, true,
2023 kLogical32Imm); 2055 kLogical32Imm);
2024 } 2056 case IrOpcode::kWord64And:
2025 case IrOpcode::kWord64And: { 2057 if (TryEmitTestAndBranch<Uint64BinopMatcher, kArm64TestAndBranch>(
2026 Int64BinopMatcher m(value); 2058 selector, value, cont)) {
2027 if (cont->IsBranch() && m.right().HasValue() &&
2028 (base::bits::CountPopulation64(m.right().Value()) == 1)) {
2029 // If the mask has only one bit set, we can use tbz/tbnz.
2030 DCHECK((cont->condition() == kEqual) ||
2031 (cont->condition() == kNotEqual));
2032 selector->Emit(
2033 cont->Encode(kArm64TestAndBranch), g.NoOutput(),
2034 g.UseRegister(m.left().node()),
2035 g.TempImmediate(
2036 base::bits::CountTrailingZeros64(m.right().Value())),
2037 g.Label(cont->true_block()), g.Label(cont->false_block()));
2038 return; 2059 return;
2039 } 2060 }
2040 return VisitWordCompare(selector, value, kArm64Tst, cont, true, 2061 return VisitWordCompare(selector, value, kArm64Tst, cont, true,
2041 kLogical64Imm); 2062 kLogical64Imm);
2042 }
2043 default: 2063 default:
2044 break; 2064 break;
2045 } 2065 }
2046 break; 2066 break;
2047 } 2067 }
2048 2068
2049 // Branch could not be combined with a compare, compare against 0 and branch. 2069 // Branch could not be combined with a compare, compare against 0 and branch.
2050 if (cont->IsBranch()) { 2070 if (cont->IsBranch()) {
2051 selector->Emit(cont->Encode(kArm64CompareAndBranch32), g.NoOutput(), 2071 selector->Emit(cont->Encode(kArm64CompareAndBranch32), g.NoOutput(),
2052 g.UseRegister(value), g.Label(cont->true_block()), 2072 g.UseRegister(value), g.Label(cont->true_block()),
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
2429 // static 2449 // static
2430 MachineOperatorBuilder::AlignmentRequirements 2450 MachineOperatorBuilder::AlignmentRequirements
2431 InstructionSelector::AlignmentRequirements() { 2451 InstructionSelector::AlignmentRequirements() {
2432 return MachineOperatorBuilder::AlignmentRequirements:: 2452 return MachineOperatorBuilder::AlignmentRequirements::
2433 FullUnalignedAccessSupport(); 2453 FullUnalignedAccessSupport();
2434 } 2454 }
2435 2455
2436 } // namespace compiler 2456 } // namespace compiler
2437 } // namespace internal 2457 } // namespace internal
2438 } // namespace v8 2458 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698