From 2c89d1b783bd0318e56c4232083925e181647145 Mon Sep 17 00:00:00 2001 From: Daniel Svensson Date: Thu, 6 Mar 2025 11:02:32 +0100 Subject: [PATCH 1/2] Improve BigMul to fix VarDecCmpSub regression #11243 --- .../System.Private.CoreLib/src/System/Math.cs | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Math.cs b/src/libraries/System.Private.CoreLib/src/System/Math.cs index a099c849e458f0..650b1ec35887d8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Math.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Math.cs @@ -159,16 +159,6 @@ internal static void ThrowNegateTwosCompOverflow() [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe ulong BigMul(uint a, uint b) { -#if false // TARGET_32BIT - // This generates slower code currently than the simple multiplication - // https://github.com/dotnet/runtime/issues/11782 - if (Bmi2.IsSupported) - { - uint low; - uint high = Bmi2.MultiplyNoFlags(a, b, &low); - return ((ulong)high << 32) | low; - } -#endif return ((ulong)a) * b; } @@ -181,7 +171,7 @@ public static long BigMul(int a, int b) return ((long)a) * b; } - +#if !TARGET_ARM64 /// /// Perform multiplication between 64 and 32 bit numbers, returning lower 64 bits in /// @@ -190,21 +180,25 @@ public static long BigMul(int a, int b) [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ulong BigMul(ulong a, uint b, out ulong low) { -#if TARGET_64BIT - return Math.BigMul((ulong)a, (ulong)b, out low); -#else + if (Bmi2.X64.IsSupported) + { + // Ideally, we should do a single multiply for low and high. Doing this efficiently would mean making BigMul an instrinct (would work on all x64 targets) or fixing https://github.com/dotnet/runtime/issues/11782 + low = a * b; + return Bmi2.X64.MultiplyNoFlags(a, b); + } + ulong prodL = ((ulong)(uint)a) * b; ulong prodH = (prodL >> 32) + (((ulong)(uint)(a >> 32)) * b); low = ((prodH << 32) | (uint)prodL); return (prodH >> 32); -#endif } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ulong BigMul(uint a, ulong b, out ulong low) => BigMul(b, a, out low); +#endif /// Produces the full product of two unsigned 64-bit numbers. /// The first number to multiply. @@ -213,14 +207,13 @@ internal static ulong BigMul(uint a, ulong b, out ulong low) /// The high 64-bit of the product of the specified numbers. [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe ulong BigMul(ulong a, ulong b, out ulong low) + public static ulong BigMul(ulong a, ulong b, out ulong low) { if (Bmi2.X64.IsSupported) { - ulong tmp; - ulong high = Bmi2.X64.MultiplyNoFlags(a, b, &tmp); - low = tmp; - return high; + // Ideally, we should do a single multiply for low and high. Doing this efficiently would mean making BigMul an instrinct (would work on all x64 targets) or fixing https://github.com/dotnet/runtime/issues/11782 + low = a * b; + return Bmi2.X64.MultiplyNoFlags(a, b); } else if (ArmBase.Arm64.IsSupported) { From 18482a871dd376397a815ac0201e5a2ecae99474 Mon Sep 17 00:00:00 2001 From: Daniel Svensson Date: Wed, 30 Apr 2025 09:17:00 +0200 Subject: [PATCH 2/2] Fix typo --- src/libraries/System.Private.CoreLib/src/System/Math.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Math.cs b/src/libraries/System.Private.CoreLib/src/System/Math.cs index 650b1ec35887d8..e85433ba0891d1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Math.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Math.cs @@ -182,7 +182,7 @@ internal static ulong BigMul(ulong a, uint b, out ulong low) { if (Bmi2.X64.IsSupported) { - // Ideally, we should do a single multiply for low and high. Doing this efficiently would mean making BigMul an instrinct (would work on all x64 targets) or fixing https://github.com/dotnet/runtime/issues/11782 + // Ideally, we should do a single multiply for low and high. Doing this efficiently would mean making BigMul an intrinsic (would work on all x64 targets) or fixing https://github.com/dotnet/runtime/issues/11782 low = a * b; return Bmi2.X64.MultiplyNoFlags(a, b); } @@ -211,7 +211,7 @@ public static ulong BigMul(ulong a, ulong b, out ulong low) { if (Bmi2.X64.IsSupported) { - // Ideally, we should do a single multiply for low and high. Doing this efficiently would mean making BigMul an instrinct (would work on all x64 targets) or fixing https://github.com/dotnet/runtime/issues/11782 + // Ideally, we should do a single multiply for low and high. Doing this efficiently would mean making BigMul an intrinsic (would work on all x64 targets) or fixing https://github.com/dotnet/runtime/issues/11782 low = a * b; return Bmi2.X64.MultiplyNoFlags(a, b); }