Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize Math.Round for arm64 and AwayFromZero for x64 #64016

Merged
merged 20 commits into from
Feb 13, 2022
Merged
12 changes: 12 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Math.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,18 @@ public static double Round(double value, int digits)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Round(double value, MidpointRounding mode)
EgorBo marked this conversation as resolved.
Show resolved Hide resolved
{
// Inline single-instruction modes
EgorBo marked this conversation as resolved.
Show resolved Hide resolved
if (RuntimeHelpers.IsKnownConstant((int)mode))
{
if (mode == MidpointRounding.ToEven)
return Round(value);

// For ARM/ARM64 we can lower it down to a single instruction FRINTA
// For XARCH we have to use the common path
if (AdvSimd.Arm64.IsSupported && mode == MidpointRounding.AwayFromZero)
return AdvSimd.Arm64.RoundAwayFromZero(Vector128.CreateScalarUnsafe(value)).ToScalar();
EgorBo marked this conversation as resolved.
Show resolved Hide resolved
}

return Round(value, 0, mode);
}

Expand Down
12 changes: 12 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/MathF.cs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,18 @@ public static float Round(float x, int digits)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Round(float x, MidpointRounding mode)
{
// Inline single-instruction modes
if (RuntimeHelpers.IsKnownConstant((int)mode))
EgorBo marked this conversation as resolved.
Show resolved Hide resolved
{
if (mode == MidpointRounding.ToEven)
return Round(x);

// For ARM/ARM64 we can lower it down to a single instruction FRINTA
// For XARCH we have to use the common path
if (AdvSimd.IsSupported && mode == MidpointRounding.AwayFromZero)
return AdvSimd.RoundAwayFromZero(Vector64.CreateScalarUnsafe(x)).ToScalar();
EgorBo marked this conversation as resolved.
Show resolved Hide resolved
}

return Round(x, 0, mode);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,5 +127,8 @@ internal static bool IsPrimitiveType(this CorElementType et)

[Intrinsic]
internal static bool IsKnownConstant(char t) => false;

[Intrinsic]
internal static bool IsKnownConstant(int t) => false;
}
}