Fix StaticCast with NotSupportedException
authorFei Peng <fei.peng@intel.com>
Wed, 28 Feb 2018 06:18:06 +0000 (22:18 -0800)
committerFei Peng <fei.peng@intel.com>
Wed, 28 Feb 2018 06:18:06 +0000 (22:18 -0800)
src/jit/hwintrinsicxarch.cpp
src/jit/simd.cpp
src/mscorlib/src/System/Runtime/Intrinsics/X86/Avx.cs
src/mscorlib/src/System/Runtime/Intrinsics/X86/Avx2.cs
src/mscorlib/src/System/Runtime/Intrinsics/X86/Sse.cs
src/mscorlib/src/System/Runtime/Intrinsics/X86/Sse2.cs
tests/src/JIT/HardwareIntrinsics/X86/Sse/StaticCast.cs

index 3b6ef76..612bc7c 100644 (file)
@@ -426,7 +426,7 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic        intrinsic,
         unsigned int sizeBytes;
         baseType = getBaseTypeAndSizeOfSIMDType(sig->retTypeSigClass, &sizeBytes);
         retType  = getSIMDTypeForSize(sizeBytes);
-        assert(sizeBytes != 0 && baseType != TYP_UNKNOWN);
+        assert(sizeBytes != 0);
     }
 
     // This intrinsic is supported if
@@ -460,25 +460,19 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic        intrinsic,
 
     if ((flags & (HW_Flag_OneTypeGeneric | HW_Flag_TwoTypeGeneric)) != 0)
     {
-        assert(baseType != TYP_UNKNOWN);
-        // When the type argument is not a numeric type (and we are not being forced to expand), we need to
-        // return nullptr so a GT_CALL to the intrinsic method is emitted that will throw NotSupportedException
         if (!varTypeIsArithmetic(baseType))
         {
-            assert(!mustExpand);
-            return nullptr;
+            return impUnsupportedHWIntrinsic(CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED, method, sig, mustExpand);
         }
 
         if ((flags & HW_Flag_TwoTypeGeneric) != 0)
         {
             // StaticCast<T, U> has two type parameters.
-            assert(!mustExpand);
             assert(numArgs == 1);
             var_types srcType = getBaseTypeOfSIMDType(info.compCompHnd->getArgClass(sig, sig->args));
-            assert(srcType != TYP_UNKNOWN);
             if (!varTypeIsArithmetic(srcType))
             {
-                return nullptr;
+                return impUnsupportedHWIntrinsic(CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED, method, sig, mustExpand);
             }
         }
     }
@@ -493,7 +487,7 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic        intrinsic,
     // table-driven importer of simple intrinsics
     if (impIsTableDrivenHWIntrinsic(category, flags))
     {
-        if (!varTypeIsSIMD(retType) || (flags & HW_Flag_BaseTypeFromArg))
+        if (!varTypeIsSIMD(retType) || ((flags & HW_Flag_BaseTypeFromArg) != 0))
         {
             if (retType != TYP_VOID)
             {
index 62bed5f..56a1e9d 100644 (file)
@@ -707,9 +707,13 @@ var_types Compiler::getBaseTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeHnd, u
             }
         }
 
-        if (simdBaseType != TYP_UNKNOWN && sizeBytes != nullptr)
+        if (sizeBytes != nullptr)
         {
             *sizeBytes = size;
+        }
+
+        if (simdBaseType != TYP_UNKNOWN)
+        {
             setUsesSIMDTypes(true);
         }
     }
index 48ad6cb..37487df 100644 (file)
@@ -285,7 +285,6 @@ namespace System.Runtime.Intrinsics.X86
         /// </summary>
         public static Vector128<T> ExtractVector128<T>(Vector256<T> value, byte index) where T : struct
         {
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<T>();
             return ExtractVector128<T>(value, index);
         }
 
@@ -350,7 +349,6 @@ namespace System.Runtime.Intrinsics.X86
         /// </summary>
         public static Vector256<T> ExtendToVector256<T>(Vector128<T> value) where T : struct
         {
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<T>();
             return ExtendToVector256<T>(value);
         }
 
@@ -375,7 +373,6 @@ namespace System.Runtime.Intrinsics.X86
         /// </summary>
         public static Vector128<T> GetLowerHalf<T>(Vector256<T> value) where T : struct
         {
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<T>();
             return GetLowerHalf<T>(value);
         }
 
@@ -452,7 +449,6 @@ namespace System.Runtime.Intrinsics.X86
         /// </summary>
         public static Vector256<T> Insert<T>(Vector256<T> value, Vector128<T> data, byte index) where T : struct
         {
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<T>();
             return Insert<T>(value, data, index);
         }
 
@@ -781,7 +777,6 @@ namespace System.Runtime.Intrinsics.X86
         /// </summary>
         public static Vector256<T> Permute2x128<T>(Vector256<T> left, Vector256<T> right, byte control) where T : struct
         {
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<T>();
             return Permute2x128<T>(left, right, control);
         }
 
@@ -937,7 +932,6 @@ namespace System.Runtime.Intrinsics.X86
         /// </summary>
         public static Vector256<T> SetAllVector256<T>(T value) where T : struct
         {
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<T>();
             return SetAllVector256<T>(value);
         }
 
@@ -951,7 +945,6 @@ namespace System.Runtime.Intrinsics.X86
         /// </summary>
         public static Vector256<T> SetHighLow<T>(Vector128<T> hi, Vector128<T> lo) where T : struct
         {
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<T>();
             return SetHighLow<T>(hi, lo);
         }
 
@@ -965,7 +958,6 @@ namespace System.Runtime.Intrinsics.X86
         /// </summary>
         public static Vector256<T> SetZeroVector256<T>() where T : struct
         {
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<T>();
             return SetZeroVector256<T>();
         }
 
@@ -1007,8 +999,6 @@ namespace System.Runtime.Intrinsics.X86
         /// </summary>
         public static Vector256<U> StaticCast<T, U>(Vector256<T> value) where T : struct where U : struct
         {
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<T>();
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<T>();
             return StaticCast<T, U>(value);
         }
 
@@ -1197,7 +1187,6 @@ namespace System.Runtime.Intrinsics.X86
         /// </summary>
         public static bool TestC<T>(Vector256<T> left, Vector256<T> right) where T : struct
         {
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<T>();
             return TestC<T>(left, right);
         }
 
@@ -1222,7 +1211,6 @@ namespace System.Runtime.Intrinsics.X86
         /// </summary>
         public static bool TestNotZAndNotC<T>(Vector256<T> left, Vector256<T> right) where T : struct
         {
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<T>();
             return TestNotZAndNotC<T>(left, right);
         }
 
@@ -1247,7 +1235,6 @@ namespace System.Runtime.Intrinsics.X86
         /// </summary>
         public static bool TestZ<T>(Vector256<T> left, Vector256<T> right) where T : struct
         {
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<T>();
             return TestZ<T>(left, right);
         }
 
@@ -1305,7 +1292,6 @@ namespace System.Runtime.Intrinsics.X86
         /// </summary>
         public static Vector256<T> ZeroExtendToVector256<T>(Vector128<T> value) where T : struct
         {
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<T>();
             return ZeroExtendToVector256<T>(value);
         }
     }
index 0745fac..0b0663b 100644 (file)
@@ -250,7 +250,6 @@ namespace System.Runtime.Intrinsics.X86
         /// </summary>
         public static Vector128<T> BroadcastScalarToVector128<T>(Vector128<T> value) where T : struct
         {
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<T>();
             return BroadcastScalarToVector128<T>(value);
         }
 
@@ -270,7 +269,6 @@ namespace System.Runtime.Intrinsics.X86
         /// </summary>
         public static Vector256<T> BroadcastScalarToVector256<T>(Vector128<T> value) where T : struct
         {
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<T>();
             return BroadcastScalarToVector256<T>(value);
         }
 
index 8b089c8..fa789eb 100644 (file)
@@ -503,8 +503,6 @@ namespace System.Runtime.Intrinsics.X86
         /// </summary>
         public static Vector128<U> StaticCast<T, U>(Vector128<T> value) where T : struct where U : struct
         {
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<T>();
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<U>();
             return StaticCast<T, U>(value);
         }
 
index 50eb8ef..5d1ddf3 100644 (file)
@@ -1073,7 +1073,6 @@ namespace System.Runtime.Intrinsics.X86
         /// </summary>
         public static Vector128<T> SetZeroVector128<T>() where T : struct
         {
-            ThrowHelper.ThrowNotSupportedExceptionIfNonNumericType<T>();
             return SetZeroVector128<T>();
         }
 
index 3c541f8..707b9b1 100644 (file)
@@ -11,6 +11,13 @@ using System.Runtime.Intrinsics;
 
 namespace IntelHardwareIntrinsicTest
 {
+    // that it is intentionally designed to be a struct type that meets 
+    // the generic constraint but is not supported by any intrinsics
+    struct Num
+    {
+        public int a;
+    }
+
     class Program
     {
         const int Pass = 100;
@@ -39,12 +46,45 @@ namespace IntelHardwareIntrinsicTest
                         Console.WriteLine();
                         testResult = Fail;
                     }
-                }
-            }
 
+                    // the successful path is the one that catches the exception, so that does nothing, 
+                    // it is the fall-through path that's the error path
+                    try
+                    {
+                        var v = Sse.StaticCast<float, Num>(vf1);
+                        Unsafe.Write(floatTable.outArrayPtr, v);
+                        Console.WriteLine("SSE StaticCast failed on target type test:");
+                        testResult = Fail;
+                    }
+                    catch (System.NotSupportedException)
+                    {
+                    }
 
+                    // the successful path is the one that catches the exception, so that does nothing, 
+                    // it is the fall-through path that's the error path
+                    try
+                    {
+                        var v = TestSrcType();
+                        Unsafe.Write(floatTable.outArrayPtr, v);
+                        Console.WriteLine("SSE StaticCast failed on source type test:");
+                        testResult = Fail;
+                    }
+                    catch (System.NotSupportedException)
+                    {
+                    }
+                }
+            }
+            
             return testResult;
         }
+        
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        static Vector128<int> TestSrcType()
+        {
+            Vector128<Num> v1 = new Vector128<Num>();
+            Vector128<Num> v2 = new Vector128<Num>();
+            return Sse2.Add(Sse.StaticCast<Num, int>(v1), Sse.StaticCast<Num, int>(v2));
+        }
 
         public unsafe struct TestTable<T, U> : IDisposable where T : struct where U : struct
         {