Implement the S.R.I.VectorXXX `get_Zero` and `As` helper methods as JIT intrinsics...
authorTanner Gooding <tagoo@outlook.com>
Wed, 28 Nov 2018 11:52:43 +0000 (03:52 -0800)
committerGitHub <noreply@github.com>
Wed, 28 Nov 2018 11:52:43 +0000 (03:52 -0800)
* Remove ARM64_SIMD_StaticCast intrinsic and the x86 TwoTypeGeneric flag

* Implementing the `S.R.Intrinsic.VectorXXX.As` methods as runtime intrinsics

* Implementing the get_Zero method on the S.R.Intrinsic.VectorXXX types as runtime intrinsics

15 files changed:
src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128_1.cs
src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256_1.cs
src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64_1.cs
src/jit/codegen.h
src/jit/compiler.cpp
src/jit/compiler.h
src/jit/hwintrinsiccodegenxarch.cpp
src/jit/hwintrinsiclistArm64.h
src/jit/hwintrinsiclistxarch.h
src/jit/hwintrinsicxarch.cpp
src/jit/hwintrinsicxarch.h
src/jit/importer.cpp
src/jit/instr.h
src/jit/jitconfigvalues.h
src/jit/namedintrinsiclist.h

index 3f8523a..f3599a9 100644 (file)
@@ -24,6 +24,7 @@ namespace System.Runtime.Intrinsics
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
         public static Vector128<T> Zero
         {
+            [Intrinsic]
             get
             {
                 ThrowIfUnsupportedType();
@@ -88,6 +89,7 @@ namespace System.Runtime.Intrinsics
         /// <typeparam name="U">The type of the vector the current instance should be reinterpreted as.</typeparam>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector128{U}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) or the type of the target (<typeparamref name="U" />) is not supported.</exception>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public Vector128<U> As<U>() where U : struct
         {
@@ -99,54 +101,64 @@ namespace System.Runtime.Intrinsics
         /// <summary>Reinterprets the current instance as a new <see cref="Vector128{byte}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector128{byte}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         public Vector128<byte> AsByte() => As<byte>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector128{double}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector128{double}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         public Vector128<double> AsDouble() => As<double>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector128{short}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector128{short}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         public Vector128<short> AsInt16() => As<short>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector128{int}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector128{int}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         public Vector128<int> AsInt32() => As<int>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector128{long}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector128{long}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         public Vector128<long> AsInt64() => As<long>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector128{sbyte}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector128{sbyte}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         [CLSCompliant(false)]
         public Vector128<sbyte> AsSByte() => As<sbyte>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector128{float}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector128{float}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         public Vector128<float> AsSingle() => As<float>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector128{ushort}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector128{ushort}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         [CLSCompliant(false)]
         public Vector128<ushort> AsUInt16() => As<ushort>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector128{uint}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector128{uint}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         [CLSCompliant(false)]
         public Vector128<uint> AsUInt32() => As<uint>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector128{ulong}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector128{ulong}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         [CLSCompliant(false)]
         public Vector128<ulong> AsUInt64() => As<ulong>();
 
index d040ce9..a86ffb5 100644 (file)
@@ -26,6 +26,7 @@ namespace System.Runtime.Intrinsics
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
         public static Vector256<T> Zero
         {
+            [Intrinsic]
             get
             {
                 ThrowIfUnsupportedType();
@@ -90,6 +91,7 @@ namespace System.Runtime.Intrinsics
         /// <typeparam name="U">The type of the vector the current instance should be reinterpreted as.</typeparam>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector256{U}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) or the type of the target (<typeparamref name="U" />) is not supported.</exception>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public Vector256<U> As<U>() where U : struct
         {
@@ -101,54 +103,64 @@ namespace System.Runtime.Intrinsics
         /// <summary>Reinterprets the current instance as a new <see cref="Vector256{byte}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector256{byte}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         public Vector256<byte> AsByte() => As<byte>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector256{double}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector256{double}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         public Vector256<double> AsDouble() => As<double>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector256{short}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector256{short}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         public Vector256<short> AsInt16() => As<short>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector256{int}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector256{int}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         public Vector256<int> AsInt32() => As<int>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector256{long}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector256{long}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         public Vector256<long> AsInt64() => As<long>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector256{sbyte}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector256{sbyte}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         [CLSCompliant(false)]
         public Vector256<sbyte> AsSByte() => As<sbyte>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector256{float}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector256{float}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         public Vector256<float> AsSingle() => As<float>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector256{ushort}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector256{ushort}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         [CLSCompliant(false)]
         public Vector256<ushort> AsUInt16() => As<ushort>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector256{uint}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector256{uint}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         [CLSCompliant(false)]
         public Vector256<uint> AsUInt32() => As<uint>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector256{ulong}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector256{ulong}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         [CLSCompliant(false)]
         public Vector256<ulong> AsUInt64() => As<ulong>();
 
index 99a1e9e..0bb0286 100644 (file)
@@ -87,6 +87,7 @@ namespace System.Runtime.Intrinsics
         /// <typeparam name="U">The type of the vector the current instance should be reinterpreted as.</typeparam>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector64{U}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) or the type of the target (<typeparamref name="U" />) is not supported.</exception>
+        [Intrinsic]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public Vector64<U> As<U>() where U : struct
         {
@@ -98,54 +99,64 @@ namespace System.Runtime.Intrinsics
         /// <summary>Reinterprets the current instance as a new <see cref="Vector64{byte}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector64{byte}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         public Vector64<byte> AsByte() => As<byte>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector64{double}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector64{double}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         public Vector64<double> AsDouble() => As<double>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector64{short}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector64{short}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         public Vector64<short> AsInt16() => As<short>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector64{int}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector64{int}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         public Vector64<int> AsInt32() => As<int>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector64{long}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector64{long}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         public Vector64<long> AsInt64() => As<long>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector64{sbyte}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector64{sbyte}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         [CLSCompliant(false)]
         public Vector64<sbyte> AsSByte() => As<sbyte>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector64{float}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector64{float}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         public Vector64<float> AsSingle() => As<float>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector64{ushort}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector64{ushort}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         [CLSCompliant(false)]
         public Vector64<ushort> AsUInt16() => As<ushort>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector64{uint}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector64{uint}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         [CLSCompliant(false)]
         public Vector64<uint> AsUInt32() => As<uint>();
 
         /// <summary>Reinterprets the current instance as a new <see cref="Vector64{ulong}" />.</summary>
         /// <returns>The current instance reinterpreted as a new <see cref="Vector64{ulong}" />.</returns>
         /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
+        [Intrinsic]
         [CLSCompliant(false)]
         public Vector64<ulong> AsUInt64() => As<ulong>();
 
index 06670aa..e17633e 100644 (file)
@@ -935,6 +935,7 @@ protected:
     void genHWIntrinsic_R_R_RM_R(GenTreeHWIntrinsic* node, instruction ins);
     void genHWIntrinsic_R_R_R_RM(
         instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, GenTree* op3);
+    void genBaseIntrinsic(GenTreeHWIntrinsic* node);
     void genSSEIntrinsic(GenTreeHWIntrinsic* node);
     void genSSE2Intrinsic(GenTreeHWIntrinsic* node);
     void genSSE41Intrinsic(GenTreeHWIntrinsic* node);
index f394e02..fe42bb0 100644 (file)
@@ -2366,7 +2366,13 @@ static bool configEnableISA(InstructionSet isa)
             }
             __fallthrough;
         case InstructionSet_SSE:
-            return JitConfig.EnableSSE() != 0;
+            if (JitConfig.EnableSSE() == 0)
+            {
+                return false;
+            }
+            __fallthrough;
+        case InstructionSet_Base:
+            return (JitConfig.EnableHWIntrinsic() != 0);
 
         // TODO:  BMI1/BMI2 actually don't depend on AVX, they depend on the VEX encoding; which is currently controlled
         // by InstructionSet_AVX
@@ -2434,6 +2440,10 @@ void Compiler::compSetProcessor()
 
     if (!jitFlags.IsSet(JitFlags::JIT_FLAG_PREJIT))
     {
+        if (configEnableISA(InstructionSet_Base))
+        {
+            opts.setSupportedISA(InstructionSet_Base);
+        }
         if (configEnableISA(InstructionSet_SSE))
         {
             opts.setSupportedISA(InstructionSet_SSE);
index b973e11..3ac8b9c 100644 (file)
@@ -3407,6 +3407,7 @@ protected:
     NamedIntrinsic lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method);
 
 #ifdef FEATURE_HW_INTRINSICS
+    GenTree* impBaseIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
     GenTree* impHWIntrinsic(NamedIntrinsic        intrinsic,
                             CORINFO_METHOD_HANDLE method,
                             CORINFO_SIG_INFO*     sig,
index 67d8c52..919b4e8 100644 (file)
@@ -302,6 +302,9 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
 
     switch (isa)
     {
+        case InstructionSet_Base:
+            genBaseIntrinsic(node);
+            break;
         case InstructionSet_SSE:
             genSSEIntrinsic(node);
             break;
@@ -1231,6 +1234,56 @@ void CodeGen::genHWIntrinsicJumpTableFallback(NamedIntrinsic            intrinsi
 }
 
 //------------------------------------------------------------------------
+// genBaseIntrinsic: Generates the code for a base hardware intrinsic node
+//
+// Arguments:
+//    node - The hardware intrinsic node
+//
+void CodeGen::genBaseIntrinsic(GenTreeHWIntrinsic* node)
+{
+    NamedIntrinsic intrinsicId = node->gtHWIntrinsicId;
+    regNumber      targetReg   = node->gtRegNum;
+    var_types      targetType  = node->TypeGet();
+    var_types      baseType    = node->gtSIMDBaseType;
+
+    assert(node->gtGetOp1() == nullptr);
+    assert(node->gtGetOp2() == nullptr);
+    assert(baseType >= TYP_BYTE && baseType <= TYP_DOUBLE);
+
+    emitter* emit = getEmitter();
+    emitAttr attr = EA_ATTR(node->gtSIMDSize);
+
+    switch (intrinsicId)
+    {
+        case NI_Base_Vector128_Zero:
+        {
+            // When SSE2 is supported, we generate pxor for integral types otherwise just use xorps
+            instruction ins =
+                (compiler->compSupports(InstructionSet_SSE2) && varTypeIsIntegral(baseType)) ? INS_pxor : INS_xorps;
+            emit->emitIns_SIMD_R_R_R(ins, attr, targetReg, targetReg, targetReg);
+            break;
+        }
+
+        case NI_Base_Vector256_Zero:
+        {
+            // When AVX2 is supported, we generate pxor for integral types otherwise just use xorps
+            instruction ins =
+                (compiler->compSupports(InstructionSet_AVX2) && varTypeIsIntegral(baseType)) ? INS_pxor : INS_xorps;
+            emit->emitIns_SIMD_R_R_R(ins, attr, targetReg, targetReg, targetReg);
+            break;
+        }
+
+        default:
+        {
+            unreached();
+            break;
+        }
+    }
+
+    genProduceReg(node);
+}
+
+//------------------------------------------------------------------------
 // genSSEIntrinsic: Generates the code for an SSE hardware intrinsic node
 //
 // Arguments:
index ffc8d39..3a2ae3a 100644 (file)
@@ -41,6 +41,24 @@ HARDWARE_INTRINSIC(NI_ARM64_NONE_MOV,             None,     None,
 //  Base
 HARDWARE_INTRINSIC(NI_ARM64_BASE_CLS,             Base,     LeadingSignCount,               UnaryOp,       INS_invalid, INS_cls,     INS_cls,      None )
 HARDWARE_INTRINSIC(NI_ARM64_BASE_CLZ,             Base,     LeadingZeroCount,               UnaryOp,       INS_invalid, INS_clz,     INS_clz,      None )
+HARDWARE_INTRINSIC(NI_Base_Vector64_AsByte,       Base,     AsByte,                         UnaryOp,       INS_invalid, INS_invalid, INS_invalid,  None )
+HARDWARE_INTRINSIC(NI_Base_Vector64_AsInt16,      Base,     AsInt16,                        UnaryOp,       INS_invalid, INS_invalid, INS_invalid,  None )
+HARDWARE_INTRINSIC(NI_Base_Vector64_AsInt32,      Base,     AsInt32,                        UnaryOp,       INS_invalid, INS_invalid, INS_invalid,  None )
+HARDWARE_INTRINSIC(NI_Base_Vector64_AsSByte,      Base,     AsSByte,                        UnaryOp,       INS_invalid, INS_invalid, INS_invalid,  None )
+HARDWARE_INTRINSIC(NI_Base_Vector64_AsSingle,     Base,     AsSingle,                       UnaryOp,       INS_invalid, INS_invalid, INS_invalid,  None )
+HARDWARE_INTRINSIC(NI_Base_Vector64_AsUInt16,     Base,     AsUInt16,                       UnaryOp,       INS_invalid, INS_invalid, INS_invalid,  None )
+HARDWARE_INTRINSIC(NI_Base_Vector64_AsUInt32,     Base,     AsUInt32,                       UnaryOp,       INS_invalid, INS_invalid, INS_invalid,  None )
+HARDWARE_INTRINSIC(NI_Base_Vector128_As,          Base,     As,                             UnaryOp,       INS_invalid, INS_invalid, INS_invalid,  None )
+HARDWARE_INTRINSIC(NI_Base_Vector128_AsByte,      Base,     AsByte,                         UnaryOp,       INS_invalid, INS_invalid, INS_invalid,  None )
+HARDWARE_INTRINSIC(NI_Base_Vector128_AsDouble,    Base,     AsDouble,                       UnaryOp,       INS_invalid, INS_invalid, INS_invalid,  None )
+HARDWARE_INTRINSIC(NI_Base_Vector128_AsInt16,     Base,     AsInt16,                        UnaryOp,       INS_invalid, INS_invalid, INS_invalid,  None )
+HARDWARE_INTRINSIC(NI_Base_Vector128_AsInt32,     Base,     AsInt32,                        UnaryOp,       INS_invalid, INS_invalid, INS_invalid,  None )
+HARDWARE_INTRINSIC(NI_Base_Vector128_AsInt64,     Base,     AsInt64,                        UnaryOp,       INS_invalid, INS_invalid, INS_invalid,  None )
+HARDWARE_INTRINSIC(NI_Base_Vector128_AsSByte,     Base,     AsSByte,                        UnaryOp,       INS_invalid, INS_invalid, INS_invalid,  None )
+HARDWARE_INTRINSIC(NI_Base_Vector128_AsSingle,    Base,     AsSingle,                       UnaryOp,       INS_invalid, INS_invalid, INS_invalid,  None )
+HARDWARE_INTRINSIC(NI_Base_Vector128_AsUInt16,    Base,     AsUInt16,                       UnaryOp,       INS_invalid, INS_invalid, INS_invalid,  None )
+HARDWARE_INTRINSIC(NI_Base_Vector128_AsUInt32,    Base,     AsUInt32,                       UnaryOp,       INS_invalid, INS_invalid, INS_invalid,  None )
+HARDWARE_INTRINSIC(NI_Base_Vector128_AsUInt64,    Base,     AsUInt64,                       UnaryOp,       INS_invalid, INS_invalid, INS_invalid,  None )
 #if NYI
 // Crc32
 HARDWARE_INTRINSIC(NI_ARM64_CRC32_CRC32,          Crc32,    Crc32,                          CrcOp,         INS_invalid, INS_invalid, INS_crc32,    None )
@@ -74,7 +92,6 @@ HARDWARE_INTRINSIC(NI_ARM64_SIMD_Max,             Simd,     Max,
 HARDWARE_INTRINSIC(NI_ARM64_SIMD_Min,             Simd,     Min,                            SimdBinaryOp,  INS_fmin,    INS_smin,    INS_umin,     None )
 HARDWARE_INTRINSIC(NI_ARM64_SIMD_Mul,             Simd,     Multiply,                       SimdBinaryOp,  INS_fmul,    INS_mul,     INS_mul,      None )
 HARDWARE_INTRINSIC(NI_ARM64_SIMD_Sqrt,            Simd,     Sqrt,                           SimdUnaryOp,   INS_fsqrt,   INS_invalid, INS_invalid,  None )
-HARDWARE_INTRINSIC(NI_ARM64_SIMD_StaticCast,      Simd,     StaticCast,                     SimdUnaryOp,   INS_mov,     INS_mov,     INS_mov,      None )
 HARDWARE_INTRINSIC(NI_ARM64_SIMD_Sub,             Simd,     Subtract,                       SimdBinaryOp,  INS_fsub,    INS_sub,     INS_sub,      None )
 HARDWARE_INTRINSIC(NI_ARM64_SIMD_GetItem,         Simd,     Extract,                        SimdExtractOp, INS_mov,     INS_mov,     INS_mov,      None )
 HARDWARE_INTRINSIC(NI_ARM64_SIMD_SetItem,         Simd,     Insert,                         SimdInsertOp,  INS_mov,     INS_mov,     INS_mov,      None )
index 2867898..08fc125 100644 (file)
     8) Each intrinsic has one category with type of `enum HWIntrinsicCategory`, please see the definition of HWIntrinsicCategory for details
     9) Each intrinsic has one or more flags with type of `enum HWIntrinsicFlag`
 */
+// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
+//                 Intrinsic ID                                     Function name                                   ISA         ival        SIMD size       NumArg                                                                                                     instructions                                                                                                     Category                            Flags
+//                                                                                                                                                                      {TYP_BYTE,              TYP_UBYTE,          TYP_SHORT,          TYP_USHORT,         TYP_INT,            TYP_UINT,           TYP_LONG,           TYP_ULONG,          TYP_FLOAT,          TYP_DOUBLE}
+// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
+//  Base Intrinsics
+HARDWARE_INTRINSIC(Base_Vector128_As,                               "As`1",                                        Base,          -1,              16,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector128_AsByte,                           "AsByte",                                      Base,          -1,              16,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector128_AsDouble,                         "AsDouble",                                    Base,          -1,              16,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector128_AsInt16,                          "AsInt16",                                     Base,          -1,              16,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector128_AsInt32,                          "AsInt32",                                     Base,          -1,              16,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector128_AsInt64,                          "AsInt64",                                     Base,          -1,              16,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector128_AsSByte,                          "AsSByte",                                     Base,          -1,              16,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector128_AsSingle,                         "AsSingle",                                    Base,          -1,              16,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector128_AsUInt16,                         "AsUInt16",                                    Base,          -1,              16,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector128_AsUInt32,                         "AsUInt32",                                    Base,          -1,              16,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector128_AsUInt64,                         "AsUInt64",                                    Base,          -1,              16,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector128_Zero,                             "get_Zero",                                    Base,          -1,              16,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector256_As,                               "As`1",                                        Base,          -1,              32,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector256_AsByte,                           "AsByte",                                      Base,          -1,              32,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector256_AsDouble,                         "AsDouble",                                    Base,          -1,              32,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector256_AsInt16,                          "AsInt16",                                     Base,          -1,              32,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector256_AsInt32,                          "AsInt32",                                     Base,          -1,              32,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector256_AsInt64,                          "AsInt64",                                     Base,          -1,              32,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector256_AsSByte,                          "AsSByte",                                     Base,          -1,              32,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector256_AsSingle,                         "AsSingle",                                    Base,          -1,              32,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector256_AsUInt16,                         "AsUInt16",                                    Base,          -1,              32,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector256_AsUInt32,                         "AsUInt32",                                    Base,          -1,              32,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector256_AsUInt64,                         "AsUInt64",                                    Base,          -1,              32,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(Base_Vector256_Zero,                             "get_Zero",                                    Base,          -1,              32,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_Helper,                 HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
 
 // ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
 //                 Intrinsic ID                                     Function name                                   ISA         ival        SIMD size       NumArg                                                                                                     instructions                                                                                                     Category                            Flags
index 09ae92f..7a7c689 100644 (file)
@@ -788,24 +788,12 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic        intrinsic,
         }
     }
 
-    if ((HWIntrinsicInfo::IsOneTypeGeneric(intrinsic) || HWIntrinsicInfo::IsTwoTypeGeneric(intrinsic)) &&
-        !HWIntrinsicInfo::HasSpecialImport(intrinsic))
+    if (HWIntrinsicInfo::IsOneTypeGeneric(intrinsic) && !HWIntrinsicInfo::HasSpecialImport(intrinsic))
     {
         if (!varTypeIsArithmetic(baseType))
         {
             return impUnsupportedHWIntrinsic(CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED, method, sig, mustExpand);
         }
-
-        if (HWIntrinsicInfo::IsTwoTypeGeneric(intrinsic))
-        {
-            // StaticCast<T, U> has two type parameters.
-            assert(numArgs == 1);
-            var_types srcType = getBaseTypeOfSIMDType(info.compCompHnd->getArgClass(sig, sig->args));
-            if (!varTypeIsArithmetic(srcType))
-            {
-                return impUnsupportedHWIntrinsic(CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED, method, sig, mustExpand);
-            }
-        }
     }
 
     if (HWIntrinsicInfo::IsFloatingPointUsed(intrinsic))
index 039543f..19d2d22 100644 (file)
@@ -60,9 +60,6 @@ enum HWIntrinsicFlag : unsigned int
     // Generic
     // - must throw NotSupportException if the type argument is not numeric type
     HW_Flag_OneTypeGeneric = 0x4,
-    // Two-type Generic
-    // - the intrinsic has two type parameters
-    HW_Flag_TwoTypeGeneric = 0x8,
 
     // NoCodeGen
     // - should be transformed in the compiler front-end, cannot reach CodeGen
@@ -225,12 +222,6 @@ struct HWIntrinsicInfo
         return (flags & HW_Flag_OneTypeGeneric) != 0;
     }
 
-    static bool IsTwoTypeGeneric(NamedIntrinsic id)
-    {
-        HWIntrinsicFlag flags = lookupFlags(id);
-        return (flags & HW_Flag_TwoTypeGeneric) != 0;
-    }
-
     static bool RequiresCodegen(NamedIntrinsic id)
     {
         HWIntrinsicFlag flags = lookupFlags(id);
index 6062511..371d277 100644 (file)
@@ -3422,7 +3422,54 @@ GenTree* Compiler::impIntrinsic(GenTree*                newobjThis,
             ni = lookupNamedIntrinsic(method);
 
 #ifdef FEATURE_HW_INTRINSICS
-            if (ni > NI_HW_INTRINSIC_START && ni < NI_HW_INTRINSIC_END)
+            switch (ni)
+            {
+#if defined(_TARGET_ARM64_)
+                case NI_Base_Vector64_AsByte:
+                case NI_Base_Vector64_AsInt16:
+                case NI_Base_Vector64_AsInt32:
+                case NI_Base_Vector64_AsSByte:
+                case NI_Base_Vector64_AsSingle:
+                case NI_Base_Vector64_AsUInt16:
+                case NI_Base_Vector64_AsUInt32:
+#endif // _TARGET_ARM64_
+                case NI_Base_Vector128_As:
+                case NI_Base_Vector128_AsByte:
+                case NI_Base_Vector128_AsDouble:
+                case NI_Base_Vector128_AsInt16:
+                case NI_Base_Vector128_AsInt32:
+                case NI_Base_Vector128_AsInt64:
+                case NI_Base_Vector128_AsSByte:
+                case NI_Base_Vector128_AsSingle:
+                case NI_Base_Vector128_AsUInt16:
+                case NI_Base_Vector128_AsUInt32:
+                case NI_Base_Vector128_AsUInt64:
+#if defined(_TARGET_XARCH_)
+                case NI_Base_Vector128_Zero:
+                case NI_Base_Vector256_As:
+                case NI_Base_Vector256_AsByte:
+                case NI_Base_Vector256_AsDouble:
+                case NI_Base_Vector256_AsInt16:
+                case NI_Base_Vector256_AsInt32:
+                case NI_Base_Vector256_AsInt64:
+                case NI_Base_Vector256_AsSByte:
+                case NI_Base_Vector256_AsSingle:
+                case NI_Base_Vector256_AsUInt16:
+                case NI_Base_Vector256_AsUInt32:
+                case NI_Base_Vector256_AsUInt64:
+                case NI_Base_Vector256_Zero:
+#endif // _TARGET_XARCH_
+                {
+                    return impBaseIntrinsic(ni, method, sig);
+                }
+
+                default:
+                {
+                    break;
+                }
+            }
+
+            if ((ni > NI_HW_INTRINSIC_START) && (ni < NI_HW_INTRINSIC_END))
             {
                 GenTree* hwintrinsic = impHWIntrinsic(ni, method, sig, mustExpand);
 
@@ -4045,6 +4092,125 @@ GenTree* Compiler::impIntrinsic(GenTree*                newobjThis,
     return retNode;
 }
 
+#ifdef FEATURE_HW_INTRINSICS
+//------------------------------------------------------------------------
+// impBaseIntrinsic: dispatch intrinsics to their own implementation
+//
+// Arguments:
+//    intrinsic  -- id of the intrinsic function.
+//    method     -- method handle of the intrinsic function.
+//    sig        -- signature of the intrinsic call
+//
+// Return Value:
+//    the expanded intrinsic.
+//
+GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
+{
+    GenTree*  retNode  = nullptr;
+    unsigned  simdSize = 0;
+    var_types baseType = getBaseTypeAndSizeOfSIMDType(sig->retTypeClass, &simdSize);
+    var_types retType  = getSIMDTypeForSize(simdSize);
+
+    if (sig->hasThis())
+    {
+        CORINFO_CLASS_HANDLE thisClass = info.compCompHnd->getArgClass(sig, sig->args);
+        var_types            thisType  = getBaseTypeOfSIMDType(thisClass);
+
+        if (!varTypeIsArithmetic(thisType))
+        {
+            return nullptr;
+        }
+    }
+
+    if (!varTypeIsArithmetic(baseType))
+    {
+        return nullptr;
+    }
+
+    switch (intrinsic)
+    {
+#if defined(_TARGET_ARM64_)
+        case NI_Base_Vector64_AsByte:
+        case NI_Base_Vector64_AsInt16:
+        case NI_Base_Vector64_AsInt32:
+        case NI_Base_Vector64_AsSByte:
+        case NI_Base_Vector64_AsSingle:
+        case NI_Base_Vector64_AsUInt16:
+        case NI_Base_Vector64_AsUInt32:
+#endif // _TARGET_ARM64_
+        case NI_Base_Vector128_As:
+        case NI_Base_Vector128_AsByte:
+        case NI_Base_Vector128_AsDouble:
+        case NI_Base_Vector128_AsInt16:
+        case NI_Base_Vector128_AsInt32:
+        case NI_Base_Vector128_AsInt64:
+        case NI_Base_Vector128_AsSByte:
+        case NI_Base_Vector128_AsSingle:
+        case NI_Base_Vector128_AsUInt16:
+        case NI_Base_Vector128_AsUInt32:
+        case NI_Base_Vector128_AsUInt64:
+#if defined(_TARGET_XARCH_)
+        case NI_Base_Vector256_As:
+        case NI_Base_Vector256_AsByte:
+        case NI_Base_Vector256_AsDouble:
+        case NI_Base_Vector256_AsInt16:
+        case NI_Base_Vector256_AsInt32:
+        case NI_Base_Vector256_AsInt64:
+        case NI_Base_Vector256_AsSByte:
+        case NI_Base_Vector256_AsSingle:
+        case NI_Base_Vector256_AsUInt16:
+        case NI_Base_Vector256_AsUInt32:
+        case NI_Base_Vector256_AsUInt64:
+#endif // _TARGET_XARCH_
+        {
+            // We fold away the cast here, as it only exists to satisfy
+            // the type system. It is safe to do this here since the retNode type
+            // and the signature return type are both the same TYP_SIMD.
+
+            assert(sig->numArgs == 0);
+            assert(sig->hasThis());
+
+            retNode = impSIMDPopStack(retType, true, sig->retTypeClass);
+            SetOpLclRelatedToSIMDIntrinsic(retNode);
+            assert(retNode->gtType == getSIMDTypeForSize(getSIMDTypeSizeInBytes(sig->retTypeSigClass)));
+            break;
+        }
+
+#ifdef _TARGET_XARCH_
+        case NI_Base_Vector128_Zero:
+        {
+            assert(sig->numArgs == 0);
+
+            if (compSupports(InstructionSet_SSE))
+            {
+                retNode = gtNewSimdHWIntrinsicNode(retType, intrinsic, baseType, simdSize);
+            }
+            break;
+        }
+
+        case NI_Base_Vector256_Zero:
+        {
+            assert(sig->numArgs == 0);
+
+            if (compSupports(InstructionSet_AVX))
+            {
+                retNode = gtNewSimdHWIntrinsicNode(retType, intrinsic, baseType, simdSize);
+            }
+            break;
+        }
+#endif // _TARGET_XARCH_
+
+        default:
+        {
+            unreached();
+            break;
+        }
+    }
+
+    return retNode;
+}
+#endif // FEATURE_HW_INTRINSICS
+
 GenTree* Compiler::impMathIntrinsic(CORINFO_METHOD_HANDLE method,
                                     CORINFO_SIG_INFO*     sig,
                                     var_types             callType,
@@ -4179,21 +4345,207 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method)
             result = NI_System_Collections_Generic_EqualityComparer_get_Default;
         }
     }
-
 #ifdef FEATURE_HW_INTRINSICS
-#if defined(_TARGET_XARCH_)
-    if (strcmp(namespaceName, "System.Runtime.Intrinsics.X86") == 0)
+    else if (strncmp(namespaceName, "System.Runtime.Intrinsics", 25) == 0)
     {
-        result = HWIntrinsicInfo::lookupId(className, methodName);
-    }
+        namespaceName += 25;
+
+        if (namespaceName[0] == '\0')
+        {
+            if (strncmp(className, "Vector", 6) == 0)
+            {
+                className += 6;
+
+#if defined(_TARGET_ARM64_)
+                if (strncmp(className, "64", 2) == 0)
+                {
+                    className += 2;
+
+                    if (strcmp(className, "`1") == 0)
+                    {
+                        if (strncmp(methodName, "As", 2) == 0)
+                        {
+                            methodName += 2;
+
+                            // Vector64_As, Vector64_AsDouble, Vector64_AsInt64, and Vector64_AsUInt64
+                            // are not currently supported as they require additional plumbing to be
+                            // supported by the JIT as TYP_SIMD8.
+
+                            if (strcmp(methodName, "Byte") == 0)
+                            {
+                                result = NI_Base_Vector64_AsByte;
+                            }
+                            else if (strcmp(methodName, "Int16") == 0)
+                            {
+                                result = NI_Base_Vector64_AsInt16;
+                            }
+                            else if (strcmp(methodName, "Int32") == 0)
+                            {
+                                result = NI_Base_Vector64_AsInt32;
+                            }
+                            else if (strcmp(methodName, "SByte") == 0)
+                            {
+                                result = NI_Base_Vector64_AsSByte;
+                            }
+                            else if (strcmp(methodName, "Single") == 0)
+                            {
+                                result = NI_Base_Vector64_AsSingle;
+                            }
+                            else if (strcmp(methodName, "UInt16") == 0)
+                            {
+                                result = NI_Base_Vector64_AsUInt16;
+                            }
+                            else if (strcmp(methodName, "UInt32") == 0)
+                            {
+                                result = NI_Base_Vector64_AsUInt32;
+                            }
+                        }
+                    }
+                }
+                else
+#endif // _TARGET_ARM64_
+                    if (strncmp(className, "128", 3) == 0)
+                {
+                    className += 3;
+
+                    if (strcmp(className, "`1") == 0)
+                    {
+                        if (strncmp(methodName, "As", 2) == 0)
+                        {
+                            methodName += 2;
+
+                            if (strcmp(methodName, "`1") == 0)
+                            {
+                                result = NI_Base_Vector128_As;
+                            }
+                            else if (strcmp(methodName, "Byte") == 0)
+                            {
+                                result = NI_Base_Vector128_AsByte;
+                            }
+                            else if (strcmp(methodName, "Double") == 0)
+                            {
+                                result = NI_Base_Vector128_AsDouble;
+                            }
+                            else if (strcmp(methodName, "Int16") == 0)
+                            {
+                                result = NI_Base_Vector128_AsInt16;
+                            }
+                            else if (strcmp(methodName, "Int32") == 0)
+                            {
+                                result = NI_Base_Vector128_AsInt32;
+                            }
+                            else if (strcmp(methodName, "Int64") == 0)
+                            {
+                                result = NI_Base_Vector128_AsInt64;
+                            }
+                            else if (strcmp(methodName, "SByte") == 0)
+                            {
+                                result = NI_Base_Vector128_AsSByte;
+                            }
+                            else if (strcmp(methodName, "Single") == 0)
+                            {
+                                result = NI_Base_Vector128_AsSingle;
+                            }
+                            else if (strcmp(methodName, "UInt16") == 0)
+                            {
+                                result = NI_Base_Vector128_AsUInt16;
+                            }
+                            else if (strcmp(methodName, "UInt32") == 0)
+                            {
+                                result = NI_Base_Vector128_AsUInt32;
+                            }
+                            else if (strcmp(methodName, "UInt64") == 0)
+                            {
+                                result = NI_Base_Vector128_AsUInt64;
+                            }
+                        }
+#if defined(_TARGET_XARCH_)
+                        else if (strcmp(methodName, "get_Zero") == 0)
+                        {
+                            result = NI_Base_Vector128_Zero;
+                        }
+#endif // _TARGET_XARCH_
+                    }
+                }
+#if defined(_TARGET_XARCH_)
+                else if (strncmp(className, "256", 3) == 0)
+                {
+                    className += 3;
+
+                    if (strcmp(className, "`1") == 0)
+                    {
+                        if (strncmp(methodName, "As", 2) == 0)
+                        {
+                            methodName += 2;
+
+                            if (strcmp(methodName, "`1") == 0)
+                            {
+                                result = NI_Base_Vector256_As;
+                            }
+                            else if (strcmp(methodName, "Byte") == 0)
+                            {
+                                result = NI_Base_Vector256_AsByte;
+                            }
+                            else if (strcmp(methodName, "Double") == 0)
+                            {
+                                result = NI_Base_Vector256_AsDouble;
+                            }
+                            else if (strcmp(methodName, "Int16") == 0)
+                            {
+                                result = NI_Base_Vector256_AsInt16;
+                            }
+                            else if (strcmp(methodName, "Int32") == 0)
+                            {
+                                result = NI_Base_Vector256_AsInt32;
+                            }
+                            else if (strcmp(methodName, "Int64") == 0)
+                            {
+                                result = NI_Base_Vector256_AsInt64;
+                            }
+                            else if (strcmp(methodName, "SByte") == 0)
+                            {
+                                result = NI_Base_Vector256_AsSByte;
+                            }
+                            else if (strcmp(methodName, "Single") == 0)
+                            {
+                                result = NI_Base_Vector256_AsSingle;
+                            }
+                            else if (strcmp(methodName, "UInt16") == 0)
+                            {
+                                result = NI_Base_Vector256_AsUInt16;
+                            }
+                            else if (strcmp(methodName, "UInt32") == 0)
+                            {
+                                result = NI_Base_Vector256_AsUInt32;
+                            }
+                            else if (strcmp(methodName, "UInt64") == 0)
+                            {
+                                result = NI_Base_Vector256_AsUInt64;
+                            }
+                        }
+                        else if (strcmp(methodName, "get_Zero") == 0)
+                        {
+                            result = NI_Base_Vector256_Zero;
+                        }
+                    }
+                }
+#endif // _TARGET_XARCH_
+            }
+        }
+#if defined(_TARGET_XARCH_)
+        else if (strcmp(namespaceName, ".X86") == 0)
+        {
+            result = HWIntrinsicInfo::lookupId(className, methodName);
+        }
 #elif defined(_TARGET_ARM64_)
-    if (strcmp(namespaceName, "System.Runtime.Intrinsics.Arm.Arm64") == 0)
-    {
-        result = lookupHWIntrinsic(className, methodName);
-    }
+        else if (strcmp(namespaceName, ".Arm.Arm64") == 0)
+        {
+            result = lookupHWIntrinsic(className, methodName);
+        }
 #else // !defined(_TARGET_XARCH_) && !defined(_TARGET_ARM64_)
 #error Unsupported platform
 #endif // !defined(_TARGET_XARCH_) && !defined(_TARGET_ARM64_)
+    }
 #endif // FEATURE_HW_INTRINSICS
 
     return result;
index 8d1c221..058bec1 100644 (file)
@@ -296,26 +296,25 @@ enum InstructionSet
 {
     InstructionSet_ILLEGAL = 0,
 #ifdef _TARGET_XARCH_
+    InstructionSet_Base,
     // Start linear order SIMD instruction sets
     // These ISAs have strictly generation to generation order.
-    InstructionSet_SSE     = 1,
-    InstructionSet_SSE2    = 2,
-    InstructionSet_SSE3    = 3,
-    InstructionSet_SSSE3   = 4,
-    InstructionSet_SSE41   = 5,
-    InstructionSet_SSE42   = 6,
-    InstructionSet_AVX     = 7,
-    InstructionSet_AVX2    = 8,
-    // Reserve values <32 for future SIMD instruction sets (i.e., AVX512),
+    InstructionSet_SSE,
+    InstructionSet_SSE2,
+    InstructionSet_SSE3,
+    InstructionSet_SSSE3,
+    InstructionSet_SSE41,
+    InstructionSet_SSE42,
+    InstructionSet_AVX,
+    InstructionSet_AVX2,
     // End linear order SIMD instruction sets.
-
-    InstructionSet_AES     = 32,
-    InstructionSet_BMI1    = 33,
-    InstructionSet_BMI2    = 34,
-    InstructionSet_FMA     = 35,
-    InstructionSet_LZCNT   = 36,
-    InstructionSet_PCLMULQDQ  = 37,
-    InstructionSet_POPCNT  = 38,
+    InstructionSet_AES,
+    InstructionSet_BMI1,
+    InstructionSet_BMI2,
+    InstructionSet_FMA,
+    InstructionSet_LZCNT,
+    InstructionSet_PCLMULQDQ,
+    InstructionSet_POPCNT,
 #elif defined(_TARGET_ARM_)
     InstructionSet_NEON,
 #elif defined(_TARGET_ARM64_)
index f238fee..383264e 100644 (file)
@@ -234,25 +234,26 @@ CONFIG_INTEGER(EnableSSE3_4, W("EnableSSE3_4"), 1) // Enable SSE3, SSSE3, SSE 4.
 #if defined(_TARGET_AMD64_) || defined(_TARGET_X86_)
 // Enable AVX instruction set for wide operations as default. When both AVX and SSE3_4 are set, we will use the most
 // capable instruction set available which will prefer AVX over SSE3/4.
-CONFIG_INTEGER(EnableSSE, W("EnableSSE"), 1)             // Enable SSE
-CONFIG_INTEGER(EnableSSE2, W("EnableSSE2"), 1)           // Enable SSE2
-CONFIG_INTEGER(EnableSSE3, W("EnableSSE3"), 1)           // Enable SSE3
-CONFIG_INTEGER(EnableSSSE3, W("EnableSSSE3"), 1)         // Enable SSSE3
-CONFIG_INTEGER(EnableSSE41, W("EnableSSE41"), 1)         // Enable SSE41
-CONFIG_INTEGER(EnableSSE42, W("EnableSSE42"), 1)         // Enable SSE42
-CONFIG_INTEGER(EnableAVX, W("EnableAVX"), 1)             // Enable AVX
-CONFIG_INTEGER(EnableAVX2, W("EnableAVX2"), 1)           // Enable AVX2
-CONFIG_INTEGER(EnableFMA, W("EnableFMA"), 1)             // Enable FMA
-CONFIG_INTEGER(EnableAES, W("EnableAES"), 1)             // Enable AES
-CONFIG_INTEGER(EnableBMI1, W("EnableBMI1"), 1)           // Enable BMI1
-CONFIG_INTEGER(EnableBMI2, W("EnableBMI2"), 1)           // Enable BMI2
-CONFIG_INTEGER(EnableLZCNT, W("EnableLZCNT"), 1)         // Enable AES
-CONFIG_INTEGER(EnablePCLMULQDQ, W("EnablePCLMULQDQ"), 1) // Enable PCLMULQDQ
-CONFIG_INTEGER(EnablePOPCNT, W("EnablePOPCNT"), 1)       // Enable POPCNT
-#else                                                    // !defined(_TARGET_AMD64_) && !defined(_TARGET_X86_)
+CONFIG_INTEGER(EnableHWIntrinsic, W("EnableHWIntrinsic"), 1) // Enable Base
+CONFIG_INTEGER(EnableSSE, W("EnableSSE"), 1)                 // Enable SSE
+CONFIG_INTEGER(EnableSSE2, W("EnableSSE2"), 1)               // Enable SSE2
+CONFIG_INTEGER(EnableSSE3, W("EnableSSE3"), 1)               // Enable SSE3
+CONFIG_INTEGER(EnableSSSE3, W("EnableSSSE3"), 1)             // Enable SSSE3
+CONFIG_INTEGER(EnableSSE41, W("EnableSSE41"), 1)             // Enable SSE41
+CONFIG_INTEGER(EnableSSE42, W("EnableSSE42"), 1)             // Enable SSE42
+CONFIG_INTEGER(EnableAVX, W("EnableAVX"), 1)                 // Enable AVX
+CONFIG_INTEGER(EnableAVX2, W("EnableAVX2"), 1)               // Enable AVX2
+CONFIG_INTEGER(EnableFMA, W("EnableFMA"), 1)                 // Enable FMA
+CONFIG_INTEGER(EnableAES, W("EnableAES"), 1)                 // Enable AES
+CONFIG_INTEGER(EnableBMI1, W("EnableBMI1"), 1)               // Enable BMI1
+CONFIG_INTEGER(EnableBMI2, W("EnableBMI2"), 1)               // Enable BMI2
+CONFIG_INTEGER(EnableLZCNT, W("EnableLZCNT"), 1)             // Enable AES
+CONFIG_INTEGER(EnablePCLMULQDQ, W("EnablePCLMULQDQ"), 1)     // Enable PCLMULQDQ
+CONFIG_INTEGER(EnablePOPCNT, W("EnablePOPCNT"), 1)           // Enable POPCNT
+#else                                                        // !defined(_TARGET_AMD64_) && !defined(_TARGET_X86_)
 // Enable AVX instruction set for wide operations as default
 CONFIG_INTEGER(EnableAVX, W("EnableAVX"), 0)
-#endif                                                   // !defined(_TARGET_AMD64_) && !defined(_TARGET_X86_)
+#endif                                                       // !defined(_TARGET_AMD64_) && !defined(_TARGET_X86_)
 ///
 /// JIT
 ///
index edf006f..6644a72 100644 (file)
@@ -15,6 +15,7 @@ enum NamedIntrinsic : unsigned short
     NI_Math_Round                                               = 3,
     NI_System_Collections_Generic_EqualityComparer_get_Default  = 4,
     NI_System_Buffers_Binary_BinaryPrimitives_ReverseEndianness = 5,
+
 #ifdef FEATURE_HW_INTRINSICS
     NI_HW_INTRINSIC_START,
 #if defined(_TARGET_XARCH_)