diff --git a/src/libraries/System.Private.CoreLib/src/System/Math.cs b/src/libraries/System.Private.CoreLib/src/System/Math.cs
index a099c849e458f0..e85433ba0891d1 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 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);
+ }
+
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 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);
}
else if (ArmBase.Arm64.IsSupported)
{