diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash3.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash3.cs index 4e821618d36e3e..17087d87631036 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash3.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash3.cs @@ -10,6 +10,7 @@ using System.Runtime.InteropServices; #if NET7_0_OR_GREATER using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.X86; #endif @@ -896,16 +897,31 @@ private static Vector128 Accumulate128(Vector128 accVec, byte* sou Vector128 sourceKey = sourceVec ^ secret; // TODO: Figure out how to unwind this shuffle and just use Vector128.Multiply - Vector128 sourceKeyLow = Vector128.Shuffle(sourceKey, Vector128.Create(1u, 0, 3, 0)); Vector128 sourceSwap = Vector128.Shuffle(sourceVec, Vector128.Create(2u, 3, 0, 1)); Vector128 sum = accVec + sourceSwap.AsUInt64(); - Vector128 product = Sse2.IsSupported ? - Sse2.Multiply(sourceKey, sourceKeyLow) : - (sourceKey & Vector128.Create(~0u, 0u, ~0u, 0u)).AsUInt64() * (sourceKeyLow & Vector128.Create(~0u, 0u, ~0u, 0u)).AsUInt64(); + Vector128 product = MultiplyWideningLower(sourceKey); accVec = product + sum; return accVec; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector128 MultiplyWideningLower(Vector128 source) + { + if (AdvSimd.IsSupported) + { + Vector64 sourceLow = Vector128.Shuffle(source, Vector128.Create(0u, 2, 0, 0)).GetLower(); + Vector64 sourceHigh = Vector128.Shuffle(source, Vector128.Create(1u, 3, 0, 0)).GetLower(); + return AdvSimd.MultiplyWideningLower(sourceLow, sourceHigh); + } + else + { + Vector128 sourceLow = Vector128.Shuffle(source, Vector128.Create(1u, 0, 3, 0)); + return Sse2.IsSupported ? + Sse2.Multiply(source, sourceLow) : + (source & Vector128.Create(~0u, 0u, ~0u, 0u)).AsUInt64() * (sourceLow & Vector128.Create(~0u, 0u, ~0u, 0u)).AsUInt64(); + } + } #endif private static void ScrambleAccumulators(ulong* accumulators, byte* secret)