From d236b8c5e42013d70879bea349d49d7d466364c8 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Fri, 26 Oct 2018 09:07:08 +0300 Subject: [PATCH] Optimize FormattingHelpers.CountHexDigits using Lzcnt.LeadingZeroCount (#19006) * Optimize CountHexDigits using Lzcnt * shift bits instead * use Lzcnt only on 64 bit * Optimize Buffer.Utilities.SelectBucketIndex() * #if HAS_INTRINSICS * remove HAS_INTRINSICS * remove HAS_INTRINSICS --- .../shared/System/Buffers/Text/FormattingHelpers.CountDigits.cs | 8 ++++++-- src/System.Private.CoreLib/shared/System/Buffers/Utilities.cs | 6 ++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/System.Private.CoreLib/shared/System/Buffers/Text/FormattingHelpers.CountDigits.cs b/src/System.Private.CoreLib/shared/System/Buffers/Text/FormattingHelpers.CountDigits.cs index b6140ad..8982803 100644 --- a/src/System.Private.CoreLib/shared/System/Buffers/Text/FormattingHelpers.CountDigits.cs +++ b/src/System.Private.CoreLib/shared/System/Buffers/Text/FormattingHelpers.CountDigits.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics.X86; namespace System.Buffers.Text { @@ -103,8 +104,11 @@ namespace System.Buffers.Text [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int CountHexDigits(ulong value) { - // TODO: When x86 intrinsic support comes online, experiment with implementing this using lzcnt. - // return 16 - (int)((uint)Lzcnt.LeadingZeroCount(value | 1) >> 3); + if (Lzcnt.IsSupported && IntPtr.Size == 8) + { + int right = 64 - (int)Lzcnt.LeadingZeroCount(value | 1); + return (right + 3) >> 2; + } int digits = 1; diff --git a/src/System.Private.CoreLib/shared/System/Buffers/Utilities.cs b/src/System.Private.CoreLib/shared/System/Buffers/Utilities.cs index b675100..628449c 100644 --- a/src/System.Private.CoreLib/shared/System/Buffers/Utilities.cs +++ b/src/System.Private.CoreLib/shared/System/Buffers/Utilities.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics.X86; namespace System.Buffers { @@ -13,6 +14,11 @@ namespace System.Buffers internal static int SelectBucketIndex(int bufferSize) { Debug.Assert(bufferSize >= 0); + if (Lzcnt.IsSupported) + { + uint bits = ((uint)bufferSize - 1) >> 4; + return 32 - (int)Lzcnt.LeadingZeroCount(bits); + } // bufferSize of 0 will underflow here, causing a huge // index which the caller will discard because it is not -- 2.7.4