diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
index e4f97a37356299..09db5ad47cc55b 100644
--- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
+++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
@@ -920,7 +920,9 @@
+
+
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs
new file mode 100644
index 00000000000000..8c12e1e935dd4e
--- /dev/null
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs
@@ -0,0 +1,450 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace System.Runtime.Intrinsics
+{
+ /// Defines a single instruction, multiple data (SIMD) vector type.
+ /// The type that implements the interface.
+ /// The type of the elements in the vector.
+ internal interface ISimdVector
+ : IAdditionOperators,
+ // IAdditiveIdentity,
+ IBitwiseOperators,
+ // IComparisonOperators,
+ // IDecrementOperators,
+ IDivisionOperators,
+ IEqualityOperators,
+ IEquatable,
+ // IIncrementOperators,
+ // IMinMaxValue,
+ // IModulusOperators,
+ // IMultiplicativeIdentity,
+ IMultiplyOperators,
+ // IShiftOperators
+ // ISpanFormattable,
+ ISubtractionOperators,
+ IUnaryNegationOperators,
+ IUnaryPlusOperators
+ where TSelf : unmanaged, ISimdVector
+ where T : struct
+ {
+ /// Gets an instance of the vector type in which all bits are set.
+ /// The type of the elements in the vector () is not supported.
+ static abstract TSelf AllBitsSet { get; }
+
+ /// Gets the number of that are in the vector.
+ /// The type of the elements in the vector () is not supported.
+ static abstract int Count { get; }
+
+ /// Gets a value that indicates whether the vector operations are subject to hardware acceleration through JIT intrinsic support.
+ /// if the vector operations are subject to hardware acceleration; otherwise, .
+ static abstract bool IsHardwareAccelerated { get; }
+
+ /// Gets if is supported; otherwise, .
+ /// if is supported; otherwise, .
+ static abstract bool IsSupported { get; }
+
+ /// Gets an instance of the vector type in which each element is the value zero.
+ /// The type of the elements in the vector () is not supported.
+ static abstract TSelf Zero { get; }
+
+ /// Gets the element at the specified index.
+ /// The index of the element to get.
+ /// The value of the element at .
+ /// was less than zero or greater than the number of elements.
+ /// The type of the elements in the vector () is not supported.
+ T this[int index] { get; }
+
+ /// Computes the absolute of a vector.
+ /// The vector for which to get its absolute.
+ /// A absolute of .
+ /// The type of the elements in the vector () is not supported.
+ static abstract TSelf Abs(TSelf vector);
+
+ /// Conditionally selects bits from two vectors based on a given condition.
+ /// The mask that is used to select a value from or .
+ /// The vector that is selected when the corresponding bit in is one.
+ /// The vector that is selected when the corresponding bit in is zero.
+ /// A vector whose bits come from or based on the value of .
+ /// The type of the elements in the vector () is not supported.
+ static abstract TSelf ConditionalSelect(TSelf condition, TSelf left, TSelf right);
+
+ /// Copies a vector to a given array.
+ /// The vector to be copied.
+ /// The array to which is copied.
+ /// The length of is less than .
+ /// The type of the elements in the vector () is not supported.
+ /// is null.
+ static virtual void CopyTo(TSelf vector, T[] destination)
+ {
+ if (!TSelf.IsSupported)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.Arg_TypeNotSupported);
+ }
+
+ // We explicitly don't check for `null` because historically this has thrown `NullReferenceException` for perf reasons
+
+ if (destination.Length < TSelf.Count)
+ {
+ ThrowHelper.ThrowArgumentException_DestinationTooShort();
+ }
+
+ ref byte address = ref Unsafe.As(ref MemoryMarshal.GetArrayDataReference(destination));
+ Unsafe.WriteUnaligned(ref address, vector);
+ }
+
+ /// Copies a vector to a given array starting at the specified index.
+ /// The vector to be copied.
+ /// The array to which is copied.
+ /// The starting index of which will be copied to.
+ /// The length of is less than .
+ /// is negative or greater than the length of .
+ /// The type of the elements in the vector () is not supported.
+ /// is null.
+ static virtual void CopyTo(TSelf vector, T[] destination, int startIndex)
+ {
+ if (!TSelf.IsSupported)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.Arg_TypeNotSupported);
+ }
+
+ // We explicitly don't check for `null` because historically this has thrown `NullReferenceException` for perf reasons
+
+ if ((uint)(startIndex) >= (uint)(destination.Length))
+ {
+ ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLess();
+ }
+
+ if ((destination.Length - startIndex) < TSelf.Count)
+ {
+ ThrowHelper.ThrowArgumentException_DestinationTooShort();
+ }
+
+ ref byte address = ref Unsafe.As(ref MemoryMarshal.GetArrayDataReference(destination));
+ Unsafe.WriteUnaligned(ref Unsafe.Add(ref address, startIndex), vector);
+ }
+
+ /// Copies a vector to a given span.
+ /// The vector to be copied.
+ /// The span to which the is copied.
+ /// The length of is less than .
+ /// The type of the elements in the vector () is not supported.
+ static virtual void CopyTo(TSelf vector, Span destination)
+ {
+ if (!TSelf.IsSupported)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.Arg_TypeNotSupported);
+ }
+
+ if ((uint)(destination.Length) < (uint)(TSelf.Count))
+ {
+ ThrowHelper.ThrowArgumentException_DestinationTooShort();
+ }
+
+ ref byte address = ref Unsafe.As(ref MemoryMarshal.GetReference(destination));
+ Unsafe.WriteUnaligned(ref address, vector);
+ }
+
+ /// Creates a new vector with all elements initialized to the specified value.
+ /// The value that all elements will be initialized to.
+ /// A new vector with all elements initialized to .
+ /// The type of the elements in the vector () is not supported.
+ static abstract TSelf Create(T value);
+
+ /// Creates a new vector from a given array.
+ /// The array from which the vector is created.
+ /// A new vector with its elements set to the first elements from .
+ /// The length of is less than .
+ /// The type of the elements in the vector () is not supported.
+ /// is null.
+ static virtual TSelf Create(T[] values)
+ {
+ if (!TSelf.IsSupported)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.Arg_TypeNotSupported);
+ }
+
+ // We explicitly don't check for `null` because historically this has thrown `NullReferenceException` for perf reasons
+
+ if (values.Length < TSelf.Count)
+ {
+ ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessOrEqualException();
+ }
+
+ ref byte address = ref Unsafe.As(ref MemoryMarshal.GetArrayDataReference(values));
+ return Unsafe.ReadUnaligned(ref address);
+ }
+
+ /// Creates a new vector from a given array.
+ /// The array from which the vector is created.
+ /// The index in at which to being reading elements.
+ /// A new vector with its elements set to the first elements from .
+ /// The length of , starting from , is less than .
+ /// The type of the elements in the vector () is not supported.
+ /// is null.
+ static virtual TSelf Create(T[] values, int index)
+ {
+ if (!TSelf.IsSupported)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.Arg_TypeNotSupported);
+ }
+
+ // We explicitly don't check for `null` because historically this has thrown `NullReferenceException` for perf reasons
+
+ if ((index < 0) || ((values.Length - index) < TSelf.Count))
+ {
+ ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessOrEqualException();
+ }
+
+ ref byte address = ref Unsafe.As(ref MemoryMarshal.GetArrayDataReference(values));
+ return Unsafe.ReadUnaligned(ref Unsafe.Add(ref address, index));
+ }
+
+ /// Creates a new vector from a given readonly span.
+ /// The readonly span from which the vector is created.
+ /// A new vector with its elements set to the first elements from .
+ /// The length of is less than .
+ /// The type of the elements in the vector () is not supported.
+ static virtual TSelf Create(ReadOnlySpan values)
+ {
+ if (!TSelf.IsSupported)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.Arg_TypeNotSupported);
+ }
+
+ if (values.Length < TSelf.Count)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.values);
+ }
+
+ ref byte address = ref Unsafe.As(ref MemoryMarshal.GetReference(values));
+ return Unsafe.ReadUnaligned(ref address);
+ }
+
+ /// Creates a new vector with the first element initialized to the specified value and the remaining elements initialized to zero.
+ /// The value that element 0 will be initialized to.
+ /// A new vector with the first element initialized to and the remaining elements initialized to zero.
+ /// The type of the elements in the vector () is not supported.
+ static abstract TSelf CreateScalar(T value);
+
+ /// Creates a new vector with the first element initialized to the specified value and the remaining elements left uninitialized.
+ /// The value that element 0 will be initialized to.
+ /// A new vector with the first element initialized to and the remaining elements left uninitialized.
+ /// The type of the elements in the vector () is not supported.
+ static abstract TSelf CreateScalarUnsafe(T value);
+
+ /// Compares two vectors to determine if they are equal on a per-element basis.
+ /// The vector to compare with .
+ /// The vector to compare with .
+ /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in and were equal.
+ /// The type of the elements in the vector () is not supported.
+ static abstract TSelf Equals(TSelf left, TSelf right);
+
+ /// Compares two vectors to determine if all elements are equal.
+ /// The vector to compare with .
+ /// The vector to compare with .
+ /// true if all elements in were equal to the corresponding element in .
+ /// The type of the elements in the vector () is not supported.
+ static abstract bool EqualsAll(TSelf left, TSelf right);
+
+ /// Compares two vectors to determine if any elements are equal.
+ /// The vector to compare with .
+ /// The vector to compare with .
+ /// true if any elements in was equal to the corresponding element in .
+ /// The type of the elements in the vector () is not supported.
+ static abstract bool EqualsAny(TSelf left, TSelf right);
+
+ /// Gets the element at the specified index.
+ /// The vector to get the element from.
+ /// The index of the element to get.
+ /// The value of the element at .
+ /// was less than zero or greater than the number of elements.
+ /// The type of the elements in the vector () is not supported.
+ static abstract T GetElement(TSelf vector, int index);
+
+ /// Compares two vectors to determine which is greater on a per-element basis.
+ /// The vector to compare with .
+ /// The vector to compare with .
+ /// A vector whose elements are all-bits-set or zero, depending on if which of the corresponding elements in and were greater.
+ /// The type of the elements in the vector () is not supported.
+ static abstract TSelf GreaterThan(TSelf left, TSelf right);
+
+ /// Compares two vectors to determine if all elements are greater.
+ /// The vector to compare with .
+ /// The vector to compare with .
+ /// true if all elements in were greater than the corresponding element in .
+ /// The type of the elements in the vector () is not supported.
+ static abstract bool GreaterThanAll(TSelf left, TSelf right);
+
+ /// Compares two vectors to determine if any elements are greater.
+ /// The vector to compare with .
+ /// The vector to compare with .
+ /// true if any elements in was greater than the corresponding element in .
+ /// The type of the elements in the vector () is not supported.
+ static abstract bool GreaterThanAny(TSelf left, TSelf right);
+
+ /// Compares two vectors to determine which is greater or equal on a per-element basis.
+ /// The vector to compare with .
+ /// The vector to compare with .
+ /// A vector whose elements are all-bits-set or zero, depending on if which of the corresponding elements in and were greater or equal.
+ /// The type of the elements in the vector () is not supported.
+ static abstract TSelf GreaterThanOrEqual(TSelf left, TSelf right);
+
+ /// Compares two vectors to determine if all elements are greater or equal.
+ /// The vector to compare with .
+ /// The vector to compare with .
+ /// true if all elements in were greater than or equal to the corresponding element in .
+ /// The type of the elements in the vector () is not supported.
+ static abstract bool GreaterThanOrEqualAll(TSelf left, TSelf right);
+
+ /// Compares two vectors to determine if any elements are greater or equal.
+ /// The vector to compare with .
+ /// The vector to compare with .
+ /// true if any elements in was greater than or equal to the corresponding element in .
+ /// The type of the elements in the vector () is not supported.
+ static abstract bool GreaterThanOrEqualAny(TSelf left, TSelf right);
+
+ /// Compares two vectors to determine which is less on a per-element basis.
+ /// The vector to compare with .
+ /// The vector to compare with .
+ /// A vector whose elements are all-bits-set or zero, depending on if which of the corresponding elements in and were less.
+ /// The type of the elements in the vector () is not supported.
+ static abstract TSelf LessThan(TSelf left, TSelf right);
+
+ /// Compares two vectors to determine if all elements are less.
+ /// The vector to compare with .
+ /// The vector to compare with .
+ /// true if all elements in were less than the corresponding element in .
+ /// The type of the elements in the vector () is not supported.
+ static abstract bool LessThanAll(TSelf left, TSelf right);
+
+ /// Compares two vectors to determine if any elements are less.
+ /// The vector to compare with .
+ /// The vector to compare with .
+ /// true if any elements in was less than the corresponding element in .
+ /// The type of the elements in the vector () is not supported.
+ static abstract bool LessThanAny(TSelf left, TSelf right);
+
+ /// Compares two vectors to determine which is less or equal on a per-element basis.
+ /// The vector to compare with .
+ /// The vector to compare with .
+ /// A vector whose elements are all-bits-set or zero, depending on if which of the corresponding elements in and were less or equal.
+ /// The type of the elements in the vector () is not supported.
+ static abstract TSelf LessThanOrEqual(TSelf left, TSelf right);
+
+ /// Compares two vectors to determine if all elements are less or equal.
+ /// The vector to compare with .
+ /// The vector to compare with .
+ /// true if all elements in were less than or equal to the corresponding element in .
+ /// The type of the elements in the vector () is not supported.
+ static abstract bool LessThanOrEqualAll(TSelf left, TSelf right);
+
+ /// Compares two vectors to determine if any elements are less or equal.
+ /// The vector to compare with .
+ /// The vector to compare with .
+ /// true if any elements in was less than or equal to the corresponding element in .
+ /// The type of the elements in the vector () is not supported.
+ static abstract bool LessThanOrEqualAny(TSelf left, TSelf right);
+
+ /// Loads a vector from the given source.
+ /// The source from which the vector will be loaded.
+ /// The vector loaded from .
+ /// The type of the elements in the vector () is not supported.
+ static abstract TSelf LoadUnsafe(ref T source);
+
+ /// Loads a vector from the given source and element offset.
+ /// The source to which will be added before loading the vector.
+ /// The element offset from from which the vector will be loaded.
+ /// The vector loaded from plus .
+ /// The type of the elements in the vector () is not supported.
+ static abstract TSelf LoadUnsafe(ref T source, nuint elementOffset);
+
+ /// Computes the maximum of two vectors on a per-element basis.
+ /// The vector to compare with .
+ /// The vector to compare with .
+ /// A vector whose elements are the maximum of the corresponding elements in and .
+ /// The type of the elements in the vector () is not supported.
+ static abstract TSelf Max(TSelf left, TSelf right);
+
+ /// Computes the minimum of two vectors on a per-element basis.
+ /// The vector to compare with .
+ /// The vector to compare with .
+ /// A vector whose elements are the minimum of the corresponding elements in and .
+ /// The type of the elements in the vector () is not supported.
+ static abstract TSelf Min(TSelf left, TSelf right);
+
+ /// Stores a vector at the given destination.
+ /// The vector that will be stored.
+ /// The destination at which will be stored.
+ /// The type of the elements in the vector () is not supported.
+ static abstract void StoreUnsafe(TSelf vector, ref T destination);
+
+ /// Stores a vector at the given destination.
+ /// The vector that will be stored.
+ /// The destination to which will be added before the vector will be stored.
+ /// The element offset from from which the vector will be stored.
+ /// The type of the elements in the vector () is not supported.
+ static abstract void StoreUnsafe(TSelf vector, ref T destination, nuint elementOffset);
+
+ /// Converts the given vector to a scalar containing the value of the first element.
+ /// The vector to get the first element from.
+ /// A scalar containing the value of the first element.
+ /// The type of the elements in the vector () is not supported.
+ static abstract T ToScalar(TSelf vector);
+
+ /// Tries to copy a to a given span.
+ /// The vector to copy.
+ /// The span to which is copied.
+ /// true if was successfully copied to ; otherwise, false if the length of is less than .
+ /// The type of the elements in the vector () is not supported.
+ static virtual bool TryCopyTo(TSelf vector, Span destination)
+ {
+ if (!TSelf.IsSupported)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.Arg_TypeNotSupported);
+ }
+
+ if ((uint)(destination.Length) < (uint)(TSelf.Count))
+ {
+ return false;
+ }
+
+ ref byte address = ref Unsafe.As(ref MemoryMarshal.GetReference(destination));
+ Unsafe.WriteUnaligned(ref address, vector);
+
+ return true;
+ }
+
+ /// Creates a new with the element at the specified index set to the specified value and the remaining elements set to the same value as that in the given vector.
+ /// The vector to get the remaining elements from.
+ /// The index of the element to set.
+ /// The value to set the element to.
+ /// A with the value of the element at set to and the remaining elements set to the same value as that in .
+ /// was less than zero or greater than the number of elements.
+ /// The type of the elements in the vector () is not supported.
+ static abstract TSelf WithElement(TSelf vector, int index, T value);
+
+ // TODO: static abstract operator *(TSelf left, T right);
+ // TODO: As()
+ // TODO: Ceiling()
+ // TODO: Dot
+ // TODO: ExtractMostSignificantBits
+ // TODO: Floor
+ // TODO: Load
+ // TODO: LoadAligned
+ // TODO: LoadAlignedNonTemporal
+ // TODO: ShiftLeft
+ // TODO: ShiftRightArithmetic
+ // TODO: ShiftRightLogical
+ // TODO: Shuffle
+ // TODO: Sqrt
+ // TODO: Store
+ // TODO: StoreAligned
+ // TODO: StoreAlignedNonTemporal
+ // TODO: Sum
+ }
+}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/SimdVectorExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/SimdVectorExtensions.cs
new file mode 100644
index 00000000000000..5bc7a6646945c6
--- /dev/null
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/SimdVectorExtensions.cs
@@ -0,0 +1,122 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Runtime.Intrinsics
+{
+ internal static class SimdVectorExtensions
+ {
+ /// Copies a vector to a given array.
+ /// The type of the vector.
+ /// The type of the elements in the vector.
+ /// The vector to be copied.
+ /// The array to which is copied.
+ /// The length of is less than .
+ /// is null.
+ /// The type of the elements in the vector () is not supported.
+ public static void CopyTo(this TVector vector, T[] destination)
+ where TVector : unmanaged, ISimdVector
+ where T : struct
+ {
+ TVector.CopyTo(vector, destination);
+ }
+
+ /// Copies a vector to a given array starting at the specified index.
+ /// The type of the vector.
+ /// The type of the elements in the vector.
+ /// The vector to be copied.
+ /// The array to which is copied.
+ /// The starting index of which will be copied to.
+ /// The length of is less than .
+ /// is negative or greater than the length of .
+ /// is null.
+ /// The type of the elements in the vector () is not supported.
+ public static void CopyTo(this TVector vector, T[] destination, int startIndex)
+ where TVector : unmanaged, ISimdVector
+ where T : struct
+ {
+ TVector.CopyTo(vector, destination, startIndex);
+ }
+
+ /// Copies a vector to a given span.
+ /// The type of the vector.
+ /// The type of the elements in the vector.
+ /// The vector to be copied.
+ /// The span to which the is copied.
+ /// The length of is less than .
+ /// The type of the elements in the vector () is not supported.
+ public static void CopyTo(this TVector vector, Span destination)
+ where TVector : unmanaged, ISimdVector
+ where T : struct
+ {
+ TVector.CopyTo(vector, destination);
+ }
+
+ /// Stores a vector at the given destination.
+ /// The type of the vector.
+ /// The type of the elements in the vector.
+ /// The vector that will be stored.
+ /// The destination at which the vector will be stored.
+ /// The type of the elements in the vector () is not supported.
+ public static void StoreUnsafe(this TVector vector, ref T destination)
+ where TVector : unmanaged, ISimdVector
+ where T : struct
+ {
+ TVector.StoreUnsafe(vector, ref destination);
+ }
+
+ /// Stores a vector at the given destination.
+ /// The type of the vector.
+ /// The type of the elements in the vector.
+ /// The vector that will be stored.
+ /// The destination to which will be added before the vector will be stored.
+ /// The element offset from from which the vector will be stored.
+ /// The type of the elements in the vector () is not supported.
+ public static void StoreUnsafe(this TVector vector, ref T destination, nuint elementOffset)
+ where TVector : unmanaged, ISimdVector
+ where T : struct
+ {
+ TVector.StoreUnsafe(vector, ref destination, elementOffset);
+ }
+
+ /// Converts the given vector to a scalar containing the value of the first element.
+ /// The type of the vector.
+ /// The type of the elements in the vector.
+ /// The vector to get the first element from.
+ /// A scalar containing the value of the first element.
+ /// The type of the elements in the vector () is not supported.
+ public static T ToScalar(this TVector vector)
+ where TVector : unmanaged, ISimdVector
+ where T : struct
+ {
+ return TVector.ToScalar(vector);
+ }
+
+ /// Tries to copy a vector to a given span.
+ /// The type of the vector.
+ /// The type of the elements in the vector.
+ /// The vector to copy.
+ /// The span to which is copied.
+ /// true if was successfully copied to ; otherwise, false if the length of is less than .
+ /// The type of the elements in the vector () is not supported.
+ public static bool TryCopyTo(this TVector vector, Span destination)
+ where TVector : unmanaged, ISimdVector
+ where T : struct
+ {
+ return TVector.TryCopyTo(vector, destination);
+ }
+
+ /// Creates a new with the element at the specified index set to the specified value and the remaining elements set to the same value as that in the given vector.
+ /// The vector to get the remaining elements from.
+ /// The index of the element to set.
+ /// The value to set the element to.
+ /// A with the value of the element at set to and the remaining elements set to the same value as that in .
+ /// was less than zero or greater than the number of elements.
+ /// The type of the elements in the vector () is not supported.
+ public static TVector WithElement(this TVector vector, int index, T value)
+ where TVector : unmanaged, ISimdVector
+ where T : struct
+ {
+ return TVector.WithElement(vector, index, value);
+ }
+ }
+}
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 658c48aa04511c..47fb4a8ae42058 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
@@ -72,6 +72,10 @@ public static Vector128 Abs(Vector128 vector)
{
return vector;
}
+ else if (typeof(T) == typeof(nuint))
+ {
+ return vector;
+ }
else
{
return SoftwareFallback(vector);
@@ -709,6 +713,10 @@ public static unsafe Vector128 Create(T value)
{
return Create((long)(object)value).As();
}
+ else if (typeof(T) == typeof(nint))
+ {
+ return Create((nint)(object)value).As();
+ }
else if (typeof(T) == typeof(sbyte))
{
return Create((sbyte)(object)value).As();
@@ -729,6 +737,10 @@ public static unsafe Vector128 Create(T value)
{
return Create((ulong)(object)value).As();
}
+ else if (typeof(T) == typeof(nuint))
+ {
+ return Create((nuint)(object)value).As();
+ }
else
{
throw new NotSupportedException(SR.Arg_TypeNotSupported);
@@ -1538,6 +1550,20 @@ static Vector128 SoftwareFallback(Vector64 lower, Vector64
}
}
+ /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero.
+ /// The type of the elements in the vector.
+ /// The value that element 0 will be initialized to.
+ /// A new instance with the first element initialized to and the remaining elements initialized to zero.
+ /// The type of the elements in the vector () is not supported.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static unsafe Vector128 CreateScalar(T value)
+ where T : struct
+ {
+ Vector128 result = Vector128.Zero;
+ result.SetElementUnsafe(0, value);
+ return result;
+ }
+
/// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero.
/// The value that element 0 will be initialized to.
/// A new instance with the first element initialized to and the remaining elements initialized to zero.
@@ -1556,14 +1582,7 @@ public static unsafe Vector128 CreateScalar(byte value)
return Sse2.ConvertScalarToVector128UInt32(value).AsByte();
}
- return SoftwareFallback(value);
-
- static Vector128 SoftwareFallback(byte value)
- {
- Vector128 result = Vector128.Zero;
- Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value);
- return result;
- }
+ return CreateScalar(value);
}
/// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero.
@@ -1582,14 +1601,7 @@ public static unsafe Vector128 CreateScalar(double value)
return Sse2.MoveScalar(Vector128.Zero, CreateScalarUnsafe(value));
}
- return SoftwareFallback(value);
-
- static Vector128 SoftwareFallback(double value)
- {
- Vector128 result = Vector128.Zero;
- Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value);
- return result;
- }
+ return CreateScalar(value);
}
/// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero.
@@ -1610,14 +1622,7 @@ public static unsafe Vector128 CreateScalar(short value)
return Sse2.ConvertScalarToVector128UInt32((ushort)(value)).AsInt16();
}
- return SoftwareFallback(value);
-
- static Vector128 SoftwareFallback(short value)
- {
- Vector128 result = Vector128.Zero;
- Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value);
- return result;
- }
+ return CreateScalar(value);
}
/// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero.
@@ -1636,14 +1641,7 @@ public static unsafe Vector128 CreateScalar(int value)
return Sse2.ConvertScalarToVector128Int32(value);
}
- return SoftwareFallback(value);
-
- static Vector128 SoftwareFallback(int value)
- {
- Vector128 result = Vector128.Zero;
- Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value);
- return result;
- }
+ return CreateScalar(value);
}
/// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero.
@@ -1662,14 +1660,7 @@ public static unsafe Vector128 CreateScalar(long value)
return Sse2.X64.ConvertScalarToVector128Int64(value);
}
- return SoftwareFallback(value);
-
- static Vector128 SoftwareFallback(long value)
- {
- Vector128 result = Vector128.Zero;
- Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value);
- return result;
- }
+ return CreateScalar(value);
}
/// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero.
@@ -1679,9 +1670,9 @@ static Vector128 SoftwareFallback(long value)
public static unsafe Vector128 CreateScalar(nint value)
{
#if TARGET_64BIT
- return CreateScalar((long)value).AsNInt();
+ return CreateScalar((long)(value)).AsNInt();
#else
- return CreateScalar((int)value).AsNInt();
+ return CreateScalar((int)(value)).AsNInt();
#endif
}
@@ -1693,9 +1684,9 @@ public static unsafe Vector128 CreateScalar(nint value)
public static unsafe Vector128 CreateScalar(nuint value)
{
#if TARGET_64BIT
- return CreateScalar((ulong)value).AsNUInt();
+ return CreateScalar((ulong)(value)).AsNUInt();
#else
- return CreateScalar((uint)value).AsNUInt();
+ return CreateScalar((uint)(value)).AsNUInt();
#endif
}
@@ -1718,14 +1709,7 @@ public static unsafe Vector128 CreateScalar(sbyte value)
return Sse2.ConvertScalarToVector128UInt32((byte)(value)).AsSByte();
}
- return SoftwareFallback(value);
-
- static Vector128 SoftwareFallback(sbyte value)
- {
- Vector128 result = Vector128.Zero;
- Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value);
- return result;
- }
+ return CreateScalar(value);
}
/// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero.
@@ -1744,14 +1728,7 @@ public static unsafe Vector128 CreateScalar(float value)
return Sse.MoveScalar(Vector128.Zero, CreateScalarUnsafe(value));
}
- return SoftwareFallback(value);
-
- static Vector128 SoftwareFallback(float value)
- {
- Vector128 result = Vector128.Zero;
- Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value);
- return result;
- }
+ return CreateScalar(value);
}
/// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero.
@@ -1773,14 +1750,7 @@ public static unsafe Vector128 CreateScalar(ushort value)
return Sse2.ConvertScalarToVector128UInt32(value).AsUInt16();
}
- return SoftwareFallback(value);
-
- static Vector128 SoftwareFallback(ushort value)
- {
- Vector128 result = Vector128.Zero;
- Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value);
- return result;
- }
+ return CreateScalar(value);
}
/// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero.
@@ -1800,14 +1770,7 @@ public static unsafe Vector128 CreateScalar(uint value)
return Sse2.ConvertScalarToVector128UInt32(value);
}
- return SoftwareFallback(value);
-
- static Vector128 SoftwareFallback(uint value)
- {
- Vector128 result = Vector128.Zero;
- Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value);
- return result;
- }
+ return CreateScalar(value);
}
/// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero.
@@ -1827,186 +1790,104 @@ public static unsafe Vector128 CreateScalar(ulong value)
return Sse2.X64.ConvertScalarToVector128UInt64(value);
}
- return SoftwareFallback(value);
-
- static Vector128 SoftwareFallback(ulong value)
- {
- Vector128 result = Vector128.Zero;
- Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value);
- return result;
- }
+ return CreateScalar(value);
}
- /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized.
+ /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized.
+ /// The type of the elements in the vector.
/// The value that element 0 will be initialized to.
- /// A new instance with the first element initialized to and the remaining elements left uninitialized.
+ /// A new instance with the first element initialized to and the remaining elements left uninitialized.
+ /// The type of the elements in the vector () is not supported.
[Intrinsic]
- public static unsafe Vector128 CreateScalarUnsafe(byte value)
+ internal static unsafe Vector128 CreateScalarUnsafe(T value)
+ where T : struct
{
// This relies on us stripping the "init" flag from the ".locals"
// declaration to let the upper bits be uninitialized.
- byte* pResult = stackalloc byte[16];
- pResult[0] = value;
- return Unsafe.AsRef>(pResult);
+ ThrowHelper.ThrowForUnsupportedIntrinsicsVector128BaseType();
+ Unsafe.SkipInit(out Vector128 result);
+
+ result.SetElementUnsafe(0, value);
+ return result;
}
+ /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized.
+ /// The value that element 0 will be initialized to.
+ /// A new instance with the first element initialized to and the remaining elements left uninitialized.
+ [Intrinsic]
+ public static unsafe Vector128 CreateScalarUnsafe(byte value) => CreateScalarUnsafe(value);
+
/// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized.
/// The value that element 0 will be initialized to.
/// A new instance with the first element initialized to and the remaining elements left uninitialized.
[Intrinsic]
- public static unsafe Vector128 CreateScalarUnsafe(double value)
- {
- // This relies on us stripping the "init" flag from the ".locals"
- // declaration to let the upper bits be uninitialized.
-
- double* pResult = stackalloc double[2];
- pResult[0] = value;
- return Unsafe.AsRef>(pResult);
- }
+ public static unsafe Vector128 CreateScalarUnsafe(double value) => CreateScalarUnsafe(value);
/// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized.
/// The value that element 0 will be initialized to.
/// A new instance with the first element initialized to and the remaining elements left uninitialized.
[Intrinsic]
- public static unsafe Vector128 CreateScalarUnsafe(short value)
- {
- // This relies on us stripping the "init" flag from the ".locals"
- // declaration to let the upper bits be uninitialized.
-
- short* pResult = stackalloc short[8];
- pResult[0] = value;
- return Unsafe.AsRef>(pResult);
- }
+ public static unsafe Vector128 CreateScalarUnsafe(short value) => CreateScalarUnsafe(value);
/// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized.
/// The value that element 0 will be initialized to.
/// A new instance with the first element initialized to and the remaining elements left uninitialized.
[Intrinsic]
- public static unsafe Vector128 CreateScalarUnsafe(int value)
- {
- // This relies on us stripping the "init" flag from the ".locals"
- // declaration to let the upper bits be uninitialized.
-
- int* pResult = stackalloc int[4];
- pResult[0] = value;
- return Unsafe.AsRef>(pResult);
- }
+ public static unsafe Vector128 CreateScalarUnsafe(int value) => CreateScalarUnsafe(value);
/// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized.
/// The value that element 0 will be initialized to.
/// A new instance with the first element initialized to and the remaining elements left uninitialized.
[Intrinsic]
- public static unsafe Vector128 CreateScalarUnsafe(long value)
- {
- // This relies on us stripping the "init" flag from the ".locals"
- // declaration to let the upper bits be uninitialized.
-
- long* pResult = stackalloc long[2];
- pResult[0] = value;
- return Unsafe.AsRef>(pResult);
- }
+ public static unsafe Vector128 CreateScalarUnsafe(long value) => CreateScalarUnsafe(value);
/// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized.
/// The value that element 0 will be initialized to.
/// A new instance with the first element initialized to and the remaining elements left uninitialized.
[Intrinsic]
- public static unsafe Vector128 CreateScalarUnsafe(nint value)
- {
-#if TARGET_64BIT
- return CreateScalarUnsafe((long)value).AsNInt();
-#else
- return CreateScalarUnsafe((int)value).AsNInt();
-#endif
- }
+ public static unsafe Vector128 CreateScalarUnsafe(nint value) => CreateScalarUnsafe(value);
/// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized.
/// The value that element 0 will be initialized to.
/// A new instance with the first element initialized to and the remaining elements left uninitialized.
[Intrinsic]
[CLSCompliant(false)]
- public static unsafe Vector128 CreateScalarUnsafe(nuint value)
- {
-#if TARGET_64BIT
- return CreateScalarUnsafe((ulong)value).AsNUInt();
-#else
- return CreateScalarUnsafe((uint)value).AsNUInt();
-#endif
- }
+ public static unsafe Vector128 CreateScalarUnsafe(nuint value) => CreateScalarUnsafe(value);
/// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized.
/// The value that element 0 will be initialized to.
/// A new instance with the first element initialized to and the remaining elements left uninitialized.
[Intrinsic]
[CLSCompliant(false)]
- public static unsafe Vector128 CreateScalarUnsafe(sbyte value)
- {
- // This relies on us stripping the "init" flag from the ".locals"
- // declaration to let the upper bits be uninitialized.
-
- sbyte* pResult = stackalloc sbyte[16];
- pResult[0] = value;
- return Unsafe.AsRef>(pResult);
- }
+ public static unsafe Vector128 CreateScalarUnsafe(sbyte value) => CreateScalarUnsafe(value);
/// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized.
/// The value that element 0 will be initialized to.
/// A new instance with the first element initialized to and the remaining elements left uninitialized.
[Intrinsic]
- public static unsafe Vector128 CreateScalarUnsafe(float value)
- {
- // This relies on us stripping the "init" flag from the ".locals"
- // declaration to let the upper bits be uninitialized.
-
- float* pResult = stackalloc float[4];
- pResult[0] = value;
- return Unsafe.AsRef>(pResult);
- }
+ public static unsafe Vector128 CreateScalarUnsafe(float value) => CreateScalarUnsafe(value);
/// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized.
/// The value that element 0 will be initialized to.
/// A new instance with the first element initialized to and the remaining elements left uninitialized.
[Intrinsic]
[CLSCompliant(false)]
- public static unsafe Vector128 CreateScalarUnsafe(ushort value)
- {
- // This relies on us stripping the "init" flag from the ".locals"
- // declaration to let the upper bits be uninitialized.
-
- ushort* pResult = stackalloc ushort[8];
- pResult[0] = value;
- return Unsafe.AsRef>(pResult);
- }
+ public static unsafe Vector128 CreateScalarUnsafe(ushort value) => CreateScalarUnsafe(value);
/// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized.
/// The value that element 0 will be initialized to.
/// A new instance with the first element initialized to and the remaining elements left uninitialized.
[Intrinsic]
[CLSCompliant(false)]
- public static unsafe Vector128 CreateScalarUnsafe(uint value)
- {
- // This relies on us stripping the "init" flag from the ".locals"
- // declaration to let the upper bits be uninitialized.
-
- uint* pResult = stackalloc uint[4];
- pResult[0] = value;
- return Unsafe.AsRef>(pResult);
- }
+ public static unsafe Vector128 CreateScalarUnsafe(uint value) => CreateScalarUnsafe(value);
/// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized.
/// The value that element 0 will be initialized to.
/// A new instance with the first element initialized to and the remaining elements left uninitialized.
[Intrinsic]
[CLSCompliant(false)]
- public static unsafe Vector128 CreateScalarUnsafe(ulong value)
- {
- // This relies on us stripping the "init" flag from the ".locals"
- // declaration to let the upper bits be uninitialized.
-
- ulong* pResult = stackalloc ulong[2];
- pResult[0] = value;
- return Unsafe.AsRef>(pResult);
- }
+ public static unsafe Vector128 CreateScalarUnsafe(ulong value) => CreateScalarUnsafe(value);
/// Divides two vectors to compute their quotient.
/// The vector that will be divided by .
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 7fa449d3ef503e..05e7c077d5f756 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
@@ -6,7 +6,6 @@
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using System.Runtime.Intrinsics.X86;
using System.Text;
namespace System.Runtime.Intrinsics
@@ -26,7 +25,7 @@ namespace System.Runtime.Intrinsics
[DebuggerDisplay("{DisplayString,nq}")]
[DebuggerTypeProxy(typeof(Vector128DebugView<>))]
[StructLayout(LayoutKind.Sequential, Size = Vector128.Size)]
- public readonly struct Vector128 : IEquatable>
+ public readonly struct Vector128 : ISimdVector, T>
where T : struct
{
// These fields exist to ensure the alignment is 8, rather than 1.
@@ -89,6 +88,9 @@ public static Vector128 Zero
}
}
+ ///
+ static bool ISimdVector, T>.IsHardwareAccelerated => Vector128.IsHardwareAccelerated;
+
internal unsafe string DisplayString
{
get
@@ -387,5 +389,92 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri
return sb.ToString();
}
+
+ ///
+ static Vector128 ISimdVector, T>.Abs(Vector128 vector) => Vector128.Abs(vector);
+
+ ///
+ static Vector128 ISimdVector, T>.ConditionalSelect(Vector128 condition, Vector128 left, Vector128 right) => Vector128.ConditionalSelect(condition, left, right);
+
+ ///
+ static Vector128 ISimdVector, T>.Create(T value) => Vector128.Create(value);
+
+ ///
+ static Vector128 ISimdVector, T>.CreateScalar(T value) => Vector128.CreateScalar(value);
+
+ ///
+ static Vector128 ISimdVector, T>.CreateScalarUnsafe(T value) => Vector128.CreateScalarUnsafe(value);
+
+ ///
+ 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>.EqualsAny(Vector128 left, Vector128 right) => Vector128.EqualsAny(left, right);
+
+ ///
+ 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);
+
+ ///
+ static bool ISimdVector, T>.GreaterThanAll(Vector128 left, Vector128 right) => Vector128.GreaterThanAll(left, right);
+
+ ///
+ static bool ISimdVector, T>.GreaterThanAny(Vector128 left, Vector128 right) => Vector128.GreaterThanAny(left, right);
+
+ ///
+ static Vector128 ISimdVector, T>.GreaterThanOrEqual(Vector128 left, Vector128 right) => Vector128.GreaterThanOrEqual(left, right);
+
+ ///
+ static bool ISimdVector, T>.GreaterThanOrEqualAll(Vector128 left, Vector128 right) => Vector128.GreaterThanOrEqualAll(left, right);
+
+ ///
+ static bool ISimdVector, T>.GreaterThanOrEqualAny(Vector128 left, Vector128 right) => Vector128.GreaterThanOrEqualAny(left, right);
+
+ ///
+ static Vector128 ISimdVector, T>.LessThan(Vector128 left, Vector128 right) => Vector128.LessThan(left, right);
+
+ ///
+ static bool ISimdVector, T>.LessThanAll(Vector128 left, Vector128 right) => Vector128.LessThanAll(left, right);
+
+ ///
+ static bool ISimdVector, T>.LessThanAny(Vector128 left, Vector128 right) => Vector128.LessThanAny(left, right);
+
+ ///
+ static Vector128 ISimdVector, T>.LessThanOrEqual(Vector128 left, Vector128 right) => Vector128.LessThanOrEqual(left, right);
+
+ ///
+ static bool ISimdVector, T>.LessThanOrEqualAll(Vector128 left, Vector128