Move down S.N.Vector APIs and expose new conversion support (dotnet/coreclr#27401)
authorTanner Gooding <tagoo@outlook.com>
Thu, 24 Oct 2019 16:01:00 +0000 (09:01 -0700)
committerJan Kotas <jkotas@microsoft.com>
Thu, 24 Oct 2019 16:01:00 +0000 (09:01 -0700)
* Updating S.P.Corelib to start building Vector2/3/4 and supporting types

* Removing HAS_INTRINSICS usages from Matrix4x4

Commit migrated from https://github.com/dotnet/coreclr/commit/72338012f64849a996bf171c9c1b66cc20c64728

src/coreclr/src/tools/crossgen2/Common/Compiler/SimdHelper.cs
src/coreclr/src/vm/jitinterface.cpp
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix4x4.cs
src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs
src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs
src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs
src/libraries/System.Private.CoreLib/src/System/Numerics/VectorMath.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs

index 53f606c..a8550b7 100644 (file)
@@ -34,8 +34,8 @@ namespace ILCompiler
                 if (metadataType.IsIntrinsic)
                 {
                     string name = metadataType.Name;
-                    if ((name == "Vector`1" || name == "Vector") &&
-                        metadataType.Namespace == "System.Numerics")
+                    if (((name == "Vector") || (name == "Vector`1") || (name == "Vector2") || (name == "Vector3") || (name == "Vector4")) &&
+                        (metadataType.Namespace == "System.Numerics"))
                         return true;
                 }
             }
index be32d61..c7588fb 100644 (file)
@@ -8970,11 +8970,15 @@ CONTRACTL {
         LPCUTF8 namespaceName;
         LPCUTF8 className = methodTable->GetFullyQualifiedNameInfo(&namespaceName);
 
-        if (strcmp(className, "Vector`1") == 0 || strcmp(className, "Vector") == 0)
+        if (strncmp(className, "Vector", 6) == 0)
         {
-            assert(strcmp(namespaceName, "System.Numerics") == 0);
+            className += 6;
 
-            result = true;
+            if ((className[0] == '\0') || (strcmp(className, "`1") == 0) || (strcmp(className, "2") == 0) || (strcmp(className, "3") == 0) || (strcmp(className, "4") == 0))
+            {
+                assert(strcmp(namespaceName, "System.Numerics") == 0);
+                result = true;
+            }
         }
     }
     EE_TO_JIT_TRANSITION_LEAF();
index 709ad5f..ccf3d3f 100644 (file)
     <Compile Include="$(MSBuildThisFileDirectory)System\Number.NumberToFloatingPointBits.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Number.Parsing.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\BitOperations.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Matrix3x2.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Matrix4x4.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Plane.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Quaternion.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Vector2.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Vector2_Intrinsics.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Vector3.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Vector3_Intrinsics.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Vector4.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Vector4_Intrinsics.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\VectorMath.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\NullReferenceException.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Object.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\ObjectDisposedException.cs" />
index 4d30615..e391e70 100644 (file)
@@ -4,10 +4,8 @@
 
 using System.Globalization;
 using System.Runtime.InteropServices;
-#if HAS_INTRINSICS
 using System.Runtime.Intrinsics;
 using System.Runtime.Intrinsics.X86;
-#endif
 
 namespace System.Numerics
 {
@@ -1761,7 +1759,6 @@ namespace System.Numerics
         /// <returns>The transposed matrix.</returns>
         public static unsafe Matrix4x4 Transpose(Matrix4x4 matrix)
         {
-#if HAS_INTRINSICS
             if (Sse.IsSupported)
             {
                 var row1 = Sse.LoadVector128(&matrix.M11);
@@ -1781,7 +1778,7 @@ namespace System.Numerics
 
                 return matrix;
             }
-#endif
+
             Matrix4x4 result;
 
             result.M11 = matrix.M11;
@@ -1813,7 +1810,6 @@ namespace System.Numerics
         /// <returns>The interpolated matrix.</returns>
         public static unsafe Matrix4x4 Lerp(Matrix4x4 matrix1, Matrix4x4 matrix2, float amount)
         {
-#if HAS_INTRINSICS
             if (Sse.IsSupported)
             {
                 Vector128<float> amountVec = Vector128.Create(amount);
@@ -1823,7 +1819,7 @@ namespace System.Numerics
                 Sse.Store(&matrix1.M41, VectorMath.Lerp(Sse.LoadVector128(&matrix1.M41), Sse.LoadVector128(&matrix2.M41), amountVec));
                 return matrix1;
             }
-#endif
+
             Matrix4x4 result;
 
             // First row
@@ -1899,7 +1895,6 @@ namespace System.Numerics
         /// <returns>The negated matrix.</returns>
         public static unsafe Matrix4x4 operator -(Matrix4x4 value)
         {
-#if HAS_INTRINSICS
             if (Sse.IsSupported)
             {
                 Vector128<float> zero = Vector128<float>.Zero;
@@ -1910,7 +1905,7 @@ namespace System.Numerics
 
                 return value;
             }
-#endif
+
             Matrix4x4 m;
 
             m.M11 = -value.M11;
@@ -1941,7 +1936,6 @@ namespace System.Numerics
         /// <returns>The resulting matrix.</returns>
         public static unsafe Matrix4x4 operator +(Matrix4x4 value1, Matrix4x4 value2)
         {
-#if HAS_INTRINSICS
             if (Sse.IsSupported)
             {
                 Sse.Store(&value1.M11, Sse.Add(Sse.LoadVector128(&value1.M11), Sse.LoadVector128(&value2.M11)));
@@ -1950,7 +1944,7 @@ namespace System.Numerics
                 Sse.Store(&value1.M41, Sse.Add(Sse.LoadVector128(&value1.M41), Sse.LoadVector128(&value2.M41)));
                 return value1;
             }
-#endif
+
             Matrix4x4 m;
 
             m.M11 = value1.M11 + value2.M11;
@@ -1981,7 +1975,6 @@ namespace System.Numerics
         /// <returns>The result of the subtraction.</returns>
         public static unsafe Matrix4x4 operator -(Matrix4x4 value1, Matrix4x4 value2)
         {
-#if HAS_INTRINSICS
             if (Sse.IsSupported)
             {
                 Sse.Store(&value1.M11, Sse.Subtract(Sse.LoadVector128(&value1.M11), Sse.LoadVector128(&value2.M11)));
@@ -1990,7 +1983,7 @@ namespace System.Numerics
                 Sse.Store(&value1.M41, Sse.Subtract(Sse.LoadVector128(&value1.M41), Sse.LoadVector128(&value2.M41)));
                 return value1;
             }
-#endif
+
             Matrix4x4 m;
 
             m.M11 = value1.M11 - value2.M11;
@@ -2021,7 +2014,6 @@ namespace System.Numerics
         /// <returns>The result of the multiplication.</returns>
         public static unsafe Matrix4x4 operator *(Matrix4x4 value1, Matrix4x4 value2)
         {
-#if HAS_INTRINSICS
             if (Sse.IsSupported)
             {
                 var row = Sse.LoadVector128(&value1.M11);
@@ -2056,7 +2048,7 @@ namespace System.Numerics
                                     Sse.Multiply(Sse.Shuffle(row, row, 0xFF), Sse.LoadVector128(&value2.M41)))));
                 return value1;
             }
-#endif
+
             Matrix4x4 m;
 
             // First row
@@ -2094,7 +2086,6 @@ namespace System.Numerics
         /// <returns>The scaled matrix.</returns>
         public static unsafe Matrix4x4 operator *(Matrix4x4 value1, float value2)
         {
-#if HAS_INTRINSICS
             if (Sse.IsSupported)
             {
                 Vector128<float> value2Vec = Vector128.Create(value2);
@@ -2104,7 +2095,7 @@ namespace System.Numerics
                 Sse.Store(&value1.M41, Sse.Multiply(Sse.LoadVector128(&value1.M41), value2Vec));
                 return value1;
             }
-#endif
+
             Matrix4x4 m;
 
             m.M11 = value1.M11 * value2;
@@ -2134,7 +2125,6 @@ namespace System.Numerics
         /// <returns>True if the given matrices are equal; False otherwise.</returns>
         public static unsafe bool operator ==(Matrix4x4 value1, Matrix4x4 value2)
         {
-#if HAS_INTRINSICS
             if (Sse.IsSupported)
             {
                 return
@@ -2143,7 +2133,7 @@ namespace System.Numerics
                     VectorMath.Equal(Sse.LoadVector128(&value1.M31), Sse.LoadVector128(&value2.M31)) &&
                     VectorMath.Equal(Sse.LoadVector128(&value1.M41), Sse.LoadVector128(&value2.M41));
             }
-#endif
+
             return (value1.M11 == value2.M11 && value1.M22 == value2.M22 && value1.M33 == value2.M33 && value1.M44 == value2.M44 && // Check diagonal element first for early out.
                     value1.M12 == value2.M12 && value1.M13 == value2.M13 && value1.M14 == value2.M14 && value1.M21 == value2.M21 &&
                     value1.M23 == value2.M23 && value1.M24 == value2.M24 && value1.M31 == value2.M31 && value1.M32 == value2.M32 &&
@@ -2158,7 +2148,6 @@ namespace System.Numerics
         /// <returns>True if the given matrices are not equal; False if they are equal.</returns>
         public static unsafe bool operator !=(Matrix4x4 value1, Matrix4x4 value2)
         {
-#if HAS_INTRINSICS
             if (Sse.IsSupported)
             {
                 return
@@ -2167,7 +2156,7 @@ namespace System.Numerics
                     VectorMath.NotEqual(Sse.LoadVector128(&value1.M31), Sse.LoadVector128(&value2.M31)) ||
                     VectorMath.NotEqual(Sse.LoadVector128(&value1.M41), Sse.LoadVector128(&value2.M41));
             }
-#endif
+
             return (value1.M11 != value2.M11 || value1.M12 != value2.M12 || value1.M13 != value2.M13 || value1.M14 != value2.M14 ||
                     value1.M21 != value2.M21 || value1.M22 != value2.M22 || value1.M23 != value2.M23 || value1.M24 != value2.M24 ||
                     value1.M31 != value2.M31 || value1.M32 != value2.M32 || value1.M33 != value2.M33 || value1.M34 != value2.M34 ||
index 868dba3..15cd50f 100644 (file)
@@ -11,6 +11,7 @@ namespace System.Numerics
     /// <summary>
     /// A structure encapsulating two single precision floating point values and provides hardware accelerated methods.
     /// </summary>
+    [Intrinsic]
     public partial struct Vector2 : IEquatable<Vector2>, IFormattable
     {
         #region Public Static Properties
index 5e1994d..7b5ad78 100644 (file)
@@ -11,6 +11,7 @@ namespace System.Numerics
     /// <summary>
     /// A structure encapsulating three single precision floating point values and provides hardware accelerated methods.
     /// </summary>
+    [Intrinsic]
     public partial struct Vector3 : IEquatable<Vector3>, IFormattable
     {
         #region Public Static Properties
index 4f6b343..43f1b96 100644 (file)
@@ -11,6 +11,7 @@ namespace System.Numerics
     /// <summary>
     /// A structure encapsulating four single precision floating point values and provides hardware accelerated methods.
     /// </summary>
+    [Intrinsic]
     public partial struct Vector4 : IEquatable<Vector4>, IFormattable
     {
         #region Public Static Properties
index cec1e3a..0c652c4 100644 (file)
@@ -1,6 +1,7 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
+
 using System.Diagnostics;
 using System.Runtime.Intrinsics;
 using System.Runtime.Intrinsics.X86;
index f0d5aa8..121a1e0 100644 (file)
@@ -2,6 +2,8 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using System.Diagnostics;
+using System.Numerics;
 using System.Runtime.CompilerServices;
 using System.Runtime.Intrinsics.X86;
 using Internal.Runtime.CompilerServices;
@@ -171,6 +173,83 @@ namespace System.Runtime.Intrinsics
             return vector.As<T, ulong>();
         }
 
+        /// <summary>Reinterprets a <see cref="Vector2" /> as a new <see cref="Vector128{Single}" />.</summary>
+        /// <param name="value">The vector to reinterpret.</param>
+        /// <returns><paramref name="value" /> reinterpreted as a new <see cref="Vector128{Single}" />.</returns>
+        public static Vector128<float> AsVector128(this Vector2 value)
+        {
+            return new Vector4(value, 0.0f, 0.0f).AsVector128();
+        }
+
+        /// <summary>Reinterprets a <see cref="Vector3" /> as a new <see cref="Vector128{Single}" />.</summary>
+        /// <param name="value">The vector to reinterpret.</param>
+        /// <returns><paramref name="value" /> reinterpreted as a new <see cref="Vector128{Single}" />.</returns>
+        public static Vector128<float> AsVector128(this Vector3 value)
+        {
+            return new Vector4(value, 0.0f).AsVector128();
+        }
+
+        /// <summary>Reinterprets a <see cref="Vector4" /> as a new <see cref="Vector128{Single}" />.</summary>
+        /// <param name="value">The vector to reinterpret.</param>
+        /// <returns><paramref name="value" /> reinterpreted as a new <see cref="Vector128{Single}" />.</returns>
+        public static Vector128<float> AsVector128(this Vector4 value)
+        {
+            return Unsafe.As<Vector4, Vector128<float>>(ref value);
+        }
+
+        /// <summary>Reinterprets a <see cref="Vector{T}" /> as a new <see cref="Vector128{T}" />.</summary>
+        /// <typeparam name="T">The type of the vectors.</typeparam>
+        /// <param name="value">The vector to reinterpret.</param>
+        /// <returns><paramref name="value" /> reinterpreted as a new <see cref="Vector128{T}" />.</returns>
+        /// <exception cref="NotSupportedException">The type of <paramref name="value" /> (<typeparamref name="T" />) is not supported.</exception>
+        public static Vector128<T> AsVector128<T>(this Vector<T> value)
+            where T : struct
+        {
+            Debug.Assert(Vector<T>.Count >= Vector128<T>.Count);
+            ThrowHelper.ThrowForUnsupportedVectorBaseType<T>();
+            return Unsafe.As<Vector<T>, Vector128<T>>(ref value);
+        }
+
+        /// <summary>Reinterprets a <see cref="Vector128{Single}" /> as a new <see cref="Vector2" />.</summary>
+        /// <param name="value">The vector to reinterpret.</param>
+        /// <returns><paramref name="value" /> reinterpreted as a new <see cref="Vector2" />.</returns>
+        public static Vector2 AsVector2(this Vector128<float> value)
+        {
+            return Unsafe.As<Vector128<float>, Vector2>(ref value);
+        }
+
+        /// <summary>Reinterprets a <see cref="Vector128{Single}" /> as a new <see cref="Vector3" />.</summary>
+        /// <param name="value">The vector to reinterpret.</param>
+        /// <returns><paramref name="value" /> reinterpreted as a new <see cref="Vector3" />.</returns>
+        public static Vector3 AsVector3(this Vector128<float> value)
+        {
+            throw new PlatformNotSupportedException();
+        }
+
+        /// <summary>Reinterprets a <see cref="Vector128{Single}" /> as a new <see cref="Vector4" />.</summary>
+        /// <param name="value">The vector to reinterpret.</param>
+        /// <returns><paramref name="value" /> reinterpreted as a new <see cref="Vector4" />.</returns>
+        public static Vector4 AsVector4(this Vector128<float> value)
+        {
+            return Unsafe.As<Vector128<float>, Vector4>(ref value);
+        }
+
+        /// <summary>Reinterprets a <see cref="Vector128{T}" /> as a new <see cref="Vector{T}" />.</summary>
+        /// <typeparam name="T">The type of the vectors.</typeparam>
+        /// <param name="value">The vector to reinterpret.</param>
+        /// <returns><paramref name="value" /> reinterpreted as a new <see cref="Vector{T}" />.</returns>
+        /// <exception cref="NotSupportedException">The type of <paramref name="value" /> (<typeparamref name="T" />) is not supported.</exception>
+        public static Vector<T> AsVector<T>(this Vector128<T> value)
+            where T : struct
+        {
+            Debug.Assert(Vector<T>.Count >= Vector128<T>.Count);
+            ThrowHelper.ThrowForUnsupportedVectorBaseType<T>();
+
+            Vector<T> result = default;
+            Unsafe.WriteUnaligned(ref Unsafe.As<Vector<T>, byte>(ref result), value);
+            return result;
+        }
+
         /// <summary>Creates a new <see cref="Vector128{Byte}" /> instance with all elements initialized to the specified value.</summary>
         /// <param name="value">The value that all elements will be initialized to.</param>
         /// <returns>A new <see cref="Vector128{Byte}" /> with all elements initialized to <paramref name="value" />.</returns>
index 7443604..53ee749 100644 (file)
@@ -2,6 +2,8 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using System.Diagnostics;
+using System.Numerics;
 using System.Runtime.CompilerServices;
 using System.Runtime.Intrinsics.X86;
 using Internal.Runtime.CompilerServices;
@@ -171,6 +173,35 @@ namespace System.Runtime.Intrinsics
             return vector.As<T, ulong>();
         }
 
+        /// <summary>Reinterprets a <see cref="Vector{T}" /> as a new <see cref="Vector256{T}" />.</summary>
+        /// <typeparam name="T">The type of the vectors.</typeparam>
+        /// <param name="value">The vector to reinterpret.</param>
+        /// <returns><paramref name="value" /> reinterpreted as a new <see cref="Vector256{T}" />.</returns>
+        /// <exception cref="NotSupportedException">The type of <paramref name="value" /> (<typeparamref name="T" />) is not supported.</exception>
+        public static Vector256<T> AsVector256<T>(this Vector<T> value)
+            where T : struct
+        {
+            Debug.Assert(Vector256<T>.Count >= Vector<T>.Count);
+            ThrowHelper.ThrowForUnsupportedVectorBaseType<T>();
+
+            Vector256<T> result = default;
+            Unsafe.WriteUnaligned(ref Unsafe.As<Vector256<T>, byte>(ref result), value);
+            return result;
+        }
+
+        /// <summary>Reinterprets a <see cref="Vector256{T}" /> as a new <see cref="Vector{T}" />.</summary>
+        /// <typeparam name="T">The type of the vectors.</typeparam>
+        /// <param name="value">The vector to reinterpret.</param>
+        /// <returns><paramref name="value" /> reinterpreted as a new <see cref="Vector{T}" />.</returns>
+        /// <exception cref="NotSupportedException">The type of <paramref name="value" /> (<typeparamref name="T" />) is not supported.</exception>
+        public static Vector<T> AsVector<T>(this Vector256<T> value)
+            where T : struct
+        {
+            Debug.Assert(Vector256<T>.Count >= Vector<T>.Count);
+            ThrowHelper.ThrowForUnsupportedVectorBaseType<T>();
+            return Unsafe.As<Vector256<T>, Vector<T>>(ref value);
+        }
+
         /// <summary>Creates a new <see cref="Vector256{Byte}" /> instance with all elements initialized to the specified value.</summary>
         /// <param name="value">The value that all elements will be initialized to.</param>
         /// <returns>A new <see cref="Vector256{Byte}" /> with all elements initialized to <paramref name="value" />.</returns>