From 4bab1d8913fde2f11fc5c9da6b3ad7ac1b79ec71 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 5 Jun 2024 14:46:23 -0700 Subject: [PATCH 1/5] Minor cleanup of the Vector64/128/256/512 implementations to improve fallbacks --- .../src/System/Numerics/Vector.cs | 2 +- .../System/Runtime/Intrinsics/Vector128.cs | 96 +++++++++------ .../System/Runtime/Intrinsics/Vector128_1.cs | 77 ++++++------ .../System/Runtime/Intrinsics/Vector256.cs | 104 +++++++++------- .../System/Runtime/Intrinsics/Vector256_1.cs | 77 ++++++------ .../System/Runtime/Intrinsics/Vector512.cs | 112 ++++++++++-------- .../System/Runtime/Intrinsics/Vector512_1.cs | 77 ++++++------ .../src/System/Runtime/Intrinsics/Vector64.cs | 2 +- .../System/Runtime/Intrinsics/Vector64_1.cs | 61 ++++------ 9 files changed, 310 insertions(+), 298 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs index 41961bbb54c79..9af865a30fea4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs @@ -1186,7 +1186,7 @@ public static Vector Min(Vector left, Vector right) /// The type of the elements in the vector. /// The product of and . [Intrinsic] - public static Vector Multiply(T left, Vector right) => left * right; + public static Vector Multiply(T left, Vector right) => right * left; /// [Intrinsic] diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs index 7f83b8c09d79e..1cda7d5ccdb21 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs @@ -58,10 +58,21 @@ public static bool IsHardwareAccelerated [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Abs(Vector128 vector) { - return Create( - Vector64.Abs(vector._lower), - Vector64.Abs(vector._upper) - ); + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return vector; + } + else + { + return Create( + Vector64.Abs(vector._lower), + Vector64.Abs(vector._upper) + ); + } } /// Adds two vectors to compute their sum. @@ -80,13 +91,7 @@ public static Vector128 Abs(Vector128 vector) /// The bitwise-and of and the ones-complement of . [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 AndNot(Vector128 left, Vector128 right) - { - return Create( - Vector64.AndNot(left._lower, right._lower), - Vector64.AndNot(left._upper, right._upper) - ); - } + public static Vector128 AndNot(Vector128 left, Vector128 right) => left & ~right; /// Reinterprets a as a new . /// The type of the elements in the input vector. @@ -377,10 +382,26 @@ public static Vector AsVector(this Vector128 value) [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Vector128 Ceiling(Vector128 vector) { - return Create( - Vector64.Ceiling(vector._lower), - Vector64.Ceiling(vector._upper) - ); + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint)) + || (typeof(T) == typeof(nuint)) + || (typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong))) + { + return vector; + } + else + { + return Create( + Vector64.Ceiling(vector._lower), + Vector64.Ceiling(vector._upper) + ); + } } /// Computes the ceiling of each element in a vector. @@ -406,13 +427,7 @@ internal static Vector128 Ceiling(Vector128 vector) /// The type of , , and () is not supported. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 ConditionalSelect(Vector128 condition, Vector128 left, Vector128 right) - { - return Create( - Vector64.ConditionalSelect(condition._lower, left._lower, right._lower), - Vector64.ConditionalSelect(condition._upper, left._upper, right._upper) - ); - } + public static Vector128 ConditionalSelect(Vector128 condition, Vector128 left, Vector128 right) => (left & condition) | (right & ~condition); /// Converts a to a . /// The vector to convert. @@ -1413,16 +1428,7 @@ public static Vector128 CreateScalarUnsafe(T value) /// The type of and () is not supported. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T Dot(Vector128 left, Vector128 right) - { - // Doing this as Dot(lower) + Dot(upper) is important for floating-point determinism - // This is because the underlying dpps instruction on x86/x64 will do this equivalently - // and otherwise the software vs accelerated implementations may differ in returned result. - - T result = Vector64.Dot(left._lower, right._lower); - result = Scalar.Add(result, Vector64.Dot(left._upper, right._upper)); - return result; - } + public static T Dot(Vector128 left, Vector128 right) => Sum(left * right); /// Compares two vectors to determine if they are equal on a per-element basis. /// The type of the elements in the vector. @@ -1519,10 +1525,26 @@ public static uint ExtractMostSignificantBits(this Vector128 vector) [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Vector128 Floor(Vector128 vector) { - return Create( - Vector64.Floor(vector._lower), - Vector64.Floor(vector._upper) - ); + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint)) + || (typeof(T) == typeof(nuint)) + || (typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong))) + { + return vector; + } + else + { + return Create( + Vector64.Floor(vector._lower), + Vector64.Floor(vector._upper) + ); + } } /// Computes the floor of each element in a vector. @@ -1989,7 +2011,7 @@ public static Vector128 Min(Vector128 left, Vector128 right) /// The product of and . /// The type of and () is not supported. [Intrinsic] - public static Vector128 Multiply(T left, Vector128 right) => left * right; + public static Vector128 Multiply(T left, Vector128 right) => right * left; /// [Intrinsic] diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs index c9f1b6e3f21ef..50d5290d44a3d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs @@ -39,20 +39,22 @@ namespace System.Runtime.Intrinsics public static Vector128 AllBitsSet { [Intrinsic] - get - { - Vector64 vector = Vector64.AllBitsSet; - return Vector128.Create(vector, vector); - } + get => Vector128.Create(Scalar.AllBitsSet); } +#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') /// Gets the number of that are in a . /// The type of the vector () is not supported. public static int Count { [Intrinsic] - get => Vector64.Count * 2; + get + { + ThrowHelper.ThrowForUnsupportedIntrinsicsVector128BaseType(); + return Vector128.Size / sizeof(T); + } } +#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') /// Gets a new with the elements set to their index. /// The type of the vector () is not supported. @@ -102,11 +104,7 @@ public static bool IsSupported public static Vector128 One { [Intrinsic] - get - { - Vector64 vector = Vector64.One; - return Vector128.Create(vector, vector); - } + get => Vector128.Create(Scalar.One); } /// Gets a new with all elements initialized to zero. @@ -341,14 +339,7 @@ public static Vector128 operator >>(Vector128 value, int shiftCount) /// A vector whose elements are the unary negation of the corresponding elements in . /// The type of the vector () is not supported. [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 operator -(Vector128 vector) - { - return Vector128.Create( - -vector._lower, - -vector._upper - ); - } + public static Vector128 operator -(Vector128 vector) => Zero - vector; /// Returns a given vector unchanged. /// The vector. @@ -474,16 +465,16 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector128 ISimdVector, T>.Abs(Vector128 vector) => Vector128.Abs(vector); /// - static Vector128 ISimdVector, T>.Add(Vector128 left, Vector128 right) => Vector128.Add(left, right); + static Vector128 ISimdVector, T>.Add(Vector128 left, Vector128 right) => left + right; /// static Vector128 ISimdVector, T>.AndNot(Vector128 left, Vector128 right) => Vector128.AndNot(left, right); /// - static Vector128 ISimdVector, T>.BitwiseAnd(Vector128 left, Vector128 right) => Vector128.BitwiseAnd(left, right); + static Vector128 ISimdVector, T>.BitwiseAnd(Vector128 left, Vector128 right) => left & right; /// - static Vector128 ISimdVector, T>.BitwiseOr(Vector128 left, Vector128 right) => Vector128.BitwiseOr(left, right); + static Vector128 ISimdVector, T>.BitwiseOr(Vector128 left, Vector128 right) => left | right; /// static Vector128 ISimdVector, T>.Ceiling(Vector128 vector) => Vector128.Ceiling(vector); @@ -519,10 +510,10 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector128 ISimdVector, T>.CreateScalarUnsafe(T value) => Vector128.CreateScalarUnsafe(value); /// - static Vector128 ISimdVector, T>.Divide(Vector128 left, Vector128 right) => Vector128.Divide(left, right); + static Vector128 ISimdVector, T>.Divide(Vector128 left, Vector128 right) => left / right; /// - static Vector128 ISimdVector, T>.Divide(Vector128 left, T right) => Vector128.Divide(left, right); + static Vector128 ISimdVector, T>.Divide(Vector128 left, T right) => left / right; /// static T ISimdVector, T>.Dot(Vector128 left, Vector128 right) => Vector128.Dot(left, right); @@ -531,7 +522,7 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector128 ISimdVector, T>.Equals(Vector128 left, Vector128 right) => Vector128.Equals(left, right); /// - static bool ISimdVector, T>.EqualsAll(Vector128 left, Vector128 right) => Vector128.EqualsAll(left, right); + static bool ISimdVector, T>.EqualsAll(Vector128 left, Vector128 right) => left == right; /// static bool ISimdVector, T>.EqualsAny(Vector128 left, Vector128 right) => Vector128.EqualsAny(left, right); @@ -540,7 +531,7 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector128 ISimdVector, T>.Floor(Vector128 vector) => Vector128.Floor(vector); /// - static T ISimdVector, T>.GetElement(Vector128 vector, int index) => Vector128.GetElement(vector, index); + static T ISimdVector, T>.GetElement(Vector128 vector, int index) => vector.GetElement(index); /// static Vector128 ISimdVector, T>.GreaterThan(Vector128 left, Vector128 right) => Vector128.GreaterThan(left, right); @@ -602,63 +593,63 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector128 ISimdVector, T>.Min(Vector128 left, Vector128 right) => Vector128.Min(left, right); /// - static Vector128 ISimdVector, T>.Multiply(Vector128 left, Vector128 right) => Vector128.Multiply(left, right); + static Vector128 ISimdVector, T>.Multiply(Vector128 left, Vector128 right) => left * right; /// - static Vector128 ISimdVector, T>.Multiply(Vector128 left, T right) => Vector128.Multiply(left, right); + static Vector128 ISimdVector, T>.Multiply(Vector128 left, T right) => left * right; /// - static Vector128 ISimdVector, T>.Negate(Vector128 vector) => Vector128.Negate(vector); + static Vector128 ISimdVector, T>.Negate(Vector128 vector) => -vector; /// - static Vector128 ISimdVector, T>.OnesComplement(Vector128 vector) => Vector128.OnesComplement(vector); + static Vector128 ISimdVector, T>.OnesComplement(Vector128 vector) => ~vector; /// - static Vector128 ISimdVector, T>.ShiftLeft(Vector128 vector, int shiftCount) => Vector128.ShiftLeft(vector, shiftCount); + static Vector128 ISimdVector, T>.ShiftLeft(Vector128 vector, int shiftCount) => vector << shiftCount; /// - static Vector128 ISimdVector, T>.ShiftRightArithmetic(Vector128 vector, int shiftCount) => Vector128.ShiftRightArithmetic(vector, shiftCount); + static Vector128 ISimdVector, T>.ShiftRightArithmetic(Vector128 vector, int shiftCount) => vector >> shiftCount; /// - static Vector128 ISimdVector, T>.ShiftRightLogical(Vector128 vector, int shiftCount) => Vector128.ShiftRightLogical(vector, shiftCount); + static Vector128 ISimdVector, T>.ShiftRightLogical(Vector128 vector, int shiftCount) => vector >>> shiftCount; /// static Vector128 ISimdVector, T>.Sqrt(Vector128 vector) => Vector128.Sqrt(vector); #pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') /// - static void ISimdVector, T>.Store(Vector128 source, T* destination) => Vector128.Store(source, destination); + static void ISimdVector, T>.Store(Vector128 source, T* destination) => source.Store(destination); /// - static void ISimdVector, T>.StoreAligned(Vector128 source, T* destination) => Vector128.StoreAligned(source, destination); + static void ISimdVector, T>.StoreAligned(Vector128 source, T* destination) => source.StoreAligned(destination); /// - static void ISimdVector, T>.StoreAlignedNonTemporal(Vector128 source, T* destination) => Vector128.StoreAlignedNonTemporal(source, destination); + static void ISimdVector, T>.StoreAlignedNonTemporal(Vector128 source, T* destination) => source.StoreAlignedNonTemporal(destination); #pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') /// - static void ISimdVector, T>.StoreUnsafe(Vector128 vector, ref T destination) => Vector128.StoreUnsafe(vector, ref destination); + static void ISimdVector, T>.StoreUnsafe(Vector128 vector, ref T destination) => vector.StoreUnsafe(ref destination); /// - static void ISimdVector, T>.StoreUnsafe(Vector128 vector, ref T destination, nuint elementOffset) => Vector128.StoreUnsafe(vector, ref destination, elementOffset); + static void ISimdVector, T>.StoreUnsafe(Vector128 vector, ref T destination, nuint elementOffset) => vector.StoreUnsafe(ref destination, elementOffset); /// - static Vector128 ISimdVector, T>.Subtract(Vector128 left, Vector128 right) => Vector128.Subtract(left, right); + static Vector128 ISimdVector, T>.Subtract(Vector128 left, Vector128 right) => left - right; /// static T ISimdVector, T>.Sum(Vector128 vector) => Vector128.Sum(vector); /// - static T ISimdVector, T>.ToScalar(Vector128 vector) => Vector128.ToScalar(vector); + static T ISimdVector, T>.ToScalar(Vector128 vector) => vector.ToScalar(); /// - static bool ISimdVector, T>.TryCopyTo(Vector128 vector, Span destination) => Vector128.TryCopyTo(vector, destination); + static bool ISimdVector, T>.TryCopyTo(Vector128 vector, Span destination) => vector.TryCopyTo(destination); /// - static Vector128 ISimdVector, T>.WithElement(Vector128 vector, int index, T value) => Vector128.WithElement(vector, index, value); + static Vector128 ISimdVector, T>.WithElement(Vector128 vector, int index, T value) => vector.WithElement(index, value); /// - static Vector128 ISimdVector, T>.Xor(Vector128 left, Vector128 right) => Vector128.Xor(left, right); + static Vector128 ISimdVector, T>.Xor(Vector128 left, Vector128 right) => left ^ right; // // New Surface Area diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs index e8f16472b3695..69b116885282c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs @@ -62,10 +62,21 @@ public static bool IsHardwareAccelerated [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 Abs(Vector256 vector) { - return Create( - Vector128.Abs(vector._lower), - Vector128.Abs(vector._upper) - ); + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return vector; + } + else + { + return Create( + Vector128.Abs(vector._lower), + Vector128.Abs(vector._upper) + ); + } } /// Adds two vectors to compute their sum. @@ -85,13 +96,7 @@ public static Vector256 Abs(Vector256 vector) /// The type of and () is not supported. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector256 AndNot(Vector256 left, Vector256 right) - { - return Create( - Vector128.AndNot(left._lower, right._lower), - Vector128.AndNot(left._upper, right._upper) - ); - } + public static Vector256 AndNot(Vector256 left, Vector256 right) => left & ~right; /// Reinterprets a as a new . /// The type of the elements in the input vector. @@ -272,10 +277,26 @@ public static Vector AsVector(this Vector256 value) [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Vector256 Ceiling(Vector256 vector) { - return Create( - Vector128.Ceiling(vector._lower), - Vector128.Ceiling(vector._upper) - ); + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint)) + || (typeof(T) == typeof(nuint)) + || (typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong))) + { + return vector; + } + else + { + return Create( + Vector128.Ceiling(vector._lower), + Vector128.Ceiling(vector._upper) + ); + } } /// Computes the ceiling of each element in a vector. @@ -301,13 +322,7 @@ internal static Vector256 Ceiling(Vector256 vector) /// The type of , , and () is not supported. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector256 ConditionalSelect(Vector256 condition, Vector256 left, Vector256 right) - { - return Create( - Vector128.ConditionalSelect(condition._lower, left._lower, right._lower), - Vector128.ConditionalSelect(condition._upper, left._upper, right._upper) - ); - } + public static Vector256 ConditionalSelect(Vector256 condition, Vector256 left, Vector256 right) => (left & condition) | (right & ~condition); /// Converts a to a . /// The vector to convert. @@ -1353,16 +1368,7 @@ public static Vector256 CreateScalarUnsafe(T value) /// The type of and () is not supported. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T Dot(Vector256 left, Vector256 right) - { - // Doing this as Dot(lower) + Dot(upper) is important for floating-point determinism - // This is because the underlying dpps instruction on x86/x64 will do this equivalently - // and otherwise the software vs accelerated implementations may differ in returned result. - - T result = Vector128.Dot(left._lower, right._lower); - result = Scalar.Add(result, Vector128.Dot(left._upper, right._upper)); - return result; - } + public static T Dot(Vector256 left, Vector256 right) => Sum(left * right); /// Compares two vectors to determine if they are equal on a per-element basis. /// The type of the elements in the vector. @@ -1459,10 +1465,26 @@ public static uint ExtractMostSignificantBits(this Vector256 vector) [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Vector256 Floor(Vector256 vector) { - return Create( - Vector128.Floor(vector._lower), - Vector128.Floor(vector._upper) - ); + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint)) + || (typeof(T) == typeof(nuint)) + || (typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong))) + { + return vector; + } + else + { + return Create( + Vector128.Floor(vector._lower), + Vector128.Floor(vector._upper) + ); + } } /// Computes the floor of each element in a vector. @@ -1927,7 +1949,7 @@ public static Vector256 Min(Vector256 left, Vector256 right) /// The product of and . /// The type of and () is not supported. [Intrinsic] - public static Vector256 Multiply(T left, Vector256 right) => left * right; + public static Vector256 Multiply(T left, Vector256 right) => right * left; /// [Intrinsic] @@ -2067,13 +2089,7 @@ public static Vector256 Narrow(Vector256 lower, Vector256 up /// A vector whose elements are the ones-complement of the corresponding elements in . /// The type of () is not supported. [Intrinsic] - public static Vector256 OnesComplement(Vector256 vector) - { - return Create( - Vector128.OnesComplement(vector._lower), - Vector128.OnesComplement(vector._upper) - ); - } + public static Vector256 OnesComplement(Vector256 vector) => ~vector; /// Shifts each element of a vector left by the specified amount. /// The vector whose elements are to be shifted. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs index 36b704682d320..c4120a2c2febe 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs @@ -38,20 +38,22 @@ namespace System.Runtime.Intrinsics public static Vector256 AllBitsSet { [Intrinsic] - get - { - Vector128 vector = Vector128.AllBitsSet; - return Vector256.Create(vector, vector); - } + get => Vector256.Create(Scalar.AllBitsSet); } +#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') /// Gets the number of that are in a . /// The type of the vector () is not supported. public static int Count { [Intrinsic] - get => Vector128.Count * 2; + get + { + ThrowHelper.ThrowForUnsupportedIntrinsicsVector128BaseType(); + return Vector256.Size / sizeof(T); + } } +#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') /// Gets a new with the elements set to their index. /// The type of the vector () is not supported. @@ -101,11 +103,7 @@ public static bool IsSupported public static Vector256 One { [Intrinsic] - get - { - Vector128 vector = Vector128.One; - return Vector256.Create(vector, vector); - } + get => Vector256.Create(Scalar.One); } /// Gets a new with all elements initialized to zero. @@ -339,14 +337,7 @@ public static Vector256 operator >>(Vector256 value, int shiftCount) /// A vector whose elements are the unary negation of the corresponding elements in . /// The type of the vector () is not supported. [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector256 operator -(Vector256 vector) - { - return Vector256.Create( - -vector._lower, - -vector._upper - ); - } + public static Vector256 operator -(Vector256 vector) => Zero - vector; /// Returns a given vector unchanged. /// The vector. @@ -463,16 +454,16 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector256 ISimdVector, T>.Abs(Vector256 vector) => Vector256.Abs(vector); /// - static Vector256 ISimdVector, T>.Add(Vector256 left, Vector256 right) => Vector256.Add(left, right); + static Vector256 ISimdVector, T>.Add(Vector256 left, Vector256 right) => left + right; /// static Vector256 ISimdVector, T>.AndNot(Vector256 left, Vector256 right) => Vector256.AndNot(left, right); /// - static Vector256 ISimdVector, T>.BitwiseAnd(Vector256 left, Vector256 right) => Vector256.BitwiseAnd(left, right); + static Vector256 ISimdVector, T>.BitwiseAnd(Vector256 left, Vector256 right) => left & right; /// - static Vector256 ISimdVector, T>.BitwiseOr(Vector256 left, Vector256 right) => Vector256.BitwiseOr(left, right); + static Vector256 ISimdVector, T>.BitwiseOr(Vector256 left, Vector256 right) => left | right; /// static Vector256 ISimdVector, T>.Ceiling(Vector256 vector) => Vector256.Ceiling(vector); @@ -508,10 +499,10 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector256 ISimdVector, T>.CreateScalarUnsafe(T value) => Vector256.CreateScalarUnsafe(value); /// - static Vector256 ISimdVector, T>.Divide(Vector256 left, Vector256 right) => Vector256.Divide(left, right); + static Vector256 ISimdVector, T>.Divide(Vector256 left, Vector256 right) => left / right; /// - static Vector256 ISimdVector, T>.Divide(Vector256 left, T right) => Vector256.Divide(left, right); + static Vector256 ISimdVector, T>.Divide(Vector256 left, T right) => left / right; /// static T ISimdVector, T>.Dot(Vector256 left, Vector256 right) => Vector256.Dot(left, right); @@ -520,7 +511,7 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector256 ISimdVector, T>.Equals(Vector256 left, Vector256 right) => Vector256.Equals(left, right); /// - static bool ISimdVector, T>.EqualsAll(Vector256 left, Vector256 right) => Vector256.EqualsAll(left, right); + static bool ISimdVector, T>.EqualsAll(Vector256 left, Vector256 right) => left == right; /// static bool ISimdVector, T>.EqualsAny(Vector256 left, Vector256 right) => Vector256.EqualsAny(left, right); @@ -529,7 +520,7 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector256 ISimdVector, T>.Floor(Vector256 vector) => Vector256.Floor(vector); /// - static T ISimdVector, T>.GetElement(Vector256 vector, int index) => Vector256.GetElement(vector, index); + static T ISimdVector, T>.GetElement(Vector256 vector, int index) => vector.GetElement(index); /// static Vector256 ISimdVector, T>.GreaterThan(Vector256 left, Vector256 right) => Vector256.GreaterThan(left, right); @@ -591,63 +582,63 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector256 ISimdVector, T>.Min(Vector256 left, Vector256 right) => Vector256.Min(left, right); /// - static Vector256 ISimdVector, T>.Multiply(Vector256 left, Vector256 right) => Vector256.Multiply(left, right); + static Vector256 ISimdVector, T>.Multiply(Vector256 left, Vector256 right) => left * right; /// - static Vector256 ISimdVector, T>.Multiply(Vector256 left, T right) => Vector256.Multiply(left, right); + static Vector256 ISimdVector, T>.Multiply(Vector256 left, T right) => left * right; /// - static Vector256 ISimdVector, T>.Negate(Vector256 vector) => Vector256.Negate(vector); + static Vector256 ISimdVector, T>.Negate(Vector256 vector) => -vector; /// - static Vector256 ISimdVector, T>.OnesComplement(Vector256 vector) => Vector256.OnesComplement(vector); + static Vector256 ISimdVector, T>.OnesComplement(Vector256 vector) => ~vector; /// - static Vector256 ISimdVector, T>.ShiftLeft(Vector256 vector, int shiftCount) => Vector256.ShiftLeft(vector, shiftCount); + static Vector256 ISimdVector, T>.ShiftLeft(Vector256 vector, int shiftCount) => vector << shiftCount; /// - static Vector256 ISimdVector, T>.ShiftRightArithmetic(Vector256 vector, int shiftCount) => Vector256.ShiftRightArithmetic(vector, shiftCount); + static Vector256 ISimdVector, T>.ShiftRightArithmetic(Vector256 vector, int shiftCount) => vector >> shiftCount; /// - static Vector256 ISimdVector, T>.ShiftRightLogical(Vector256 vector, int shiftCount) => Vector256.ShiftRightLogical(vector, shiftCount); + static Vector256 ISimdVector, T>.ShiftRightLogical(Vector256 vector, int shiftCount) => vector >>> shiftCount; /// static Vector256 ISimdVector, T>.Sqrt(Vector256 vector) => Vector256.Sqrt(vector); #pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') /// - static void ISimdVector, T>.Store(Vector256 source, T* destination) => Vector256.Store(source, destination); + static void ISimdVector, T>.Store(Vector256 source, T* destination) => source.Store(destination); /// - static void ISimdVector, T>.StoreAligned(Vector256 source, T* destination) => Vector256.StoreAligned(source, destination); + static void ISimdVector, T>.StoreAligned(Vector256 source, T* destination) => source.StoreAligned(destination); /// - static void ISimdVector, T>.StoreAlignedNonTemporal(Vector256 source, T* destination) => Vector256.StoreAlignedNonTemporal(source, destination); + static void ISimdVector, T>.StoreAlignedNonTemporal(Vector256 source, T* destination) => source.StoreAlignedNonTemporal(destination); #pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') /// - static void ISimdVector, T>.StoreUnsafe(Vector256 vector, ref T destination) => Vector256.StoreUnsafe(vector, ref destination); + static void ISimdVector, T>.StoreUnsafe(Vector256 vector, ref T destination) => vector.StoreUnsafe(ref destination); /// - static void ISimdVector, T>.StoreUnsafe(Vector256 vector, ref T destination, nuint elementOffset) => Vector256.StoreUnsafe(vector, ref destination, elementOffset); + static void ISimdVector, T>.StoreUnsafe(Vector256 vector, ref T destination, nuint elementOffset) => vector.StoreUnsafe(ref destination, elementOffset); /// - static Vector256 ISimdVector, T>.Subtract(Vector256 left, Vector256 right) => Vector256.Subtract(left, right); + static Vector256 ISimdVector, T>.Subtract(Vector256 left, Vector256 right) => left - right; /// static T ISimdVector, T>.Sum(Vector256 vector) => Vector256.Sum(vector); /// - static T ISimdVector, T>.ToScalar(Vector256 vector) => Vector256.ToScalar(vector); + static T ISimdVector, T>.ToScalar(Vector256 vector) => vector.ToScalar(); /// - static bool ISimdVector, T>.TryCopyTo(Vector256 vector, Span destination) => Vector256.TryCopyTo(vector, destination); + static bool ISimdVector, T>.TryCopyTo(Vector256 vector, Span destination) => vector.TryCopyTo(destination); /// - static Vector256 ISimdVector, T>.WithElement(Vector256 vector, int index, T value) => Vector256.WithElement(vector, index, value); + static Vector256 ISimdVector, T>.WithElement(Vector256 vector, int index, T value) => vector.WithElement(index, value); /// - static Vector256 ISimdVector, T>.Xor(Vector256 left, Vector256 right) => Vector256.Xor(left, right); + static Vector256 ISimdVector, T>.Xor(Vector256 left, Vector256 right) => left ^ right; // // New Surface Area diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs index 8d44bf2899841..cb0efbf531a55 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs @@ -62,10 +62,21 @@ public static bool IsHardwareAccelerated [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 Abs(Vector512 vector) { - return Create( - Vector256.Abs(vector._lower), - Vector256.Abs(vector._upper) - ); + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong)) + || (typeof(T) == typeof(nuint))) + { + return vector; + } + else + { + return Create( + Vector256.Abs(vector._lower), + Vector256.Abs(vector._upper) + ); + } } /// Adds two vectors to compute their sum. @@ -85,13 +96,7 @@ public static Vector512 Abs(Vector512 vector) /// The type of and () is not supported. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector512 AndNot(Vector512 left, Vector512 right) - { - return Create( - Vector256.AndNot(left._lower, right._lower), - Vector256.AndNot(left._upper, right._upper) - ); - } + public static Vector512 AndNot(Vector512 left, Vector512 right) => left & ~right; /// Reinterprets a as a new . /// The type of the elements in the input vector. @@ -272,10 +277,26 @@ public static Vector AsVector(this Vector512 value) [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Vector512 Ceiling(Vector512 vector) { - return Create( - Vector256.Ceiling(vector._lower), - Vector256.Ceiling(vector._upper) - ); + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint)) + || (typeof(T) == typeof(nuint)) + || (typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong))) + { + return vector; + } + else + { + return Create( + Vector256.Ceiling(vector._lower), + Vector256.Ceiling(vector._upper) + ); + } } /// Computes the ceiling of each element in a vector. @@ -301,13 +322,7 @@ internal static Vector512 Ceiling(Vector512 vector) /// The type of , , and () is not supported. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector512 ConditionalSelect(Vector512 condition, Vector512 left, Vector512 right) - { - return Create( - Vector256.ConditionalSelect(condition._lower, left._lower, right._lower), - Vector256.ConditionalSelect(condition._upper, left._upper, right._upper) - ); - } + public static Vector512 ConditionalSelect(Vector512 condition, Vector512 left, Vector512 right) => (left & condition) | (right & ~condition); /// Converts a to a . /// The vector to convert. @@ -1390,13 +1405,7 @@ public static Vector512 CreateScalarUnsafe(T value) /// The type of and () is not supported. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector512 Divide(Vector512 left, Vector512 right) - { - return Create( - Vector256.Divide(left._lower, right._lower), - Vector256.Divide(left._upper, right._upper) - ); - } + public static Vector512 Divide(Vector512 left, Vector512 right) => left / right; /// Divides a vector by a scalar to compute the per-element quotient. /// The vector that will be divided by . @@ -1414,16 +1423,7 @@ public static Vector512 Divide(Vector512 left, Vector512 right) /// The type of and () is not supported. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T Dot(Vector512 left, Vector512 right) - { - // Doing this as Dot(lower) + Dot(upper) is important for floating-point determinism - // This is because the underlying dpps instruction on x86/x64 will do this equivalently - // and otherwise the software vs accelerated implementations may differ in returned result. - - T result = Vector256.Dot(left._lower, right._lower); - result = Scalar.Add(result, Vector256.Dot(left._upper, right._upper)); - return result; - } + public static T Dot(Vector512 left, Vector512 right) => Sum(left * right); /// Compares two vectors to determine if they are equal on a per-element basis. /// The type of the elements in the vector. @@ -1520,10 +1520,26 @@ public static ulong ExtractMostSignificantBits(this Vector512 vector) [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Vector512 Floor(Vector512 vector) { - return Create( - Vector256.Floor(vector._lower), - Vector256.Floor(vector._upper) - ); + if ((typeof(T) == typeof(byte)) + || (typeof(T) == typeof(short)) + || (typeof(T) == typeof(int)) + || (typeof(T) == typeof(long)) + || (typeof(T) == typeof(nint)) + || (typeof(T) == typeof(nuint)) + || (typeof(T) == typeof(sbyte)) + || (typeof(T) == typeof(ushort)) + || (typeof(T) == typeof(uint)) + || (typeof(T) == typeof(ulong))) + { + return vector; + } + else + { + return Create( + Vector256.Floor(vector._lower), + Vector256.Floor(vector._upper) + ); + } } /// Computes the floor of each element in a vector. @@ -1988,7 +2004,7 @@ public static Vector512 Min(Vector512 left, Vector512 right) /// The product of and . /// The type of and () is not supported. [Intrinsic] - public static Vector512 Multiply(T left, Vector512 right) => left * right; + public static Vector512 Multiply(T left, Vector512 right) => right * left; /// [Intrinsic] @@ -2127,13 +2143,7 @@ public static Vector512 Narrow(Vector512 lower, Vector512 up /// A vector whose elements are the ones-complement of the corresponding elements in . /// The type of () is not supported. [Intrinsic] - public static Vector512 OnesComplement(Vector512 vector) - { - return Create( - Vector256.OnesComplement(vector._lower), - Vector256.OnesComplement(vector._upper) - ); - } + public static Vector512 OnesComplement(Vector512 vector) => ~vector; /// Shifts each element of a vector left by the specified amount. /// The vector whose elements are to be shifted. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs index 235871dbe6069..86a8acd823660 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs @@ -38,20 +38,22 @@ namespace System.Runtime.Intrinsics public static Vector512 AllBitsSet { [Intrinsic] - get - { - Vector256 vector = Vector256.AllBitsSet; - return Vector512.Create(vector, vector); - } + get => Vector512.Create(Scalar.AllBitsSet); } +#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') /// Gets the number of that are in a . /// The type of the vector () is not supported. public static int Count { [Intrinsic] - get => Vector256.Count * 2; + get + { + ThrowHelper.ThrowForUnsupportedIntrinsicsVector128BaseType(); + return Vector512.Size / sizeof(T); + } } +#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') /// Gets a new with the elements set to their index. /// The type of the vector () is not supported. @@ -101,11 +103,7 @@ public static bool IsSupported public static Vector512 One { [Intrinsic] - get - { - Vector256 vector = Vector256.One; - return Vector512.Create(vector, vector); - } + get => Vector512.Create(Scalar.One); } /// Gets a new with all elements initialized to zero. @@ -339,14 +337,7 @@ public static Vector512 operator >>(Vector512 value, int shiftCount) /// A vector whose elements are the unary negation of the corresponding elements in . /// The type of the vector () is not supported. [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector512 operator -(Vector512 vector) - { - return Vector512.Create( - -vector._lower, - -vector._upper - ); - } + public static Vector512 operator -(Vector512 vector) => Zero - vector; /// Returns a given vector unchanged. /// The vector. @@ -463,16 +454,16 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector512 ISimdVector, T>.Abs(Vector512 vector) => Vector512.Abs(vector); /// - static Vector512 ISimdVector, T>.Add(Vector512 left, Vector512 right) => Vector512.Add(left, right); + static Vector512 ISimdVector, T>.Add(Vector512 left, Vector512 right) => left + right; /// static Vector512 ISimdVector, T>.AndNot(Vector512 left, Vector512 right) => Vector512.AndNot(left, right); /// - static Vector512 ISimdVector, T>.BitwiseAnd(Vector512 left, Vector512 right) => Vector512.BitwiseAnd(left, right); + static Vector512 ISimdVector, T>.BitwiseAnd(Vector512 left, Vector512 right) => left & right; /// - static Vector512 ISimdVector, T>.BitwiseOr(Vector512 left, Vector512 right) => Vector512.BitwiseOr(left, right); + static Vector512 ISimdVector, T>.BitwiseOr(Vector512 left, Vector512 right) => left | right; /// static Vector512 ISimdVector, T>.Ceiling(Vector512 vector) => Vector512.Ceiling(vector); @@ -508,10 +499,10 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector512 ISimdVector, T>.CreateScalarUnsafe(T value) => Vector512.CreateScalarUnsafe(value); /// - static Vector512 ISimdVector, T>.Divide(Vector512 left, Vector512 right) => Vector512.Divide(left, right); + static Vector512 ISimdVector, T>.Divide(Vector512 left, Vector512 right) => left / right; /// - static Vector512 ISimdVector, T>.Divide(Vector512 left, T right) => Vector512.Divide(left, right); + static Vector512 ISimdVector, T>.Divide(Vector512 left, T right) => left / right; /// static T ISimdVector, T>.Dot(Vector512 left, Vector512 right) => Vector512.Dot(left, right); @@ -520,7 +511,7 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector512 ISimdVector, T>.Equals(Vector512 left, Vector512 right) => Vector512.Equals(left, right); /// - static bool ISimdVector, T>.EqualsAll(Vector512 left, Vector512 right) => Vector512.EqualsAll(left, right); + static bool ISimdVector, T>.EqualsAll(Vector512 left, Vector512 right) => left == right; /// static bool ISimdVector, T>.EqualsAny(Vector512 left, Vector512 right) => Vector512.EqualsAny(left, right); @@ -529,7 +520,7 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector512 ISimdVector, T>.Floor(Vector512 vector) => Vector512.Floor(vector); /// - static T ISimdVector, T>.GetElement(Vector512 vector, int index) => Vector512.GetElement(vector, index); + static T ISimdVector, T>.GetElement(Vector512 vector, int index) => vector.GetElement(index); /// static Vector512 ISimdVector, T>.GreaterThan(Vector512 left, Vector512 right) => Vector512.GreaterThan(left, right); @@ -591,63 +582,63 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector512 ISimdVector, T>.Min(Vector512 left, Vector512 right) => Vector512.Min(left, right); /// - static Vector512 ISimdVector, T>.Multiply(Vector512 left, Vector512 right) => Vector512.Multiply(left, right); + static Vector512 ISimdVector, T>.Multiply(Vector512 left, Vector512 right) => left * right; /// - static Vector512 ISimdVector, T>.Multiply(Vector512 left, T right) => Vector512.Multiply(left, right); + static Vector512 ISimdVector, T>.Multiply(Vector512 left, T right) => left * right; /// - static Vector512 ISimdVector, T>.Negate(Vector512 vector) => Vector512.Negate(vector); + static Vector512 ISimdVector, T>.Negate(Vector512 vector) => -vector; /// - static Vector512 ISimdVector, T>.OnesComplement(Vector512 vector) => Vector512.OnesComplement(vector); + static Vector512 ISimdVector, T>.OnesComplement(Vector512 vector) => ~vector; /// - static Vector512 ISimdVector, T>.ShiftLeft(Vector512 vector, int shiftCount) => Vector512.ShiftLeft(vector, shiftCount); + static Vector512 ISimdVector, T>.ShiftLeft(Vector512 vector, int shiftCount) => vector << shiftCount; /// - static Vector512 ISimdVector, T>.ShiftRightArithmetic(Vector512 vector, int shiftCount) => Vector512.ShiftRightArithmetic(vector, shiftCount); + static Vector512 ISimdVector, T>.ShiftRightArithmetic(Vector512 vector, int shiftCount) => vector >> shiftCount; /// - static Vector512 ISimdVector, T>.ShiftRightLogical(Vector512 vector, int shiftCount) => Vector512.ShiftRightLogical(vector, shiftCount); + static Vector512 ISimdVector, T>.ShiftRightLogical(Vector512 vector, int shiftCount) => vector >>> shiftCount; /// static Vector512 ISimdVector, T>.Sqrt(Vector512 vector) => Vector512.Sqrt(vector); #pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') /// - static void ISimdVector, T>.Store(Vector512 source, T* destination) => Vector512.Store(source, destination); + static void ISimdVector, T>.Store(Vector512 source, T* destination) => source.Store(destination); /// - static void ISimdVector, T>.StoreAligned(Vector512 source, T* destination) => Vector512.StoreAligned(source, destination); + static void ISimdVector, T>.StoreAligned(Vector512 source, T* destination) => source.StoreAligned(destination); /// - static void ISimdVector, T>.StoreAlignedNonTemporal(Vector512 source, T* destination) => Vector512.StoreAlignedNonTemporal(source, destination); + static void ISimdVector, T>.StoreAlignedNonTemporal(Vector512 source, T* destination) => source.StoreAlignedNonTemporal(destination); #pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') /// - static void ISimdVector, T>.StoreUnsafe(Vector512 vector, ref T destination) => Vector512.StoreUnsafe(vector, ref destination); + static void ISimdVector, T>.StoreUnsafe(Vector512 vector, ref T destination) => vector.StoreUnsafe(ref destination); /// - static void ISimdVector, T>.StoreUnsafe(Vector512 vector, ref T destination, nuint elementOffset) => Vector512.StoreUnsafe(vector, ref destination, elementOffset); + static void ISimdVector, T>.StoreUnsafe(Vector512 vector, ref T destination, nuint elementOffset) => vector.StoreUnsafe(ref destination, elementOffset); /// - static Vector512 ISimdVector, T>.Subtract(Vector512 left, Vector512 right) => Vector512.Subtract(left, right); + static Vector512 ISimdVector, T>.Subtract(Vector512 left, Vector512 right) => left - right; /// static T ISimdVector, T>.Sum(Vector512 vector) => Vector512.Sum(vector); /// - static T ISimdVector, T>.ToScalar(Vector512 vector) => Vector512.ToScalar(vector); + static T ISimdVector, T>.ToScalar(Vector512 vector) => vector.ToScalar(); /// - static bool ISimdVector, T>.TryCopyTo(Vector512 vector, Span destination) => Vector512.TryCopyTo(vector, destination); + static bool ISimdVector, T>.TryCopyTo(Vector512 vector, Span destination) => vector.TryCopyTo(destination); /// - static Vector512 ISimdVector, T>.WithElement(Vector512 vector, int index, T value) => Vector512.WithElement(vector, index, value); + static Vector512 ISimdVector, T>.WithElement(Vector512 vector, int index, T value) => vector.WithElement(index, value); /// - static Vector512 ISimdVector, T>.Xor(Vector512 left, Vector512 right) => Vector512.Xor(left, right); + static Vector512 ISimdVector, T>.Xor(Vector512 left, Vector512 right) => left ^ right; // // New Surface Area diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs index 743aad0a6503f..cb0355b18ebc9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs @@ -1795,7 +1795,7 @@ public static Vector64 Min(Vector64 left, Vector64 right) /// The product of and . /// The type of and () is not supported. [Intrinsic] - public static Vector64 Multiply(T left, Vector64 right) => left * right; + public static Vector64 Multiply(T left, Vector64 right) => right * left; /// Computes an estimate of ( * ) + . /// The vector to be multiplied with . diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs index 23730bb5b0090..7f34f2ec539f2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs @@ -38,16 +38,7 @@ namespace System.Runtime.Intrinsics public static Vector64 AllBitsSet { [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - ThrowHelper.ThrowForUnsupportedIntrinsicsVector64BaseType(); - - Unsafe.SkipInit(out Vector64 result); - Unsafe.AsRef(in result._00) = ulong.MaxValue; - - return result; - } + get => Vector64.Create(Scalar.AllBitsSet); } #pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') @@ -531,16 +522,16 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector64 ISimdVector, T>.Abs(Vector64 vector) => Vector64.Abs(vector); /// - static Vector64 ISimdVector, T>.Add(Vector64 left, Vector64 right) => Vector64.Add(left, right); + static Vector64 ISimdVector, T>.Add(Vector64 left, Vector64 right) => left + right; /// - static Vector64 ISimdVector, T>.AndNot(Vector64 left, Vector64 right) => Vector64.AndNot(left, right); + static Vector64 ISimdVector, T>.AndNot(Vector64 left, Vector64 right) => left & ~right; /// - static Vector64 ISimdVector, T>.BitwiseAnd(Vector64 left, Vector64 right) => Vector64.BitwiseAnd(left, right); + static Vector64 ISimdVector, T>.BitwiseAnd(Vector64 left, Vector64 right) => left & right; /// - static Vector64 ISimdVector, T>.BitwiseOr(Vector64 left, Vector64 right) => Vector64.BitwiseOr(left, right); + static Vector64 ISimdVector, T>.BitwiseOr(Vector64 left, Vector64 right) => left | right; /// static Vector64 ISimdVector, T>.Ceiling(Vector64 vector) => Vector64.Ceiling(vector); @@ -576,10 +567,10 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector64 ISimdVector, T>.CreateScalarUnsafe(T value) => Vector64.CreateScalarUnsafe(value); /// - static Vector64 ISimdVector, T>.Divide(Vector64 left, Vector64 right) => Vector64.Divide(left, right); + static Vector64 ISimdVector, T>.Divide(Vector64 left, Vector64 right) => left / right; /// - static Vector64 ISimdVector, T>.Divide(Vector64 left, T right) => Vector64.Divide(left, right); + static Vector64 ISimdVector, T>.Divide(Vector64 left, T right) => left / right; /// static T ISimdVector, T>.Dot(Vector64 left, Vector64 right) => Vector64.Dot(left, right); @@ -588,7 +579,7 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector64 ISimdVector, T>.Equals(Vector64 left, Vector64 right) => Vector64.Equals(left, right); /// - static bool ISimdVector, T>.EqualsAll(Vector64 left, Vector64 right) => Vector64.EqualsAll(left, right); + static bool ISimdVector, T>.EqualsAll(Vector64 left, Vector64 right) => left == right; /// static bool ISimdVector, T>.EqualsAny(Vector64 left, Vector64 right) => Vector64.EqualsAny(left, right); @@ -597,7 +588,7 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector64 ISimdVector, T>.Floor(Vector64 vector) => Vector64.Floor(vector); /// - static T ISimdVector, T>.GetElement(Vector64 vector, int index) => Vector64.GetElement(vector, index); + static T ISimdVector, T>.GetElement(Vector64 vector, int index) => vector.GetElement(index); /// static Vector64 ISimdVector, T>.GreaterThan(Vector64 left, Vector64 right) => Vector64.GreaterThan(left, right); @@ -659,63 +650,63 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector64 ISimdVector, T>.Min(Vector64 left, Vector64 right) => Vector64.Min(left, right); /// - static Vector64 ISimdVector, T>.Multiply(Vector64 left, Vector64 right) => Vector64.Multiply(left, right); + static Vector64 ISimdVector, T>.Multiply(Vector64 left, Vector64 right) => left * right; /// - static Vector64 ISimdVector, T>.Multiply(Vector64 left, T right) => Vector64.Multiply(left, right); + static Vector64 ISimdVector, T>.Multiply(Vector64 left, T right) => left * right; /// - static Vector64 ISimdVector, T>.Negate(Vector64 vector) => Vector64.Negate(vector); + static Vector64 ISimdVector, T>.Negate(Vector64 vector) => -vector; /// - static Vector64 ISimdVector, T>.OnesComplement(Vector64 vector) => Vector64.OnesComplement(vector); + static Vector64 ISimdVector, T>.OnesComplement(Vector64 vector) => ~vector; /// - static Vector64 ISimdVector, T>.ShiftLeft(Vector64 vector, int shiftCount) => Vector64.ShiftLeft(vector, shiftCount); + static Vector64 ISimdVector, T>.ShiftLeft(Vector64 vector, int shiftCount) => vector << shiftCount; /// - static Vector64 ISimdVector, T>.ShiftRightArithmetic(Vector64 vector, int shiftCount) => Vector64.ShiftRightArithmetic(vector, shiftCount); + static Vector64 ISimdVector, T>.ShiftRightArithmetic(Vector64 vector, int shiftCount) => vector >> shiftCount; /// - static Vector64 ISimdVector, T>.ShiftRightLogical(Vector64 vector, int shiftCount) => Vector64.ShiftRightLogical(vector, shiftCount); + static Vector64 ISimdVector, T>.ShiftRightLogical(Vector64 vector, int shiftCount) => vector >>> shiftCount; /// static Vector64 ISimdVector, T>.Sqrt(Vector64 vector) => Vector64.Sqrt(vector); #pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') /// - static void ISimdVector, T>.Store(Vector64 source, T* destination) => Vector64.Store(source, destination); + static void ISimdVector, T>.Store(Vector64 source, T* destination) => source.Store(destination); /// - static void ISimdVector, T>.StoreAligned(Vector64 source, T* destination) => Vector64.StoreAligned(source, destination); + static void ISimdVector, T>.StoreAligned(Vector64 source, T* destination) => source.StoreAligned(destination); /// - static void ISimdVector, T>.StoreAlignedNonTemporal(Vector64 source, T* destination) => Vector64.StoreAlignedNonTemporal(source, destination); + static void ISimdVector, T>.StoreAlignedNonTemporal(Vector64 source, T* destination) => source.StoreAlignedNonTemporal(destination); #pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') /// - static void ISimdVector, T>.StoreUnsafe(Vector64 vector, ref T destination) => Vector64.StoreUnsafe(vector, ref destination); + static void ISimdVector, T>.StoreUnsafe(Vector64 vector, ref T destination) => vector.StoreUnsafe(ref destination); /// - static void ISimdVector, T>.StoreUnsafe(Vector64 vector, ref T destination, nuint elementOffset) => Vector64.StoreUnsafe(vector, ref destination, elementOffset); + static void ISimdVector, T>.StoreUnsafe(Vector64 vector, ref T destination, nuint elementOffset) => vector.StoreUnsafe(ref destination, elementOffset); /// - static Vector64 ISimdVector, T>.Subtract(Vector64 left, Vector64 right) => Vector64.Subtract(left, right); + static Vector64 ISimdVector, T>.Subtract(Vector64 left, Vector64 right) => left - right; /// static T ISimdVector, T>.Sum(Vector64 vector) => Vector64.Sum(vector); /// - static T ISimdVector, T>.ToScalar(Vector64 vector) => Vector64.ToScalar(vector); + static T ISimdVector, T>.ToScalar(Vector64 vector) => vector.ToScalar(); /// - static bool ISimdVector, T>.TryCopyTo(Vector64 vector, Span destination) => Vector64.TryCopyTo(vector, destination); + static bool ISimdVector, T>.TryCopyTo(Vector64 vector, Span destination) => vector.TryCopyTo(destination); /// - static Vector64 ISimdVector, T>.WithElement(Vector64 vector, int index, T value) => Vector64.WithElement(vector, index, value); + static Vector64 ISimdVector, T>.WithElement(Vector64 vector, int index, T value) => vector.WithElement(index, value); /// - static Vector64 ISimdVector, T>.Xor(Vector64 left, Vector64 right) => Vector64.Xor(left, right); + static Vector64 ISimdVector, T>.Xor(Vector64 left, Vector64 right) => left ^ right; // // New Surface Area From 0ed78a41dadd78a8925583f57e1b52539c1fe492 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 5 Jun 2024 17:16:34 -0700 Subject: [PATCH 2/5] Ensure gtNewSimdSumNode maintains consistency with the software fallback --- src/coreclr/jit/gentree.cpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 949d611519e4c..ae42013413a16 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -25510,20 +25510,28 @@ GenTree* Compiler::gtNewSimdSumNode(var_types type, GenTree* op1, CorInfoType si { assert(IsBaselineVector512IsaSupportedDebugOnly()); GenTree* op1Dup = fgMakeMultiUse(&op1); - op1 = gtNewSimdGetUpperNode(TYP_SIMD32, op1, simdBaseJitType, simdSize); - op1Dup = gtNewSimdGetLowerNode(TYP_SIMD32, op1Dup, simdBaseJitType, simdSize); - simdSize = simdSize / 2; - op1 = gtNewSimdBinOpNode(GT_ADD, TYP_SIMD32, op1, op1Dup, simdBaseJitType, simdSize); + + op1 = gtNewSimdGetLowerNode(TYP_SIMD32, op1, simdBaseJitType, simdSize); + op1Dup = gtNewSimdGetUpperNode(TYP_SIMD32, op1Dup, simdBaseJitType, simdSize); + + op1 = gtNewSimdSumNode(type, op1, simdBaseJitType, 32); + op1Dup = gtNewSimdSumNode(type, op1Dup, simdBaseJitType, 32); + + return gtNewOperNode(GT_ADD, type, op1, op1Dup); } if (simdSize == 32) { assert(compIsaSupportedDebugOnly(InstructionSet_AVX2)); GenTree* op1Dup = fgMakeMultiUse(&op1); - op1 = gtNewSimdGetUpperNode(TYP_SIMD16, op1, simdBaseJitType, simdSize); - op1Dup = gtNewSimdGetLowerNode(TYP_SIMD16, op1Dup, simdBaseJitType, simdSize); - simdSize = simdSize / 2; - op1 = gtNewSimdBinOpNode(GT_ADD, TYP_SIMD16, op1, op1Dup, simdBaseJitType, simdSize); + + op1 = gtNewSimdGetUpperNode(TYP_SIMD16, op1, simdBaseJitType, simdSize); + op1Dup = gtNewSimdGetLowerNode(TYP_SIMD16, op1Dup, simdBaseJitType, simdSize); + + op1 = gtNewSimdSumNode(type, op1, simdBaseJitType, 16); + op1Dup = gtNewSimdSumNode(type, op1Dup, simdBaseJitType, 16); + + return gtNewOperNode(GT_ADD, type, op1, op1Dup); } assert(simdSize == 16); From 69f352a57534fa253cf7e1c0cddb0cab626d1a09 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 5 Jun 2024 19:33:45 -0700 Subject: [PATCH 3/5] Ensure Vector128.Sum also does pairwise adds for floating-point --- src/coreclr/jit/gentree.cpp | 38 +++++++++++++++---- .../System/Runtime/Intrinsics/Vector128.cs | 13 +++---- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index ae42013413a16..7215a24f56d22 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -25514,10 +25514,20 @@ GenTree* Compiler::gtNewSimdSumNode(var_types type, GenTree* op1, CorInfoType si op1 = gtNewSimdGetLowerNode(TYP_SIMD32, op1, simdBaseJitType, simdSize); op1Dup = gtNewSimdGetUpperNode(TYP_SIMD32, op1Dup, simdBaseJitType, simdSize); - op1 = gtNewSimdSumNode(type, op1, simdBaseJitType, 32); - op1Dup = gtNewSimdSumNode(type, op1Dup, simdBaseJitType, 32); + if (varTypeIsFloating(simdBaseType)) + { + // We need to ensure deterministic results which requires + // consistently adding values together. Since many operations + // end up operating on 128-bit lanes, we break sum the same way. + + op1 = gtNewSimdSumNode(type, op1, simdBaseJitType, 32); + op1Dup = gtNewSimdSumNode(type, op1Dup, simdBaseJitType, 32); - return gtNewOperNode(GT_ADD, type, op1, op1Dup); + return gtNewOperNode(GT_ADD, type, op1, op1Dup); + } + + simdSize = 32; + op1 = gtNewSimdBinOpNode(GT_ADD, TYP_SIMD32, op1, op1Dup, simdBaseJitType, 32); } if (simdSize == 32) @@ -25525,13 +25535,23 @@ GenTree* Compiler::gtNewSimdSumNode(var_types type, GenTree* op1, CorInfoType si assert(compIsaSupportedDebugOnly(InstructionSet_AVX2)); GenTree* op1Dup = fgMakeMultiUse(&op1); - op1 = gtNewSimdGetUpperNode(TYP_SIMD16, op1, simdBaseJitType, simdSize); - op1Dup = gtNewSimdGetLowerNode(TYP_SIMD16, op1Dup, simdBaseJitType, simdSize); + op1 = gtNewSimdGetLowerNode(TYP_SIMD16, op1, simdBaseJitType, simdSize); + op1Dup = gtNewSimdGetUpperNode(TYP_SIMD16, op1Dup, simdBaseJitType, simdSize); + + if (varTypeIsFloating(simdBaseType)) + { + // We need to ensure deterministic results which requires + // consistently adding values together. Since many operations + // end up operating on 128-bit lanes, we break sum the same way. + + op1 = gtNewSimdSumNode(type, op1, simdBaseJitType, 16); + op1Dup = gtNewSimdSumNode(type, op1Dup, simdBaseJitType, 16); - op1 = gtNewSimdSumNode(type, op1, simdBaseJitType, 16); - op1Dup = gtNewSimdSumNode(type, op1Dup, simdBaseJitType, 16); + return gtNewOperNode(GT_ADD, type, op1, op1Dup); + } - return gtNewOperNode(GT_ADD, type, op1, op1Dup); + simdSize = 16; + op1 = gtNewSimdBinOpNode(GT_ADD, TYP_SIMD32, op1, op1Dup, simdBaseJitType, 16); } assert(simdSize == 16); @@ -25542,6 +25562,7 @@ GenTree* Compiler::gtNewSimdSumNode(var_types type, GenTree* op1, CorInfoType si { assert(compIsaSupportedDebugOnly(InstructionSet_SSE2)); GenTree* op1Shuffled = fgMakeMultiUse(&op1); + if (compOpportunisticallyDependsOn(InstructionSet_AVX)) { assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); @@ -25579,6 +25600,7 @@ GenTree* Compiler::gtNewSimdSumNode(var_types type, GenTree* op1, CorInfoType si { assert(compIsaSupportedDebugOnly(InstructionSet_SSE2)); GenTree* op1Shuffled = fgMakeMultiUse(&op1); + if (compOpportunisticallyDependsOn(InstructionSet_AVX)) { assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs index 1cda7d5ccdb21..3114dd1cb9bb3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs @@ -2757,14 +2757,13 @@ public static void StoreUnsafe(this Vector128 source, ref T destination, n [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T Sum(Vector128 vector) { - T sum = default!; + // Doing this as Sum(lower) + Sum(upper) is important for floating-point determinism + // This is because the underlying dpps instruction on x86/x64 will do this equivalently + // and otherwise the software vs accelerated implementations may differ in returned result. - for (int index = 0; index < Vector128.Count; index++) - { - sum = Scalar.Add(sum, vector.GetElementUnsafe(index)); - } - - return sum; + T result = Vector64.Sum(vector._lower); + result = Scalar.Add(result, Vector64.Sum(vector._upper)); + return result; } /// Converts the given vector to a scalar containing the value of the first element. From 41759057ab36b5890db3bb1fcc277cf31de9e14c Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 5 Jun 2024 20:59:48 -0700 Subject: [PATCH 4/5] Use the right type in the gtNewSimdBinOpNode call --- src/coreclr/jit/gentree.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 7215a24f56d22..000def1e8f1eb 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -25551,7 +25551,7 @@ GenTree* Compiler::gtNewSimdSumNode(var_types type, GenTree* op1, CorInfoType si } simdSize = 16; - op1 = gtNewSimdBinOpNode(GT_ADD, TYP_SIMD32, op1, op1Dup, simdBaseJitType, 16); + op1 = gtNewSimdBinOpNode(GT_ADD, TYP_SIMD16, op1, op1Dup, simdBaseJitType, 16); } assert(simdSize == 16); From c465d2d6c548c19d0f2ea1f2e78956a11f8f064e Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Thu, 6 Jun 2024 10:19:10 -0700 Subject: [PATCH 5/5] Don't regress fallback scenarios using AndNot --- .../System.Private.CoreLib/src/System/Numerics/Vector.cs | 2 +- .../src/System/Runtime/Intrinsics/Vector128.cs | 2 +- .../src/System/Runtime/Intrinsics/Vector256.cs | 2 +- .../src/System/Runtime/Intrinsics/Vector512.cs | 2 +- .../src/System/Runtime/Intrinsics/Vector64.cs | 2 +- .../src/System/Runtime/Intrinsics/Vector64_1.cs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs index 9af865a30fea4..31ff260d270c9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs @@ -253,7 +253,7 @@ public static Vector Ceiling(Vector value) /// A vector whose bits come from or based on the value of . [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector ConditionalSelect(Vector condition, Vector left, Vector right) => (left & condition) | (right & ~condition); + public static Vector ConditionalSelect(Vector condition, Vector left, Vector right) => (left & condition) | AndNot(right, condition); /// Conditionally selects a value from two vectors on a bitwise basis. /// The mask that is used to select a value from or . diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs index 3114dd1cb9bb3..ea2446090399d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs @@ -427,7 +427,7 @@ internal static Vector128 Ceiling(Vector128 vector) /// The type of , , and () is not supported. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 ConditionalSelect(Vector128 condition, Vector128 left, Vector128 right) => (left & condition) | (right & ~condition); + public static Vector128 ConditionalSelect(Vector128 condition, Vector128 left, Vector128 right) => (left & condition) | AndNot(right, condition); /// Converts a to a . /// The vector to convert. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs index 69b116885282c..4779812149be0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs @@ -322,7 +322,7 @@ internal static Vector256 Ceiling(Vector256 vector) /// The type of , , and () is not supported. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector256 ConditionalSelect(Vector256 condition, Vector256 left, Vector256 right) => (left & condition) | (right & ~condition); + public static Vector256 ConditionalSelect(Vector256 condition, Vector256 left, Vector256 right) => (left & condition) | AndNot(right, condition); /// Converts a to a . /// The vector to convert. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs index cb0efbf531a55..4e534e8ac3947 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs @@ -322,7 +322,7 @@ internal static Vector512 Ceiling(Vector512 vector) /// The type of , , and () is not supported. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector512 ConditionalSelect(Vector512 condition, Vector512 left, Vector512 right) => (left & condition) | (right & ~condition); + public static Vector512 ConditionalSelect(Vector512 condition, Vector512 left, Vector512 right) => (left & condition) | AndNot(right, condition); /// Converts a to a . /// The vector to convert. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs index cb0355b18ebc9..f9b90a2f877ce 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs @@ -272,7 +272,7 @@ internal static Vector64 Ceiling(Vector64 vector) /// The type of , , and () is not supported. [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector64 ConditionalSelect(Vector64 condition, Vector64 left, Vector64 right) => (left & condition) | (right & ~condition); + public static Vector64 ConditionalSelect(Vector64 condition, Vector64 left, Vector64 right) => (left & condition) | AndNot(right, condition); /// Converts a to a . /// The vector to convert. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs index 7f34f2ec539f2..cca51261cf659 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs @@ -525,7 +525,7 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector64 ISimdVector, T>.Add(Vector64 left, Vector64 right) => left + right; /// - static Vector64 ISimdVector, T>.AndNot(Vector64 left, Vector64 right) => left & ~right; + static Vector64 ISimdVector, T>.AndNot(Vector64 left, Vector64 right) => Vector64.AndNot(left, right); /// static Vector64 ISimdVector, T>.BitwiseAnd(Vector64 left, Vector64 right) => left & right;