diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs index 118c82be2811..4f076eedf7fe 100644 --- a/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs +++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using System.Numerics; +using System.Runtime.Intrinsics.X86; using Internal.Runtime.CompilerServices; @@ -1109,23 +1110,39 @@ 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); + // TODO: Arm variants + if (Bmi1.X64.IsSupported) + { + return (int)(Bmi1.X64.TrailingZeroCount(match) >> 3); + } + else + { + // 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)] private static int LocateLastFoundByte(ulong match) { - // Find the most significant byte that has its highest bit set - int index = 7; - while ((long)match > 0) + // TODO: Arm variants + if (Lzcnt.X64.IsSupported) { - match = match << 8; - index--; + return 7 - (int)(Lzcnt.X64.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 47011963dfdc..d57944e9bf76 100644 --- a/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs +++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs @@ -5,10 +5,9 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using System.Numerics; +using System.Runtime.Intrinsics.X86; -#if !netstandard using Internal.Runtime.CompilerServices; -#endif #if BIT64 using nuint = System.UInt64; @@ -822,12 +821,20 @@ private static int LocateFirstFoundChar(Vector match) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int LocateFirstFoundChar(ulong match) { - unchecked + // TODO: Arm variants + if (Bmi1.X64.IsSupported) + { + return (int)(Bmi1.X64.TrailingZeroCount(match) >> 4); + } + else { - // 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); + } } } @@ -859,14 +866,22 @@ 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) + // TODO: Arm variants + if (Lzcnt.X64.IsSupported) { - match = match << 16; - index--; + return 3 - (int)(Lzcnt.X64.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; } } }