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 afc252563c0401..80901d85746412 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 @@ -2384,7 +2384,7 @@ public static Vector128 Shuffle(Vector128 vector, Vector128 [CompExactlyDependsOn(typeof(AdvSimd))] [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] [CompExactlyDependsOn(typeof(PackedSimd))] - internal static Vector128 ShuffleUnsafe(Vector128 vector, Vector128 indices) + public static Vector128 ShuffleUnsafe(Vector128 vector, Vector128 indices) { if (Ssse3.IsSupported) { 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 758d0291af49e6..73d9b5242ff4ee 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 @@ -5,6 +5,8 @@ using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.Arm; +using System.Runtime.Intrinsics.Wasm; using System.Runtime.Intrinsics.X86; namespace System.Runtime.Intrinsics @@ -2351,6 +2353,45 @@ public static Vector256 Shuffle(Vector256 vector, Vector256 return result; } + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// Behavior is platform-dependent for out-of-range indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 31]. + /// On hardware with support, indices are treated as modulo 32, and if the high bit is set, the result will be set to 0 for that element. + /// On hardware with support, this method behaves the same as Shuffle. + /// On hardware with support, indices are treated as modulo 32. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [CompExactlyDependsOn(typeof(Avx2))] + [CompExactlyDependsOn(typeof(AdvSimd))] + [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] + [CompExactlyDependsOn(typeof(PackedSimd))] + public static Vector256 ShuffleUnsafe(Vector256 vector, Vector256 indices) + { + if (Avx2.IsSupported) + { + return Avx2.Shuffle(vector, indices); + } + + if (AdvSimd.Arm64.IsSupported) + { + (Vector128, Vector128) table = (vector.GetLower(), vector.GetUpper()); + return Vector256.Create( + AdvSimd.Arm64.VectorTableLookup(table, indices.GetLower()), + AdvSimd.Arm64.VectorTableLookup(table, indices.GetUpper())); + } + + if (PackedSimd.IsSupported) + { + return Vector256.Create( + PackedSimd.Shuffle(vector.GetLower(), vector.GetUpper(), indices.GetLower()), + PackedSimd.Shuffle(vector.GetLower(), vector.GetUpper(), indices.GetUpper())); + } + + return Shuffle(vector, indices); + } + /// Creates a new vector by selecting values from an input vector using a set of indices. /// The input vector from which values are selected. /// The per-element indices used to select a value from . 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 5b740db4300982..c8b680a7a3e798 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 @@ -5,6 +5,7 @@ using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.X86; namespace System.Runtime.Intrinsics @@ -2404,6 +2405,41 @@ public static Vector512 Shuffle(Vector512 vector, Vector512 return result; } + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// Behavior is platform-dependent for out-of-range indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 63]. + /// On hardware with support, indices are treated as modulo 64, and if the high bit is set, the result will be set to 0 for that element. + /// On hardware with support, this method behaves the same as Shuffle. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [CompExactlyDependsOn(typeof(Avx512BW))] + [CompExactlyDependsOn(typeof(AdvSimd))] + [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] + public static Vector512 ShuffleUnsafe(Vector512 vector, Vector512 indices) + { + if (Avx512BW.IsSupported) + { + return Avx512BW.Shuffle(vector, indices); + } + + if (AdvSimd.Arm64.IsSupported) + { + (Vector128, Vector128, Vector128, Vector128) table = + (vector.GetLower().GetLower(), vector.GetLower().GetUpper(), vector.GetUpper().GetLower(), vector.GetUpper().GetUpper()); + return Vector512.Create( + Vector256.Create( + AdvSimd.Arm64.VectorTableLookup(table, indices.GetLower().GetLower()), + AdvSimd.Arm64.VectorTableLookup(table, indices.GetLower().GetUpper())), + Vector256.Create( + AdvSimd.Arm64.VectorTableLookup(table, indices.GetUpper().GetLower()), + AdvSimd.Arm64.VectorTableLookup(table, indices.GetUpper().GetUpper()))); + } + + return Shuffle(vector, indices); + } + /// Creates a new vector by selecting values from an input vector using a set of indices. /// The input vector from which values are selected. /// The per-element indices used to select a value from . 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 11fd7d7591a8d2..1e263204a341c0 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 @@ -6,6 +6,8 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics.Arm; +using System.Runtime.Intrinsics.Wasm; +using System.Runtime.Intrinsics.X86; namespace System.Runtime.Intrinsics { @@ -2076,6 +2078,38 @@ public static Vector64 Shuffle(Vector64 vector, Vector64 in return result; } + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// Behavior is platform-dependent for out-of-range indices. + /// The input vector from which values are selected. + /// The per-element indices used to select a value from . + /// A new vector containing the values from selected by the given . + /// Unlike Shuffle, this method delegates to the underlying hardware intrinsic without ensuring that are normalized to [0, 7]. + /// On hardware with support, indices are treated as modulo 8, and if the high bit is set, the result will be set to 0 for that element. + /// On hardware with or support, this method behaves the same as Shuffle. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [CompExactlyDependsOn(typeof(Ssse3))] + [CompExactlyDependsOn(typeof(AdvSimd))] + [CompExactlyDependsOn(typeof(PackedSimd))] + public static Vector64 ShuffleUnsafe(Vector64 vector, Vector64 indices) + { + if (Ssse3.IsSupported) + { + return Ssse3.Shuffle(Vector128.Create(vector, vector), Vector128.Create(indices, Vector64.Zero)).GetLower(); + } + + if (AdvSimd.IsSupported) + { + return AdvSimd.VectorTableLookup(Vector128.Create(vector, Vector64.Zero), indices); + } + + if (PackedSimd.IsSupported) + { + return PackedSimd.Swizzle(Vector128.Create(vector, Vector64.Zero), Vector128.Create(indices, Vector64.Zero)).GetLower(); + } + + return Shuffle(vector, indices); + } + /// Creates a new vector by selecting values from an input vector using a set of indices. /// The input vector from which values are selected. /// The per-element indices used to select a value from . diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index e5c448ba1277c1..2d3489b5dc9e60 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -253,6 +253,7 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 Shuffle(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) { throw null; } public static System.Runtime.Intrinsics.Vector128 Shuffle(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector128 ShuffleUnsafe(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) { throw null; } public static System.Runtime.Intrinsics.Vector128 Sqrt(System.Runtime.Intrinsics.Vector128 vector) { throw null; } #pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') [System.CLSCompliantAttribute(false)] @@ -580,6 +581,7 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector256 Shuffle(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) { throw null; } public static System.Runtime.Intrinsics.Vector256 Shuffle(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector256 ShuffleUnsafe(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) { throw null; } public static System.Runtime.Intrinsics.Vector256 Sqrt(System.Runtime.Intrinsics.Vector256 vector) { throw null; } #pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') [System.CLSCompliantAttribute(false)] @@ -907,6 +909,7 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector512 Shuffle(System.Runtime.Intrinsics.Vector512 vector, System.Runtime.Intrinsics.Vector512 indices) { throw null; } public static System.Runtime.Intrinsics.Vector512 Shuffle(System.Runtime.Intrinsics.Vector512 vector, System.Runtime.Intrinsics.Vector512 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector512 ShuffleUnsafe(System.Runtime.Intrinsics.Vector512 vector, System.Runtime.Intrinsics.Vector512 indices) { throw null; } public static System.Runtime.Intrinsics.Vector512 Sqrt(System.Runtime.Intrinsics.Vector512 vector) { throw null; } #pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') [System.CLSCompliantAttribute(false)] @@ -1202,6 +1205,7 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector64 Shuffle(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) { throw null; } public static System.Runtime.Intrinsics.Vector64 Shuffle(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) { throw null; } + public static System.Runtime.Intrinsics.Vector64 ShuffleUnsafe(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) { throw null; } public static System.Runtime.Intrinsics.Vector64 Sqrt(System.Runtime.Intrinsics.Vector64 vector) { throw null; } #pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type ('T') [System.CLSCompliantAttribute(false)] diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs index 3894d835a60b08..6e6d69e708eabb 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs @@ -2157,8 +2157,14 @@ public void Vector128UInt64ShiftRightLogicalTest() public void Vector128ByteShuffleOneInputTest() { Vector128 vector = Vector128.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector128 result = Vector128.Shuffle(vector, Vector128.Create((byte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((byte)(Vector128.Count - index), result.GetElement(index)); + } + result = Vector128.ShuffleUnsafe(vector, Vector128.Create((byte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); for (int index = 0; index < Vector128.Count; index++) { Assert.Equal((byte)(Vector128.Count - index), result.GetElement(index)); @@ -2277,7 +2283,12 @@ public void Vector128UInt64ShuffleOneInputTest() public void Vector128ByteShuffleOneInputWithDirectVectorTest() { Vector128 result = Vector128.Shuffle(Vector128.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), Vector128.Create((byte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((byte)(Vector128.Count - index), result.GetElement(index)); + } + result = Vector128.ShuffleUnsafe(Vector128.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), Vector128.Create((byte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); for (int index = 0; index < Vector128.Count; index++) { Assert.Equal((byte)(Vector128.Count - index), result.GetElement(index)); @@ -2388,8 +2399,14 @@ public void Vector128ByteShuffleOneInputWithLocalIndicesTest() { Vector128 vector = Vector128.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); Vector128 indices = Vector128.Create((byte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + Vector128 result = Vector128.Shuffle(vector, indices); + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((byte)(Vector128.Count - index), result.GetElement(index)); + } + result = Vector128.ShuffleUnsafe(vector, indices); for (int index = 0; index < Vector128.Count; index++) { Assert.Equal((byte)(Vector128.Count - index), result.GetElement(index)); @@ -2517,8 +2534,14 @@ public void Vector128UInt64ShuffleOneInputWithLocalIndicesTest() public void Vector128ByteShuffleOneInputWithAllBitsSetIndicesTest() { Vector128 vector = Vector128.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector128 result = Vector128.Shuffle(vector, Vector128.AllBitsSet); + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((byte)0, result.GetElement(index)); + } + result = Vector128.ShuffleUnsafe(vector, Vector128.AllBitsSet); for (int index = 0; index < Vector128.Count; index++) { Assert.Equal((byte)0, result.GetElement(index)); @@ -2637,8 +2660,14 @@ public void Vector128UInt64ShuffleOneInputWithAllBitsSetIndicesTest() public void Vector128ByteShuffleOneInputWithZeroIndicesTest() { Vector128 vector = Vector128.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Vector128 result = Vector128.Shuffle(vector, Vector128.Zero); + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((byte)1, result.GetElement(index)); + } + result = Vector128.ShuffleUnsafe(vector, Vector128.Zero); for (int index = 0; index < Vector128.Count; index++) { Assert.Equal((byte)1, result.GetElement(index)); diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs index 6bdc86bc46f437..42731732c82bfa 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs @@ -4,6 +4,7 @@ using System.Numerics; using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.Wasm; using Xunit; namespace System.Runtime.Intrinsics.Tests.Vectors @@ -2622,8 +2623,14 @@ public void Vector256UInt64ShiftRightLogicalTest() public void Vector256ByteShuffleOneInputTest() { Vector256 vector = Vector256.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + Vector256 result = Vector256.Shuffle(vector, Vector256.Create((byte)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((byte)(Vector256.Count - index), result.GetElement(index)); + } + result = Vector256.ShuffleUnsafe(vector, Vector256.Create((byte)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); for (int index = 0; index < Vector256.Count; index++) { Assert.Equal((byte)(Vector256.Count - index), result.GetElement(index)); @@ -2742,7 +2749,12 @@ public void Vector256UInt64ShuffleOneInputTest() public void Vector256ByteShuffleOneInputWithDirectVectorTest() { Vector256 result = Vector256.Shuffle(Vector256.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), Vector256.Create((byte)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((byte)(Vector256.Count - index), result.GetElement(index)); + } + result = Vector256.ShuffleUnsafe(Vector256.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), Vector256.Create((byte)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); for (int index = 0; index < Vector256.Count; index++) { Assert.Equal((byte)(Vector256.Count - index), result.GetElement(index)); @@ -2852,12 +2864,21 @@ public void Vector256UInt64ShuffleOneInputWithDirectVectorTest() public void Vector256ByteShuffleOneInputWithDirectVectorAndNoCrossLaneTest() { Vector256 result = Vector256.Shuffle(Vector256.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), Vector256.Create((byte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16)); - for (int index = 0; index < Vector128.Count; index++) { Assert.Equal((byte)(Vector128.Count - index), result.GetElement(index)); } + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((byte)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + + result = Vector256.ShuffleUnsafe(Vector256.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), Vector256.Create((byte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16)); + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((byte)(Vector128.Count - index), result.GetElement(index)); + } for (int index = Vector128.Count; index < Vector256.Count; index++) { Assert.Equal((byte)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); @@ -3013,8 +3034,14 @@ public void Vector256ByteShuffleOneInputWithLocalIndicesTest() { Vector256 vector = Vector256.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); Vector256 indices = Vector256.Create((byte)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + Vector256 result = Vector256.Shuffle(vector, indices); + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((byte)(Vector256.Count - index), result.GetElement(index)); + } + result = Vector256.ShuffleUnsafe(vector, indices); for (int index = 0; index < Vector256.Count; index++) { Assert.Equal((byte)(Vector256.Count - index), result.GetElement(index)); @@ -3142,12 +3169,26 @@ public void Vector256UInt64ShuffleOneInputWithLocalIndicesTest() public void Vector256ByteShuffleOneInputWithAllBitsSetIndicesTest() { Vector256 vector = Vector256.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); - Vector256 result = Vector256.Shuffle(vector, Vector256.AllBitsSet); + Vector256 result = Vector256.Shuffle(vector, Vector256.AllBitsSet); for (int index = 0; index < Vector256.Count; index++) { Assert.Equal((byte)0, result.GetElement(index)); } + + result = Vector256.ShuffleUnsafe(vector, Vector256.AllBitsSet); + for (int index = 0; index < Vector256.Count; index++) + { + if (!PackedSimd.IsSupported) + { + Assert.Equal((byte)0, result.GetElement(index)); + } + else + { + // On hardware with support, indices are treated as modulo 32. + Assert.Equal((byte)32, result.GetElement(index)); + } + } } [Fact] @@ -3262,8 +3303,14 @@ public void Vector256UInt64ShuffleOneInputWithAllBitsSetIndicesTest() public void Vector256ByteShuffleOneInputWithZeroIndicesTest() { Vector256 vector = Vector256.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + Vector256 result = Vector256.Shuffle(vector, Vector256.Zero); + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((byte)1, result.GetElement(index)); + } + result = Vector256.ShuffleUnsafe(vector, Vector256.Zero); for (int index = 0; index < Vector256.Count; index++) { Assert.Equal((byte)1, result.GetElement(index)); diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs index 4922cf8cab8583..2045e6e6247269 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs @@ -2263,8 +2263,14 @@ public void Vector512UInt64ShiftRightLogicalTest() public void Vector512ByteShuffleOneInputTest() { Vector512 vector = Vector512.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64); + Vector512 result = Vector512.Shuffle(vector, Vector512.Create((byte)63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((byte)(Vector512.Count - index), result.GetElement(index)); + } + result = Vector512.ShuffleUnsafe(vector, Vector512.Create((byte)63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); for (int index = 0; index < Vector512.Count; index++) { Assert.Equal((byte)(Vector512.Count - index), result.GetElement(index)); @@ -2386,7 +2392,15 @@ public void Vector512ByteShuffleOneInputWithDirectVectorTest() Vector512.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64), Vector512.Create((byte)63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) ); + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((byte)(Vector512.Count - index), result.GetElement(index)); + } + result = Vector512.ShuffleUnsafe( + Vector512.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64), + Vector512.Create((byte)63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + ); for (int index = 0; index < Vector512.Count; index++) { Assert.Equal((byte)(Vector512.Count - index), result.GetElement(index)); @@ -2526,22 +2540,39 @@ public void Vector512ByteShuffleOneInputWithDirectVectorAndNoCross128BitLaneTest Vector512.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64), Vector512.Create((byte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48) ); - for (int index = 0; index < Vector128.Count; index++) { Assert.Equal((byte)(Vector128.Count - index), result.GetElement(index)); } - for (int index = Vector128.Count; index < Vector256.Count; index++) { Assert.Equal((byte)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); } - for (int index = Vector256.Count; index < Vector512.Count - Vector128.Count; index++) { Assert.Equal((byte)(Vector512.Count - Vector128.Count - (index - Vector256.Count)), result.GetElement(index)); } + for (int index = Vector256.Count + Vector128.Count; index < Vector512.Count; index++) + { + Assert.Equal((byte)(Vector512.Count - (index - Vector256.Count - Vector128.Count)), result.GetElement(index)); + } + result = Vector512.ShuffleUnsafe( + Vector512.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64), + Vector512.Create((byte)15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48) + ); + for (int index = 0; index < Vector128.Count; index++) + { + Assert.Equal((byte)(Vector128.Count - index), result.GetElement(index)); + } + for (int index = Vector128.Count; index < Vector256.Count; index++) + { + Assert.Equal((byte)(Vector256.Count - (index - Vector128.Count)), result.GetElement(index)); + } + for (int index = Vector256.Count; index < Vector512.Count - Vector128.Count; index++) + { + Assert.Equal((byte)(Vector512.Count - Vector128.Count - (index - Vector256.Count)), result.GetElement(index)); + } for (int index = Vector256.Count + Vector128.Count; index < Vector512.Count; index++) { Assert.Equal((byte)(Vector512.Count - (index - Vector256.Count - Vector128.Count)), result.GetElement(index)); @@ -2816,12 +2847,23 @@ public void Vector512ByteShuffleOneInputWithDirectVectorAndNoCross256BitLaneTest Vector512.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64), Vector512.Create((byte)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32) ); - for (int index = 0; index < Vector256.Count; index++) { Assert.Equal((byte)(Vector256.Count - index), result.GetElement(index)); } + for (int index = Vector256.Count; index < Vector512.Count; index++) + { + Assert.Equal((byte)(Vector512.Count - (index - Vector256.Count)), result.GetElement(index)); + } + result = Vector512.ShuffleUnsafe( + Vector512.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64), + Vector512.Create((byte)31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32) + ); + for (int index = 0; index < Vector256.Count; index++) + { + Assert.Equal((byte)(Vector256.Count - index), result.GetElement(index)); + } for (int index = Vector256.Count; index < Vector512.Count; index++) { Assert.Equal((byte)(Vector512.Count - (index - Vector256.Count)), result.GetElement(index)); @@ -3004,8 +3046,14 @@ public void Vector512ByteShuffleOneInputWithLocalIndicesTest() { Vector512 vector = Vector512.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64); Vector512 indices = Vector512.Create((byte)63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + Vector512 result = Vector512.Shuffle(vector, indices); + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((byte)(Vector512.Count - index), result.GetElement(index)); + } + result = Vector512.ShuffleUnsafe(vector, indices); for (int index = 0; index < Vector512.Count; index++) { Assert.Equal((byte)(Vector512.Count - index), result.GetElement(index)); @@ -3133,8 +3181,14 @@ public void Vector512UInt64ShuffleOneInputWithLocalIndicesTest() public void Vector512ByteShuffleOneInputWithAllBitsSetIndicesTest() { Vector512 vector = Vector512.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64); + Vector512 result = Vector512.Shuffle(vector, Vector512.AllBitsSet); + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((byte)0, result.GetElement(index)); + } + result = Vector512.ShuffleUnsafe(vector, Vector512.AllBitsSet); for (int index = 0; index < Vector512.Count; index++) { Assert.Equal((byte)0, result.GetElement(index)); @@ -3253,8 +3307,14 @@ public void Vector512UInt64ShuffleOneInputWithAllBitsSetIndicesTest() public void Vector512ByteShuffleOneInputWithZeroIndicesTest() { Vector512 vector = Vector512.Create((byte)1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64); + Vector512 result = Vector512.Shuffle(vector, Vector512.Zero); + for (int index = 0; index < Vector512.Count; index++) + { + Assert.Equal((byte)1, result.GetElement(index)); + } + result = Vector512.ShuffleUnsafe(vector, Vector512.Zero); for (int index = 0; index < Vector512.Count; index++) { Assert.Equal((byte)1, result.GetElement(index)); diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs index 8596f3b0ff7861..1adb903bffa27f 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs @@ -1955,8 +1955,14 @@ public void Vector64UInt64ShiftRightLogicalTest() public void Vector64ByteShuffleOneInputTest() { Vector64 vector = Vector64.Create((byte)1, 2, 3, 4, 5, 6, 7, 8); + Vector64 result = Vector64.Shuffle(vector, Vector64.Create((byte)7, 6, 5, 4, 3, 2, 1, 0)); + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((byte)(Vector64.Count - index), result.GetElement(index)); + } + result = Vector64.ShuffleUnsafe(vector, Vector64.Create((byte)7, 6, 5, 4, 3, 2, 1, 0)); for (int index = 0; index < Vector64.Count; index++) { Assert.Equal((byte)(Vector64.Count - index), result.GetElement(index)); @@ -2044,6 +2050,12 @@ public void Vector64ByteShuffleOneInputWithDirectVectorTest() { Assert.Equal((byte)(Vector64.Count - index), result.GetElement(index)); } + + result = Vector64.ShuffleUnsafe(Vector64.Create((byte)1, 2, 3, 4, 5, 6, 7, 8), Vector64.Create((byte)7, 6, 5, 4, 3, 2, 1, 0)); + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((byte)(Vector64.Count - index), result.GetElement(index)); + } } [Fact] @@ -2117,8 +2129,14 @@ public void Vector64ByteShuffleOneInputWithLocalIndicesTest() { Vector64 vector = Vector64.Create((byte)1, 2, 3, 4, 5, 6, 7, 8); Vector64 indices = Vector64.Create((byte)7, 6, 5, 4, 3, 2, 1, 0); + Vector64 result = Vector64.Shuffle(vector, indices); + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((byte)(Vector64.Count - index), result.GetElement(index)); + } + result = Vector64.ShuffleUnsafe(vector, indices); for (int index = 0; index < Vector64.Count; index++) { Assert.Equal((byte)(Vector64.Count - index), result.GetElement(index)); @@ -2207,8 +2225,14 @@ public void Vector64UInt32ShuffleOneInputWithLocalIndicesTest() public void Vector64ByteShuffleOneInputWithAllBitsSetIndicesTest() { Vector64 vector = Vector64.Create((byte)1, 2, 3, 4, 5, 6, 7, 8); + Vector64 result = Vector64.Shuffle(vector, Vector64.AllBitsSet); + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((byte)0, result.GetElement(index)); + } + result = Vector64.ShuffleUnsafe(vector, Vector64.AllBitsSet); for (int index = 0; index < Vector64.Count; index++) { Assert.Equal((byte)0, result.GetElement(index)); @@ -2291,8 +2315,14 @@ public void Vector64UInt32ShuffleOneInputWithAllBitsSetIndicesTest() public void Vector64ByteShuffleOneInputWithZeroIndicesTest() { Vector64 vector = Vector64.Create((byte)1, 2, 3, 4, 5, 6, 7, 8); + Vector64 result = Vector64.Shuffle(vector, Vector64.Zero); + for (int index = 0; index < Vector64.Count; index++) + { + Assert.Equal((byte)1, result.GetElement(index)); + } + result = Vector64.ShuffleUnsafe(vector, Vector64.Zero); for (int index = 0; index < Vector64.Count; index++) { Assert.Equal((byte)1, result.GetElement(index));