From 482d9370ebafb4da3010bcb22c5217ec5a5a0f29 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 19 Jan 2021 16:24:23 +0800 Subject: [PATCH 01/10] Implement Vector.As using Unsafe.As. --- .../src/System/Numerics/Vector.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) 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 99fff3d99aed89..bb45653ff2d112 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs @@ -1,8 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; +using Internal.Runtime.CompilerServices; namespace System.Numerics { @@ -1431,5 +1433,27 @@ internal static void ThrowInsufficientNumberOfElementsException(int requiredElem { throw new IndexOutOfRangeException(SR.Format(SR.Arg_InsufficientNumberOfElements, requiredElementCount, "values")); } + + /// + /// Reinterprets a as a of new type. + /// + /// The type of the input vector. + /// The type to reinterpret the vector as. + /// The vector to reinterpret. + /// reinterpreted as a new . + /// + /// The type of or is not supported. + /// + public static Vector As(Vector vector) + where TFrom : struct + where TTo : struct + { + ThrowHelper.ThrowForUnsupportedVectorBaseType(); + ThrowHelper.ThrowForUnsupportedVectorBaseType(); + + Debug.Assert(Vector.Count * Unsafe.SizeOf() == Vector.Count * Unsafe.SizeOf()); + + return Unsafe.As, Vector>(ref vector); + } } } From f943af04e25821d401d7033eb7b4c382a5aaad37 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 19 Jan 2021 16:40:55 +0800 Subject: [PATCH 02/10] Ref source for Vector.As. --- .../System.Numerics.Vectors/ref/System.Numerics.Vectors.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs index 7e293b8fce2331..31be248fd1df05 100644 --- a/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs +++ b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs @@ -192,6 +192,7 @@ public static partial class Vector public static System.Numerics.Vector Abs(System.Numerics.Vector value) where T : struct { throw null; } public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) where T : struct { throw null; } public static System.Numerics.Vector AndNot(System.Numerics.Vector left, System.Numerics.Vector right) where T : struct { throw null; } + public static System.Numerics.Vector As(System.Numerics.Vector vector) where TFrom : struct where TTo : struct { throw null; } public static System.Numerics.Vector AsVectorByte(System.Numerics.Vector value) where T : struct { throw null; } public static System.Numerics.Vector AsVectorDouble(System.Numerics.Vector value) where T : struct { throw null; } public static System.Numerics.Vector AsVectorInt16(System.Numerics.Vector value) where T : struct { throw null; } From 0ea40f77841dcf8186d692690b751daa4a914684 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 20 Jan 2021 15:29:35 +0800 Subject: [PATCH 03/10] Mark managed impl with intrinsic and aggressive inlining. --- .../System.Private.CoreLib/src/System/Numerics/Vector.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 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 bb45653ff2d112..184d6e0568b9d7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; @@ -1444,6 +1443,8 @@ internal static void ThrowInsufficientNumberOfElementsException(int requiredElem /// /// The type of or is not supported. /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector As(Vector vector) where TFrom : struct where TTo : struct @@ -1451,8 +1452,6 @@ public static Vector As(Vector vector) ThrowHelper.ThrowForUnsupportedVectorBaseType(); ThrowHelper.ThrowForUnsupportedVectorBaseType(); - Debug.Assert(Vector.Count * Unsafe.SizeOf() == Vector.Count * Unsafe.SizeOf()); - return Unsafe.As, Vector>(ref vector); } } From 7a8d51d478aa830e32b07f2e888decf573b1b893 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 20 Jan 2021 15:46:57 +0800 Subject: [PATCH 04/10] Hwintrinsic definition --- src/coreclr/jit/simdashwintrinsiclistarm64.h | 1 + src/coreclr/jit/simdashwintrinsiclistxarch.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/coreclr/jit/simdashwintrinsiclistarm64.h b/src/coreclr/jit/simdashwintrinsiclistarm64.h index 481e139c2ac5b1..494377bc7172fe 100644 --- a/src/coreclr/jit/simdashwintrinsiclistarm64.h +++ b/src/coreclr/jit/simdashwintrinsiclistarm64.h @@ -102,6 +102,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector4, SquareRoot, // Vector Intrinsics SIMD_AS_HWINTRINSIC_ID(VectorT128, Abs, 1, {NI_AdvSimd_Abs, NI_VectorT128_Abs, NI_AdvSimd_Abs, NI_VectorT128_Abs, NI_AdvSimd_Abs, NI_VectorT128_Abs, NI_AdvSimd_Arm64_Abs, NI_VectorT128_Abs, NI_AdvSimd_Abs, NI_AdvSimd_Arm64_Abs}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT128, AndNot, 2, {NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear, NI_AdvSimd_BitwiseClear}, SimdAsHWIntrinsicFlag::None) +SIMD_AS_HWINTRINSIC_ID(VectorT128, As, 1, {NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT128, Ceiling, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AdvSimd_Ceiling, NI_AdvSimd_Arm64_Ceiling}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT128, ConditionalSelect, 3, {NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(VectorT128, CreateBroadcast, ".ctor", 2, {NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast}, SimdAsHWIntrinsicFlag::InstanceMethod) diff --git a/src/coreclr/jit/simdashwintrinsiclistxarch.h b/src/coreclr/jit/simdashwintrinsiclistxarch.h index d542dc63d31611..65584c3abb09e0 100644 --- a/src/coreclr/jit/simdashwintrinsiclistxarch.h +++ b/src/coreclr/jit/simdashwintrinsiclistxarch.h @@ -102,6 +102,7 @@ SIMD_AS_HWINTRINSIC_ID(Vector4, SquareRoot, // Vector Intrinsics SIMD_AS_HWINTRINSIC_ID(VectorT128, Abs, 1, {NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs, NI_VectorT128_Abs}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT128, AndNot, 2, {NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE2_AndNot, NI_SSE_AndNot, NI_SSE2_AndNot}, SimdAsHWIntrinsicFlag::NeedsOperandsSwapped) +SIMD_AS_HWINTRINSIC_ID(VectorT128, As, 1, {NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As, NI_VectorT128_As}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT128, Ceiling, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_SSE41_Ceiling, NI_SSE41_Ceiling}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT128, ConditionalSelect, 3, {NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect, NI_VectorT128_ConditionalSelect}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(VectorT128, CreateBroadcast, ".ctor", 2, {NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast, NI_VectorT128_CreateBroadcast}, SimdAsHWIntrinsicFlag::InstanceMethod) @@ -138,6 +139,7 @@ SIMD_AS_HWINTRINSIC_ID(VectorT128, SquareRoot, // Vector Intrinsics SIMD_AS_HWINTRINSIC_ID(VectorT256, Abs, 1, {NI_AVX2_Abs, NI_VectorT256_Abs, NI_AVX2_Abs, NI_VectorT256_Abs, NI_AVX2_Abs, NI_VectorT256_Abs, NI_VectorT256_Abs, NI_VectorT256_Abs, NI_VectorT256_Abs, NI_VectorT256_Abs}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT256, AndNot, 2, {NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX2_AndNot, NI_AVX_AndNot, NI_AVX_AndNot}, SimdAsHWIntrinsicFlag::NeedsOperandsSwapped) +SIMD_AS_HWINTRINSIC_ID(VectorT256, As, 1, {NI_VectorT256_As, NI_VectorT256_As, NI_VectorT256_As, NI_VectorT256_As, NI_VectorT256_As, NI_VectorT256_As, NI_VectorT256_As, NI_VectorT256_As, NI_VectorT256_As, NI_VectorT256_As}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT256, Ceiling, 1, {NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_Illegal, NI_AVX_Ceiling, NI_AVX_Ceiling}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_ID(VectorT256, ConditionalSelect, 3, {NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect, NI_VectorT256_ConditionalSelect}, SimdAsHWIntrinsicFlag::None) SIMD_AS_HWINTRINSIC_NM(VectorT256, CreateBroadcast, ".ctor", 2, {NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast, NI_VectorT256_CreateBroadcast}, SimdAsHWIntrinsicFlag::InstanceMethod) From 58e2ff5f2dff40ab922d813d3dab2dd83ff760ec Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 20 Jan 2021 16:07:18 +0800 Subject: [PATCH 05/10] Hwintrinsic impl --- src/coreclr/jit/simdashwintrinsic.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index f4f9ec906c783a..6caeb826c9f26a 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -405,6 +405,21 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, } #endif // TARGET_X86 +#if defined(TARGET_XARCH) + case NI_VectorT256_As: +#endif // TARGET_XARCH + case NI_VectorT128_As: + { + unsigned retSimdSize; + var_types retBaseType = getBaseTypeAndSizeOfSIMDType(sig->retTypeSigClass, &retSimdSize); + + if (!varTypeIsArithmetic(retBaseType) || (retSimdSize == 0)) + { + // We get here if the return type is an unsupported type + return nullptr; + } + } + case NI_VectorT128_Dot: { if (!compOpportunisticallyDependsOn(InstructionSet_SSE41)) @@ -563,10 +578,10 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, { assert(newobjThis == nullptr); - bool isOpExplicit = (intrinsic == NI_VectorT128_op_Explicit); + bool isOpExplicit = (intrinsic == NI_VectorT128_op_Explicit) || (intrinsic == NI_VectorT128_As); #if defined(TARGET_XARCH) - isOpExplicit |= (intrinsic == NI_VectorT256_op_Explicit); + isOpExplicit |= (intrinsic == NI_VectorT256_op_Explicit) || (intrinsic == NI_VectorT256_As); #endif if (isOpExplicit) From 52e6b10d2b6984365e1f53c7600f392e07daedd6 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 20 Jan 2021 22:21:29 +0800 Subject: [PATCH 06/10] Add missing break. --- src/coreclr/jit/simdashwintrinsic.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 6caeb826c9f26a..2f9c85ee4bd0c4 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -418,6 +418,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, // We get here if the return type is an unsupported type return nullptr; } + break; } case NI_VectorT128_Dot: From 6ebb89dae9b5de4317e65aafc75ec856bc8d00a6 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 22 Jan 2021 15:14:07 +0800 Subject: [PATCH 07/10] Make extension method. --- .../System.Numerics.Vectors/ref/System.Numerics.Vectors.cs | 2 +- .../System.Private.CoreLib/src/System/Numerics/Vector.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs index 31be248fd1df05..7ee9ee3c623aaa 100644 --- a/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs +++ b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs @@ -192,7 +192,7 @@ public static partial class Vector public static System.Numerics.Vector Abs(System.Numerics.Vector value) where T : struct { throw null; } public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) where T : struct { throw null; } public static System.Numerics.Vector AndNot(System.Numerics.Vector left, System.Numerics.Vector right) where T : struct { throw null; } - public static System.Numerics.Vector As(System.Numerics.Vector vector) where TFrom : struct where TTo : struct { throw null; } + public static System.Numerics.Vector As(this System.Numerics.Vector vector) where TFrom : struct where TTo : struct { throw null; } public static System.Numerics.Vector AsVectorByte(System.Numerics.Vector value) where T : struct { throw null; } public static System.Numerics.Vector AsVectorDouble(System.Numerics.Vector value) where T : struct { throw null; } public static System.Numerics.Vector AsVectorInt16(System.Numerics.Vector value) where T : struct { throw null; } 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 184d6e0568b9d7..4943bf57216da3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs @@ -1445,7 +1445,7 @@ internal static void ThrowInsufficientNumberOfElementsException(int requiredElem /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector As(Vector vector) + public static Vector As(this Vector vector) where TFrom : struct where TTo : struct { From 13c979c7cb3c4e7219f646929808a2439fd7a3b5 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 25 Jan 2021 17:15:45 +0800 Subject: [PATCH 08/10] Add test for unsupported As types. --- .../tests/GenericVectorUnsupportedTests.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/libraries/System.Numerics.Vectors/tests/GenericVectorUnsupportedTests.cs b/src/libraries/System.Numerics.Vectors/tests/GenericVectorUnsupportedTests.cs index 07448360d46498..6d435a630cc5a3 100644 --- a/src/libraries/System.Numerics.Vectors/tests/GenericVectorUnsupportedTests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/GenericVectorUnsupportedTests.cs @@ -344,5 +344,19 @@ public void ToVectorDoubleTest() Vector vector = default; Assert.Throws(() => (Vector)vector); } + + [Fact] + public void AsFromTest() + { + Vector vector = default; + Assert.Throws(() => vector.As()); + } + + [Fact] + public void AsToTest() + { + Vector vector = default; + Assert.Throws(() => vector.As()); + } } } From a6e021badf696b3c19615c2c07a78251f4e44213 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 26 Jan 2021 18:47:39 +0800 Subject: [PATCH 09/10] Add test for op_explicit and cast. --- .../tests/GenericVectorTests.cs | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs b/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs index 0d510ae80b9f51..7031a7341f4537 100644 --- a/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs @@ -3047,6 +3047,96 @@ public void NarrowDouble() #endregion Narrow / Widen + #region Explicit Cast/As + [Fact] + public void TestCastByteToInt() => TestCastToInt(); + + [Fact] + public void TestCastSByteToInt() => TestCastToInt(); + + [Fact] + public void TestCastInt16ToInt() => TestCastToInt(); + + [Fact] + public void TestCastUInt16ToInt() => TestCastToInt(); + + [Fact] + public void TestCastInt32ToInt() => TestCastToInt(); + + [Fact] + public void TestCastUInt32ToInt() => TestCastToInt(); + + [Fact] + public void TestCastInt64ToInt() => TestCastToInt(); + + [Fact] + public void TestCastUInt64ToInt() => TestCastToInt(); + + [Fact] + public void TestCastSingleToInt() => TestCastToInt(); + + [Fact] + public void TestCastDoubleToInt() => TestCastToInt(); + + private unsafe void TestCastToInt() where T : unmanaged + { + T[] values = GenerateRandomValuesForVector(); + Vector vector1 = new Vector(values); + Vector vector2 = (Vector)vector1; + + var vector1Bytes = new byte[sizeof(T) * Vector.Count]; + vector1.CopyTo(vector1Bytes); + var vector2Bytes = new byte[sizeof(int) * Vector.Count]; + vector2.CopyTo(vector2Bytes); + + Assert.Equal(vector1Bytes, vector2Bytes); + } + + [Fact] + public void TestAsIntToByte() => TestAs(); + + [Fact] + public void TestAsIntToSByte() => TestAs(); + + [Fact] + public void TestAsIntToInt16() => TestAs(); + + [Fact] + public void TestAsIntToUInt16() => TestAs(); + + [Fact] + public void TestAsIntToInt32() => TestAs(); + + [Fact] + public void TestAsIntToUInt32() => TestAs(); + + [Fact] + public void TestAsIntToInt64() => TestAs(); + + [Fact] + public void TestAsIntToUInt64() => TestAs(); + + [Fact] + public void TestAsIntToSingle() => TestAs(); + + [Fact] + public void TestAsIntToDouble() => TestAs(); + + private unsafe void TestAs() where TFrom : unmanaged where TTo : unmanaged + { + TFrom[] values = GenerateRandomValuesForVector(); + Vector vector1 = new Vector(values); + Vector vector2 = vector1.As(); + + var vector1Bytes = new byte[sizeof(TFrom) * Vector.Count]; + vector1.CopyTo(vector1Bytes); + var vector2Bytes = new byte[sizeof(TTo) * Vector.Count]; + vector2.CopyTo(vector2Bytes); + + Assert.Equal(vector1Bytes, vector2Bytes); + } + #endregion + #region Helper Methods private static void AssertEqual(T expected, T actual, string operation, int precision = -1) where T : IEquatable { From 8f3078f07e0e884c9a9b111e8c3cbd238f523c32 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 3 Feb 2021 02:24:17 +0800 Subject: [PATCH 10/10] Reorder intrinsic checks. --- src/coreclr/jit/simdashwintrinsic.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 2f9c85ee4bd0c4..d50def6863f45d 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -388,6 +388,15 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, // We should have already exited early if SSE2 isn't supported assert(compIsaSupportedDebugOnly(InstructionSet_SSE2)); + // Vector, when 32-bytes, requires at least AVX2 + assert(!isVectorT256 || compIsaSupportedDebugOnly(InstructionSet_AVX2)); +#elif defined(TARGET_ARM64) + // We should have already exited early if AdvSimd isn't supported + assert(compIsaSupportedDebugOnly(InstructionSet_AdvSimd)); +#else +#error Unsupported platform +#endif // !TARGET_XARCH && !TARGET_ARM64 + switch (intrinsic) { #if defined(TARGET_X86) @@ -421,6 +430,7 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, break; } +#if defined(TARGET_XARCH) case NI_VectorT128_Dot: { if (!compOpportunisticallyDependsOn(InstructionSet_SSE41)) @@ -433,23 +443,15 @@ GenTree* Compiler::impSimdAsHWIntrinsicSpecial(NamedIntrinsic intrinsic, } break; } +#endif // TARGET_XARCH default: { - // Most intrinsics have some path that works even if only SSE2 is available + // Most intrinsics have some path that works even if only SSE2/AdvSimd is available break; } } - // Vector, when 32-bytes, requires at least AVX2 - assert(!isVectorT256 || compIsaSupportedDebugOnly(InstructionSet_AVX2)); -#elif defined(TARGET_ARM64) - // We should have already exited early if AdvSimd isn't supported - assert(compIsaSupportedDebugOnly(InstructionSet_AdvSimd)); -#else -#error Unsupported platform -#endif // !TARGET_XARCH && !TARGET_ARM64 - GenTree* copyBlkDst = nullptr; GenTree* copyBlkSrc = nullptr;