Skip to content

Commit

Permalink
Arm64/SVE: Implemented RoundAwayFromZero, RoundToNearest, `RouteT…
Browse files Browse the repository at this point in the history
…oNegativeInfininty`, `RoundToPositiveInfinity`, `RoundToZero` (#103588)

* Added ConverToInt32 and ConvertToUInt32 for float inputs.

* Added flags to handle only low predicate registers.

* Fix whitespace

* Remove special codegen flag

* Added new test template for operations with different return types.

* Add new test template.

* Added api for ConvertToInt32 and ConvertToUInt 32 for double.

* Round SVE intrinsics for floats.

* Completed Round SVE fp apis.
  • Loading branch information
ebepho authored Jun 18, 2024
1 parent 547e69e commit b93061a
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/coreclr/jit/hwintrinsiclistarm64sve.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ HARDWARE_INTRINSIC(Sve, ReverseElement,
HARDWARE_INTRINSIC(Sve, ReverseElement16, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_revh, INS_sve_revh, INS_sve_revh, INS_sve_revh, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation)
HARDWARE_INTRINSIC(Sve, ReverseElement32, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_revw, INS_sve_revw, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation)
HARDWARE_INTRINSIC(Sve, ReverseElement8, -1, -1, false, {INS_invalid, INS_invalid, INS_sve_revb, INS_sve_revb, INS_sve_revb, INS_sve_revb, INS_sve_revb, INS_sve_revb, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation)
HARDWARE_INTRINSIC(Sve, RoundAwayFromZero, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_frinta, INS_sve_frinta}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation)
HARDWARE_INTRINSIC(Sve, RoundToNearest, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_frintn, INS_sve_frintn}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation)
HARDWARE_INTRINSIC(Sve, RoundToNegativeInfinity, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_frintm, INS_sve_frintm}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation)
HARDWARE_INTRINSIC(Sve, RoundToPositiveInfinity, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_frintp, INS_sve_frintp}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation)
HARDWARE_INTRINSIC(Sve, RoundToZero, -1, -1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_frintz, INS_sve_frintz}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_EmbeddedMaskedOperation|HW_Flag_EmbeddedMaskedOperation|HW_Flag_LowMaskedOperation)
HARDWARE_INTRINSIC(Sve, SaturatingDecrementBy16BitElementCount, -1, 3, true, {INS_invalid, INS_invalid, INS_sve_sqdech, INS_sve_uqdech, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_HasEnumOperand|HW_Flag_SpecialCodeGen|HW_Flag_HasScalarInputVariant|HW_Flag_SpecialImport|HW_Flag_HasRMWSemantics)
HARDWARE_INTRINSIC(Sve, SaturatingDecrementBy32BitElementCount, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sqdecw, INS_sve_uqdecw, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_HasEnumOperand|HW_Flag_SpecialCodeGen|HW_Flag_HasScalarInputVariant|HW_Flag_SpecialImport|HW_Flag_HasRMWSemantics)
HARDWARE_INTRINSIC(Sve, SaturatingDecrementBy64BitElementCount, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sve_sqdecd, INS_sve_uqdecd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Scalable|HW_Flag_HasImmediateOperand|HW_Flag_HasEnumOperand|HW_Flag_SpecialCodeGen|HW_Flag_HasScalarInputVariant|HW_Flag_SpecialImport|HW_Flag_HasRMWSemantics)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4351,6 +4351,111 @@ internal Arm64() { }
public static unsafe Vector<ulong> ReverseElement8(Vector<ulong> value) { throw new PlatformNotSupportedException(); }


/// RoundAwayFromZero : Round to nearest, ties away from zero

/// <summary>
/// svfloat64_t svrinta[_f64]_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op)
/// FRINTA Ztied.D, Pg/M, Zop.D
/// svfloat64_t svrinta[_f64]_x(svbool_t pg, svfloat64_t op)
/// FRINTA Ztied.D, Pg/M, Ztied.D
/// svfloat64_t svrinta[_f64]_z(svbool_t pg, svfloat64_t op)
/// </summary>
public static unsafe Vector<double> RoundAwayFromZero(Vector<double> value) { throw new PlatformNotSupportedException(); }

/// <summary>
/// svfloat32_t svrinta[_f32]_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op)
/// FRINTA Ztied.S, Pg/M, Zop.S
/// svfloat32_t svrinta[_f32]_x(svbool_t pg, svfloat32_t op)
/// FRINTA Ztied.S, Pg/M, Ztied.S
/// svfloat32_t svrinta[_f32]_z(svbool_t pg, svfloat32_t op)
/// </summary>
public static unsafe Vector<float> RoundAwayFromZero(Vector<float> value) { throw new PlatformNotSupportedException(); }


/// RoundToNearest : Round to nearest, ties to even

/// <summary>
/// svfloat64_t svrintn[_f64]_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op)
/// FRINTN Ztied.D, Pg/M, Zop.D
/// svfloat64_t svrintn[_f64]_x(svbool_t pg, svfloat64_t op)
/// FRINTN Ztied.D, Pg/M, Ztied.D
/// svfloat64_t svrintn[_f64]_z(svbool_t pg, svfloat64_t op)
/// </summary>
public static unsafe Vector<double> RoundToNearest(Vector<double> value) { throw new PlatformNotSupportedException(); }

/// <summary>
/// svfloat32_t svrintn[_f32]_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op)
/// FRINTN Ztied.S, Pg/M, Zop.S
/// svfloat32_t svrintn[_f32]_x(svbool_t pg, svfloat32_t op)
/// FRINTN Ztied.S, Pg/M, Ztied.S
/// svfloat32_t svrintn[_f32]_z(svbool_t pg, svfloat32_t op)
/// </summary>
public static unsafe Vector<float> RoundToNearest(Vector<float> value) { throw new PlatformNotSupportedException(); }


/// RoundToNegativeInfinity : Round towards -∞

/// <summary>
/// svfloat64_t svrintm[_f64]_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op)
/// FRINTM Ztied.D, Pg/M, Zop.D
/// svfloat64_t svrintm[_f64]_x(svbool_t pg, svfloat64_t op)
/// FRINTM Ztied.D, Pg/M, Ztied.D
/// svfloat64_t svrintm[_f64]_z(svbool_t pg, svfloat64_t op)
/// </summary>
public static unsafe Vector<double> RoundToNegativeInfinity(Vector<double> value) { throw new PlatformNotSupportedException(); }

/// <summary>
/// svfloat32_t svrintm[_f32]_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op)
/// FRINTM Ztied.S, Pg/M, Zop.S
/// svfloat32_t svrintm[_f32]_x(svbool_t pg, svfloat32_t op)
/// FRINTM Ztied.S, Pg/M, Ztied.S
/// svfloat32_t svrintm[_f32]_z(svbool_t pg, svfloat32_t op)
/// </summary>
public static unsafe Vector<float> RoundToNegativeInfinity(Vector<float> value) { throw new PlatformNotSupportedException(); }


/// RoundToPositiveInfinity : Round towards +∞

/// <summary>
/// svfloat64_t svrintp[_f64]_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op)
/// FRINTP Ztied.D, Pg/M, Zop.D
/// svfloat64_t svrintp[_f64]_x(svbool_t pg, svfloat64_t op)
/// FRINTP Ztied.D, Pg/M, Ztied.D
/// svfloat64_t svrintp[_f64]_z(svbool_t pg, svfloat64_t op)
/// </summary>
public static unsafe Vector<double> RoundToPositiveInfinity(Vector<double> value) { throw new PlatformNotSupportedException(); }

/// <summary>
/// svfloat32_t svrintp[_f32]_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op)
/// FRINTP Ztied.S, Pg/M, Zop.S
/// svfloat32_t svrintp[_f32]_x(svbool_t pg, svfloat32_t op)
/// FRINTP Ztied.S, Pg/M, Ztied.S
/// svfloat32_t svrintp[_f32]_z(svbool_t pg, svfloat32_t op)
/// </summary>
public static unsafe Vector<float> RoundToPositiveInfinity(Vector<float> value) { throw new PlatformNotSupportedException(); }


/// RoundToZero : Round towards zero

/// <summary>
/// svfloat64_t svrintz[_f64]_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op)
/// FRINTZ Ztied.D, Pg/M, Zop.D
/// svfloat64_t svrintz[_f64]_x(svbool_t pg, svfloat64_t op)
/// FRINTZ Ztied.D, Pg/M, Ztied.D
/// svfloat64_t svrintz[_f64]_z(svbool_t pg, svfloat64_t op)
/// </summary>
public static unsafe Vector<double> RoundToZero(Vector<double> value) { throw new PlatformNotSupportedException(); }

/// <summary>
/// svfloat32_t svrintz[_f32]_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op)
/// FRINTZ Ztied.S, Pg/M, Zop.S
/// svfloat32_t svrintz[_f32]_x(svbool_t pg, svfloat32_t op)
/// FRINTZ Ztied.S, Pg/M, Ztied.S
/// svfloat32_t svrintz[_f32]_z(svbool_t pg, svfloat32_t op)
/// </summary>
public static unsafe Vector<float> RoundToZero(Vector<float> value) { throw new PlatformNotSupportedException(); }


/// Saturating decrement by number of halfword elements

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4405,6 +4405,111 @@ internal Arm64() { }
public static unsafe Vector<ulong> ReverseElement8(Vector<ulong> value) => ReverseElement8(value);


/// RoundAwayFromZero : Round to nearest, ties away from zero

/// <summary>
/// svfloat64_t svrinta[_f64]_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op)
/// FRINTA Ztied.D, Pg/M, Zop.D
/// svfloat64_t svrinta[_f64]_x(svbool_t pg, svfloat64_t op)
/// FRINTA Ztied.D, Pg/M, Ztied.D
/// svfloat64_t svrinta[_f64]_z(svbool_t pg, svfloat64_t op)
/// </summary>
public static unsafe Vector<double> RoundAwayFromZero(Vector<double> value) => RoundAwayFromZero(value);

/// <summary>
/// svfloat32_t svrinta[_f32]_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op)
/// FRINTA Ztied.S, Pg/M, Zop.S
/// svfloat32_t svrinta[_f32]_x(svbool_t pg, svfloat32_t op)
/// FRINTA Ztied.S, Pg/M, Ztied.S
/// svfloat32_t svrinta[_f32]_z(svbool_t pg, svfloat32_t op)
/// </summary>
public static unsafe Vector<float> RoundAwayFromZero(Vector<float> value) => RoundAwayFromZero(value);


/// RoundToNearest : Round to nearest, ties to even

/// <summary>
/// svfloat64_t svrintn[_f64]_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op)
/// FRINTN Ztied.D, Pg/M, Zop.D
/// svfloat64_t svrintn[_f64]_x(svbool_t pg, svfloat64_t op)
/// FRINTN Ztied.D, Pg/M, Ztied.D
/// svfloat64_t svrintn[_f64]_z(svbool_t pg, svfloat64_t op)
/// </summary>
public static unsafe Vector<double> RoundToNearest(Vector<double> value) => RoundToNearest(value);

/// <summary>
/// svfloat32_t svrintn[_f32]_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op)
/// FRINTN Ztied.S, Pg/M, Zop.S
/// svfloat32_t svrintn[_f32]_x(svbool_t pg, svfloat32_t op)
/// FRINTN Ztied.S, Pg/M, Ztied.S
/// svfloat32_t svrintn[_f32]_z(svbool_t pg, svfloat32_t op)
/// </summary>
public static unsafe Vector<float> RoundToNearest(Vector<float> value) => RoundToNearest(value);


/// RoundToNegativeInfinity : Round towards -∞

/// <summary>
/// svfloat64_t svrintm[_f64]_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op)
/// FRINTM Ztied.D, Pg/M, Zop.D
/// svfloat64_t svrintm[_f64]_x(svbool_t pg, svfloat64_t op)
/// FRINTM Ztied.D, Pg/M, Ztied.D
/// svfloat64_t svrintm[_f64]_z(svbool_t pg, svfloat64_t op)
/// </summary>
public static unsafe Vector<double> RoundToNegativeInfinity(Vector<double> value) => RoundToNegativeInfinity(value);

/// <summary>
/// svfloat32_t svrintm[_f32]_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op)
/// FRINTM Ztied.S, Pg/M, Zop.S
/// svfloat32_t svrintm[_f32]_x(svbool_t pg, svfloat32_t op)
/// FRINTM Ztied.S, Pg/M, Ztied.S
/// svfloat32_t svrintm[_f32]_z(svbool_t pg, svfloat32_t op)
/// </summary>
public static unsafe Vector<float> RoundToNegativeInfinity(Vector<float> value) => RoundToNegativeInfinity(value);


/// RoundToPositiveInfinity : Round towards +∞

/// <summary>
/// svfloat64_t svrintp[_f64]_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op)
/// FRINTP Ztied.D, Pg/M, Zop.D
/// svfloat64_t svrintp[_f64]_x(svbool_t pg, svfloat64_t op)
/// FRINTP Ztied.D, Pg/M, Ztied.D
/// svfloat64_t svrintp[_f64]_z(svbool_t pg, svfloat64_t op)
/// </summary>
public static unsafe Vector<double> RoundToPositiveInfinity(Vector<double> value) => RoundToPositiveInfinity(value);

/// <summary>
/// svfloat32_t svrintp[_f32]_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op)
/// FRINTP Ztied.S, Pg/M, Zop.S
/// svfloat32_t svrintp[_f32]_x(svbool_t pg, svfloat32_t op)
/// FRINTP Ztied.S, Pg/M, Ztied.S
/// svfloat32_t svrintp[_f32]_z(svbool_t pg, svfloat32_t op)
/// </summary>
public static unsafe Vector<float> RoundToPositiveInfinity(Vector<float> value) => RoundToPositiveInfinity(value);


/// RoundToZero : Round towards zero

/// <summary>
/// svfloat64_t svrintz[_f64]_m(svfloat64_t inactive, svbool_t pg, svfloat64_t op)
/// FRINTZ Ztied.D, Pg/M, Zop.D
/// svfloat64_t svrintz[_f64]_x(svbool_t pg, svfloat64_t op)
/// FRINTZ Ztied.D, Pg/M, Ztied.D
/// svfloat64_t svrintz[_f64]_z(svbool_t pg, svfloat64_t op)
/// </summary>
public static unsafe Vector<double> RoundToZero(Vector<double> value) => RoundToZero(value);

/// <summary>
/// svfloat32_t svrintz[_f32]_m(svfloat32_t inactive, svbool_t pg, svfloat32_t op)
/// FRINTZ Ztied.S, Pg/M, Zop.S
/// svfloat32_t svrintz[_f32]_x(svbool_t pg, svfloat32_t op)
/// FRINTZ Ztied.S, Pg/M, Ztied.S
/// svfloat32_t svrintz[_f32]_z(svbool_t pg, svfloat32_t op)
/// </summary>
public static unsafe Vector<float> RoundToZero(Vector<float> value) => RoundToZero(value);


/// Saturating decrement by number of halfword elements

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4816,6 +4816,17 @@ internal Arm64() { }
public static System.Numerics.Vector<uint> ReverseElement8(System.Numerics.Vector<uint> value) { throw null; }
public static System.Numerics.Vector<ulong> ReverseElement8(System.Numerics.Vector<ulong> value) { throw null; }

public static System.Numerics.Vector<double> RoundAwayFromZero(System.Numerics.Vector<double> value) { throw null; }
public static System.Numerics.Vector<float> RoundAwayFromZero(System.Numerics.Vector<float> value) { throw null; }
public static System.Numerics.Vector<double> RoundToNearest(System.Numerics.Vector<double> value) { throw null; }
public static System.Numerics.Vector<float> RoundToNearest(System.Numerics.Vector<float> value) { throw null; }
public static System.Numerics.Vector<double> RoundToNegativeInfinity(System.Numerics.Vector<double> value) { throw null; }
public static System.Numerics.Vector<float> RoundToNegativeInfinity(System.Numerics.Vector<float> value) { throw null; }
public static System.Numerics.Vector<double> RoundToPositiveInfinity(System.Numerics.Vector<double> value) { throw null; }
public static System.Numerics.Vector<float> RoundToPositiveInfinity(System.Numerics.Vector<float> value) { throw null; }
public static System.Numerics.Vector<double> RoundToZero(System.Numerics.Vector<double> value) { throw null; }
public static System.Numerics.Vector<float> RoundToZero(System.Numerics.Vector<float> value) { throw null; }

public static int SaturatingDecrementBy16BitElementCount(int value, [ConstantExpected(Min = 1, Max = (byte)(16))] byte scale, [ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; }
public static long SaturatingDecrementBy16BitElementCount(long value, [ConstantExpected(Min = 1, Max = (byte)(16))] byte scale, [ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; }
public static uint SaturatingDecrementBy16BitElementCount(uint value, [ConstantExpected(Min = 1, Max = (byte)(16))] byte scale, [ConstantExpected] SveMaskPattern pattern = SveMaskPattern.All) { throw null; }
Expand Down
Loading

0 comments on commit b93061a

Please sign in to comment.