From d519034d17f72dbb31dcc17dc452f16e35b38122 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 12 Jun 2021 15:58:11 +0800 Subject: [PATCH 1/3] Clean RotateLeft --- .../Runtime/CompilerServices/CastHelpers.cs | 5 +++-- .../tools/Common/Internal/Text/Utf8String.cs | 22 +++++++------------ .../Compiler/ReadyToRunHashCode.cs | 5 +++-- .../System/Numerics/Hashing/HashHelpers.cs | 16 -------------- 4 files changed, 14 insertions(+), 34 deletions(-) delete mode 100644 src/libraries/System.Private.CoreLib/src/System/Numerics/Hashing/HashHelpers.cs diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs index cb8800994aa78..a31f67b4ebbff 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Numerics; using System.Runtime.InteropServices; using System.Threading; @@ -45,10 +46,10 @@ private static int KeyToBucket(ref int tableData, nuint source, nuint target) int hashShift = HashShift(ref tableData); #if TARGET_64BIT - ulong hash = (((ulong)source << 32) | ((ulong)source >> 32)) ^ (ulong)target; + ulong hash = BitOperations.RotateLeft((ulong)source, 32) ^ (ulong)target; return (int)((hash * 11400714819323198485ul) >> hashShift); #else - uint hash = (((uint)source >> 16) | ((uint)source << 16)) ^ (uint)target; + uint hash = BitOperations.RotateLeft((uint)source, 16) ^ (uint)target; return (int)((hash * 2654435769u) >> hashShift); #endif } diff --git a/src/coreclr/tools/Common/Internal/Text/Utf8String.cs b/src/coreclr/tools/Common/Internal/Text/Utf8String.cs index cc1b045bb19a9..9b44102c582c5 100644 --- a/src/coreclr/tools/Common/Internal/Text/Utf8String.cs +++ b/src/coreclr/tools/Common/Internal/Text/Utf8String.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Numerics; using System.Runtime.CompilerServices; using System.Text; @@ -42,38 +43,31 @@ public override bool Equals(object obj) return (obj is Utf8String) && Equals((Utf8String)obj); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static int _rotl(int value, int shift) - { - // This is expected to be optimized into a single rotl instruction - return (int)(((uint)value << shift) | ((uint)value >> (32 - shift))); - } - public unsafe override int GetHashCode() { int length = _value.Length; - int hash = length; + uint hash = (uint)length; fixed (byte* ap = _value) { byte* a = ap; while (length >= 4) { - hash = (hash + _rotl(hash, 5)) ^ *(int*)a; + hash = (hash + BitOperations.RotateLeft(hash, 5)) ^ *(uint*)a; a += 4; length -= 4; } if (length >= 2) { - hash = (hash + _rotl(hash, 5)) ^ *(short*)a; + hash = (hash + BitOperations.RotateLeft(hash, 5)) ^ *(ushort*)a; a += 2; length -= 2; } if (length > 0) { - hash = (hash + _rotl(hash, 5)) ^ *a; + hash = (hash + BitOperations.RotateLeft(hash, 5)) ^ *a; } - hash += _rotl(hash, 7); - hash += _rotl(hash, 15); - return hash; + hash += BitOperations.RotateLeft(hash, 7); + hash += BitOperations.RotateLeft(hash, 15); + return (int)hash; } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs index 19a643476ecd1..e506bb8b3b6ef 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; +using System.Numerics; using System.Text; using Internal.TypeSystem; @@ -219,7 +220,7 @@ public static int ModuleNameHashCode(ModuleDesc module) /// Number of bits private static int RotateLeft(int value, int bitCount) { - return unchecked((int)(((uint)value << bitCount) | ((uint)value >> (32 - bitCount)))); + return (int)BitOperations.RotateLeft((uint)value, bitCount); } private static uint XXHash32_MixEmptyState() @@ -231,7 +232,7 @@ private static uint XXHash32_MixEmptyState() private static uint XXHash32_QueueRound(uint hash, uint queuedValue) { - return ((uint)RotateLeft((int)(hash + queuedValue * 3266489917U/*Prime3*/), 17)) * 668265263U/*Prime4*/; + return (BitOperations.RotateLeft((hash + queuedValue * 3266489917U/*Prime3*/), 17)) * 668265263U/*Prime4*/; } private static uint XXHash32_MixFinal(uint hash) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Hashing/HashHelpers.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Hashing/HashHelpers.cs deleted file mode 100644 index 7bf7d5c6d1feb..0000000000000 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Hashing/HashHelpers.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Numerics.Hashing -{ - internal static class HashHelpers - { - public static int Combine(int h1, int h2) - { - // RyuJIT optimizes this to use the ROL instruction - // Related GitHub pull request: https://github.com/dotnet/coreclr/pull/1830 - uint rol5 = ((uint)h1 << 5) | ((uint)h1 >> 27); - return ((int)rol5 + h1) ^ h2; - } - } -} From bbd6ee748a0f432dcc3f135976f240502baa6ac8 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 12 Jun 2021 16:22:42 +0800 Subject: [PATCH 2/3] Cleanup RotateRight --- .../Internal/Cryptography/SHAHashProvider.Browser.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs index 7a83e35ce13bf..fccdff3feb81a 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs @@ -4,8 +4,8 @@ using System; using System.IO; using System.Diagnostics; -using System.Numerics; using System.Security.Cryptography; +using static System.Numerics.BitOperations; namespace Internal.Cryptography { @@ -342,11 +342,6 @@ private static unsafe void SHATransform(uint* expandedBuffer, uint* state, byte* state[7] += h; } - private static uint RotateRight(uint x, int n) - { - return (((x) >> (n)) | ((x) << (32 - (n)))); - } - private static uint Ch(uint x, uint y, uint z) { return ((x & y) ^ ((x ^ 0xffffffff) & z)); @@ -917,11 +912,6 @@ private static unsafe void SHATransform(ulong* expandedBuffer, ulong* state, byt state[7] += h; } - private static ulong RotateRight(ulong x, int n) - { - return (((x) >> (n)) | ((x) << (64 - (n)))); - } - private static ulong Ch(ulong x, ulong y, ulong z) { return ((x & y) ^ ((x ^ 0xffffffffffffffff) & z)); From 08940c301771131bb30dc5ee924f1479de952cfd Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 14 Jun 2021 17:13:45 +0800 Subject: [PATCH 3/3] Restore HashHelpers --- .../src/System/Numerics/Hashing/HashHelpers.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/libraries/System.Private.CoreLib/src/System/Numerics/Hashing/HashHelpers.cs diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Hashing/HashHelpers.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Hashing/HashHelpers.cs new file mode 100644 index 0000000000000..7bf7d5c6d1feb --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Hashing/HashHelpers.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Numerics.Hashing +{ + internal static class HashHelpers + { + public static int Combine(int h1, int h2) + { + // RyuJIT optimizes this to use the ROL instruction + // Related GitHub pull request: https://github.com/dotnet/coreclr/pull/1830 + uint rol5 = ((uint)h1 << 5) | ((uint)h1 >> 27); + return ((int)rol5 + h1) ^ h2; + } + } +}