From afbc67a80c5d1889f2a22623d5a7793573948c5a Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sat, 17 Nov 2018 23:33:47 +0000 Subject: [PATCH 1/4] Use Bmi1.TrailingZeroCount for LocateFirstFoundXxx --- .../shared/System/SpanHelpers.Byte.cs | 20 +++++++++++++++---- .../shared/System/SpanHelpers.Char.cs | 20 ++++++++++++++----- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs index 118c82be2811..cadf2b2ae592 100644 --- a/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs +++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs @@ -6,7 +6,10 @@ using System.Runtime.CompilerServices; using System.Numerics; +#if !netstandard +using System.Runtime.Intrinsics.X86; using Internal.Runtime.CompilerServices; +#endif #if BIT64 using nuint = System.UInt64; @@ -1109,10 +1112,19 @@ private static int LocateLastFoundByte(Vector match) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int LocateFirstFoundByte(ulong match) { - // Flag least significant power of two bit - var powerOfTwoFlag = match ^ (match - 1); - // Shift all powers of two into the high byte and extract - return (int)((powerOfTwoFlag * XorPowerOfTwoToHighByte) >> 57); +#if !netstandard + if (Bmi1.IsSupported && IntPtr.Size == 8) + { + return (int)(Bmi1.TrailingZeroCount(match) >> 3); + } + else +#endif + { + // Flag least significant power of two bit + var powerOfTwoFlag = match ^ (match - 1); + // Shift all powers of two into the high byte and extract + return (int)((powerOfTwoFlag * XorPowerOfTwoToHighByte) >> 57); + } } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs index 47011963dfdc..86e598c54af3 100644 --- a/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs +++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs @@ -7,6 +7,7 @@ using System.Numerics; #if !netstandard +using System.Runtime.Intrinsics.X86; using Internal.Runtime.CompilerServices; #endif @@ -822,12 +823,21 @@ private static int LocateFirstFoundChar(Vector match) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int LocateFirstFoundChar(ulong match) { - unchecked +#if !netstandard + if (Bmi1.IsSupported && IntPtr.Size == 8) + { + return (int)(Bmi1.TrailingZeroCount(match) >> 4); + } + else +#endif { - // Flag least significant power of two bit - var powerOfTwoFlag = match ^ (match - 1); - // Shift all powers of two into the high byte and extract - return (int)((powerOfTwoFlag * XorPowerOfTwoToHighChar) >> 49); + unchecked + { + // Flag least significant power of two bit + var powerOfTwoFlag = match ^ (match - 1); + // Shift all powers of two into the high byte and extract + return (int)((powerOfTwoFlag * XorPowerOfTwoToHighChar) >> 49); + } } } From 62187bf78863d2dff167f7aedadbd1fc2f7e90d5 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sun, 18 Nov 2018 01:11:33 +0000 Subject: [PATCH 2/4] remove netstd ifdefs --- .../shared/System/SpanHelpers.Byte.cs | 6 +----- .../shared/System/SpanHelpers.Char.cs | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs index cadf2b2ae592..64782180b5ab 100644 --- a/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs +++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs @@ -5,11 +5,9 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using System.Numerics; - -#if !netstandard using System.Runtime.Intrinsics.X86; + using Internal.Runtime.CompilerServices; -#endif #if BIT64 using nuint = System.UInt64; @@ -1112,13 +1110,11 @@ private static int LocateLastFoundByte(Vector match) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int LocateFirstFoundByte(ulong match) { -#if !netstandard if (Bmi1.IsSupported && IntPtr.Size == 8) { return (int)(Bmi1.TrailingZeroCount(match) >> 3); } else -#endif { // Flag least significant power of two bit var powerOfTwoFlag = match ^ (match - 1); diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs index 86e598c54af3..ed1ba04be5cb 100644 --- a/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs +++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs @@ -5,11 +5,9 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using System.Numerics; - -#if !netstandard using System.Runtime.Intrinsics.X86; + using Internal.Runtime.CompilerServices; -#endif #if BIT64 using nuint = System.UInt64; @@ -823,13 +821,11 @@ private static int LocateFirstFoundChar(Vector match) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int LocateFirstFoundChar(ulong match) { -#if !netstandard if (Bmi1.IsSupported && IntPtr.Size == 8) { return (int)(Bmi1.TrailingZeroCount(match) >> 4); } else -#endif { unchecked { From 4c74b80fc2c4b7569e5b6233e40d5486d90045e8 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sun, 18 Nov 2018 05:55:29 +0000 Subject: [PATCH 3/4] Use Lzcnt.LeadingZeroCount for LocateLastFoundXxx --- .../shared/System/SpanHelpers.Byte.cs | 19 +++++++++++++------ .../shared/System/SpanHelpers.Char.cs | 19 +++++++++++++------ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs index 64782180b5ab..58083e6e2ec1 100644 --- a/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs +++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs @@ -1126,14 +1126,21 @@ private static int LocateFirstFoundByte(ulong match) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int LocateLastFoundByte(ulong match) { - // Find the most significant byte that has its highest bit set - int index = 7; - while ((long)match > 0) + if (Lzcnt.IsSupported && IntPtr.Size == 8) { - match = match << 8; - index--; + return 7 - (int)(Lzcnt.LeadingZeroCount(match) >> 3); + } + else + { + // Find the most significant byte that has its highest bit set + int index = 7; + while ((long)match > 0) + { + match = match << 8; + index--; + } + return index; } - return index; } private const ulong XorPowerOfTwoToHighByte = (0x07ul | diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs index ed1ba04be5cb..464a2b072806 100644 --- a/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs +++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs @@ -865,14 +865,21 @@ private static int LocateLastFoundChar(Vector match) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int LocateLastFoundChar(ulong match) { - // Find the most significant char that has its highest bit set - int index = 3; - while ((long)match > 0) + if (Lzcnt.IsSupported && IntPtr.Size == 8) { - match = match << 16; - index--; + return 3 - (int)(Lzcnt.LeadingZeroCount(match) >> 4); + } + else + { + // Find the most significant char that has its highest bit set + int index = 3; + while ((long)match > 0) + { + match = match << 16; + index--; + } + return index; } - return index; } } } From 050349f04782124b6579f191ca13764b5889881a Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Tue, 20 Nov 2018 05:36:56 +0000 Subject: [PATCH 4/4] Use new apis --- .../shared/System/SpanHelpers.Byte.cs | 10 ++++++---- .../shared/System/SpanHelpers.Char.cs | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs index 58083e6e2ec1..4f076eedf7fe 100644 --- a/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs +++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs @@ -1110,9 +1110,10 @@ private static int LocateLastFoundByte(Vector match) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int LocateFirstFoundByte(ulong match) { - if (Bmi1.IsSupported && IntPtr.Size == 8) + // TODO: Arm variants + if (Bmi1.X64.IsSupported) { - return (int)(Bmi1.TrailingZeroCount(match) >> 3); + return (int)(Bmi1.X64.TrailingZeroCount(match) >> 3); } else { @@ -1126,9 +1127,10 @@ private static int LocateFirstFoundByte(ulong match) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int LocateLastFoundByte(ulong match) { - if (Lzcnt.IsSupported && IntPtr.Size == 8) + // TODO: Arm variants + if (Lzcnt.X64.IsSupported) { - return 7 - (int)(Lzcnt.LeadingZeroCount(match) >> 3); + return 7 - (int)(Lzcnt.X64.LeadingZeroCount(match) >> 3); } else { diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs index 464a2b072806..d57944e9bf76 100644 --- a/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs +++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs @@ -821,9 +821,10 @@ private static int LocateFirstFoundChar(Vector match) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int LocateFirstFoundChar(ulong match) { - if (Bmi1.IsSupported && IntPtr.Size == 8) + // TODO: Arm variants + if (Bmi1.X64.IsSupported) { - return (int)(Bmi1.TrailingZeroCount(match) >> 4); + return (int)(Bmi1.X64.TrailingZeroCount(match) >> 4); } else { @@ -865,9 +866,10 @@ private static int LocateLastFoundChar(Vector match) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int LocateLastFoundChar(ulong match) { - if (Lzcnt.IsSupported && IntPtr.Size == 8) + // TODO: Arm variants + if (Lzcnt.X64.IsSupported) { - return 3 - (int)(Lzcnt.LeadingZeroCount(match) >> 4); + return 3 - (int)(Lzcnt.X64.LeadingZeroCount(match) >> 4); } else {