Enable hardware intrinsic in debug and reflection
authorFei Peng <fei.peng@intel.com>
Sun, 24 Sep 2017 17:54:56 +0000 (10:54 -0700)
committerJan Kotas <jkotas@microsoft.com>
Fri, 29 Sep 2017 21:23:43 +0000 (14:23 -0700)
16 files changed:
src/dlls/mscorrc/mscorrc.rc
src/dlls/mscorrc/resource.h
src/jit/compiler.cpp
src/jit/compiler.h
src/jit/hwintrinsicxarch.cpp
src/jit/importer.cpp
src/jit/instr.h
src/mscorlib/src/System/Runtime/Intrinsics/X86/Lzcnt.cs
src/mscorlib/src/System/Runtime/Intrinsics/X86/Popcnt.cs
src/vm/methodtablebuilder.cpp
src/vm/methodtablebuilder.h
src/zap/zapimage.cpp
tests/src/Common/test_dependencies/test_dependencies.csproj
tests/src/JIT/HardwareIntrinsics/IsSupported.cs
tests/src/JIT/HardwareIntrinsics/IsSupported_r.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/IsSupported_ro.csproj [moved from tests/src/JIT/HardwareIntrinsics/IsSupported.csproj with 100% similarity]

index 8dd29ae..8bc7ff0 100644 (file)
@@ -853,6 +853,7 @@ BEGIN
     IDS_EE_SIMD_PARTIAL_TRUST_DISALLOWED    "SIMD intrinsics may not be used by partial trust applications."
     IDS_IBC_MISSING_EXTERNAL_TYPE           "The generic type specified by the IBC data is not available to this assembly"
     IDS_IBC_MISSING_EXTERNAL_METHOD         "The generic method specified by the IBC data is not available to this assembly"
+    IDS_EE_HWINTRINSIC_NGEN_DISALLOWED      "Hardware intrinsics may not be used with ngen."
 
     IDS_INET_E_CANNOT_CONNECT               "Cannot connect to URL for '%1'."
     IDS_INET_E_RESOURCE_NOT_FOUND           "The server or proxy was not found for '%1'."
index 205445a..eb1cb29 100644 (file)
 #define IDS_EE_SIMD_PARTIAL_TRUST_DISALLOWED    0x1ac4
 #define IDS_IBC_MISSING_EXTERNAL_TYPE           0x1ac5
 #define IDS_IBC_MISSING_EXTERNAL_METHOD         0x1ac6
+#define IDS_EE_HWINTRINSIC_NGEN_DISALLOWED      0x1ac7
 
 #define BFA_INVALID_FILE_TOKEN                  0x2000
 #define BFA_INVALID_TOKEN_TYPE                  0x2001
index 86179ec..6e1323f 100644 (file)
@@ -2561,7 +2561,7 @@ void Compiler::compSetProcessor()
 
 #endif // _TARGET_X86_
 
-// Instruction set flags fo// Instruction set flags for Intel hardware intrinsics
+// Instruction set flags for Intel hardware intrinsics
 #ifdef _TARGET_XARCH_
     opts.compSupportsISA = 0;
 
index dfc50ee..4bdb7ac 100644 (file)
@@ -3021,22 +3021,22 @@ protected:
     InstructionSet lookupHWIntrinsicISA(const char* className);
     NamedIntrinsic lookupHWIntrinsic(const char* methodName, InstructionSet isa);
     InstructionSet isaOfHWIntrinsic(NamedIntrinsic intrinsic);
-    GenTree* impX86HWIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method);
-    GenTree* impSSEIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method);
-    GenTree* impSSE2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method);
-    GenTree* impSSE3Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method);
-    GenTree* impSSSE3Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method);
-    GenTree* impSSE41Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method);
-    GenTree* impSSE42Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method);
-    GenTree* impAVXIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method);
-    GenTree* impAVX2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method);
-    GenTree* impAESIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method);
-    GenTree* impBMI1Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method);
-    GenTree* impBMI2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method);
-    GenTree* impFMAIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method);
-    GenTree* impLZCNTIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method);
-    GenTree* impPCLMULQDQIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method);
-    GenTree* impPOPCNTIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method);
+    GenTree* impX86HWIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
+    GenTree* impSSEIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
+    GenTree* impSSE2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
+    GenTree* impSSE3Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
+    GenTree* impSSSE3Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
+    GenTree* impSSE41Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
+    GenTree* impSSE42Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
+    GenTree* impAVXIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
+    GenTree* impAVX2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
+    GenTree* impAESIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
+    GenTree* impBMI1Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
+    GenTree* impBMI2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
+    GenTree* impFMAIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
+    GenTree* impLZCNTIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
+    GenTree* impPCLMULQDQIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
+    GenTree* impPOPCNTIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
 #endif
     GenTreePtr impArrayAccessIntrinsic(CORINFO_CLASS_HANDLE clsHnd,
                                        CORINFO_SIG_INFO*    sig,
@@ -7824,6 +7824,15 @@ private:
 #endif
     }
 
+    bool compSupports(InstructionSet isa)
+    {
+#ifdef _TARGET_XARCH_
+        return (opts.compSupportsISA & (1 << isa)) != 0;
+#else
+        return false;
+#endif
+    }
+
     /*
     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
@@ -7938,16 +7947,11 @@ public:
 #endif                      // _TARGET_XARCH_
 
 #ifdef _TARGET_XARCH_
-        // only for Intel hardware intrinsics
         uint64_t compSupportsISA;
         void setSupportedISA(InstructionSet isa)
         {
             compSupportsISA |= 1 << isa;
         }
-        bool compSupports(InstructionSet isa)
-        {
-            return (compSupportsISA & (1 << isa)) != 0;
-        }
 #endif
 
 // optimize maximally and/or favor speed over size?
index 4a1ca85..45ee468 100644 (file)
@@ -154,225 +154,226 @@ InstructionSet Compiler::isaOfHWIntrinsic(NamedIntrinsic intrinsic)
 // 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::impX86HWIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method)
+GenTree* Compiler::impX86HWIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
 {
     InstructionSet isa = isaOfHWIntrinsic(intrinsic);
     switch (isa)
     {
         case InstructionSet_SSE:
-            return impSSEIntrinsic(intrinsic, method);
+            return impSSEIntrinsic(intrinsic, method, sig);
         case InstructionSet_SSE2:
-            return impSSE2Intrinsic(intrinsic, method);
+            return impSSE2Intrinsic(intrinsic, method, sig);
         case InstructionSet_SSE3:
-            return impSSE3Intrinsic(intrinsic, method);
+            return impSSE3Intrinsic(intrinsic, method, sig);
         case InstructionSet_SSSE3:
-            return impSSSE3Intrinsic(intrinsic, method);
+            return impSSSE3Intrinsic(intrinsic, method, sig);
         case InstructionSet_SSE41:
-            return impSSE41Intrinsic(intrinsic, method);
+            return impSSE41Intrinsic(intrinsic, method, sig);
         case InstructionSet_SSE42:
-            return impSSE42Intrinsic(intrinsic, method);
+            return impSSE42Intrinsic(intrinsic, method, sig);
         case InstructionSet_AVX:
-            return impAVXIntrinsic(intrinsic, method);
+            return impAVXIntrinsic(intrinsic, method, sig);
         case InstructionSet_AVX2:
-            return impAVX2Intrinsic(intrinsic, method);
+            return impAVX2Intrinsic(intrinsic, method, sig);
 
         case InstructionSet_AES:
-            return impAESIntrinsic(intrinsic, method);
+            return impAESIntrinsic(intrinsic, method, sig);
         case InstructionSet_BMI1:
-            return impBMI1Intrinsic(intrinsic, method);
+            return impBMI1Intrinsic(intrinsic, method, sig);
         case InstructionSet_BMI2:
-            return impBMI2Intrinsic(intrinsic, method);
+            return impBMI2Intrinsic(intrinsic, method, sig);
         case InstructionSet_FMA:
-            return impFMAIntrinsic(intrinsic, method);
+            return impFMAIntrinsic(intrinsic, method, sig);
         case InstructionSet_LZCNT:
-            return impLZCNTIntrinsic(intrinsic, method);
+            return impLZCNTIntrinsic(intrinsic, method, sig);
         case InstructionSet_PCLMULQDQ:
-            return impPCLMULQDQIntrinsic(intrinsic, method);
+            return impPCLMULQDQIntrinsic(intrinsic, method, sig);
         case InstructionSet_POPCNT:
-            return impPOPCNTIntrinsic(intrinsic, method);
+            return impPOPCNTIntrinsic(intrinsic, method, sig);
         default:
             return nullptr;
     }
 }
 
-GenTree* Compiler::impSSEIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method)
+GenTree* Compiler::impSSEIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
 {
     switch (intrinsic)
     {
         case NI_SSE_IsSupported:
-            return gtNewIconNode(opts.compSupports(InstructionSet_SSE));
+            return gtNewIconNode(compSupports(InstructionSet_SSE));
 
         default:
             return nullptr;
     }
 }
 
-GenTree* Compiler::impSSE2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method)
+GenTree* Compiler::impSSE2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
 {
     switch (intrinsic)
     {
         case NI_SSE2_IsSupported:
-            return gtNewIconNode(opts.compSupports(InstructionSet_SSE2));
+            return gtNewIconNode(compSupports(InstructionSet_SSE2));
 
         default:
             return nullptr;
     }
 }
 
-GenTree* Compiler::impSSE3Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method)
+GenTree* Compiler::impSSE3Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
 {
     switch (intrinsic)
     {
         case NI_SSE3_IsSupported:
-            return gtNewIconNode(opts.compSupports(InstructionSet_SSE3));
+            return gtNewIconNode(compSupports(InstructionSet_SSE3));
 
         default:
             return nullptr;
     }
 }
 
-GenTree* Compiler::impSSSE3Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method)
+GenTree* Compiler::impSSSE3Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
 {
     switch (intrinsic)
     {
         case NI_SSSE3_IsSupported:
-            return gtNewIconNode(opts.compSupports(InstructionSet_SSSE3));
+            return gtNewIconNode(compSupports(InstructionSet_SSSE3));
 
         default:
             return nullptr;
     }
 }
 
-GenTree* Compiler::impSSE41Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method)
+GenTree* Compiler::impSSE41Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
 {
     switch (intrinsic)
     {
         case NI_SSE41_IsSupported:
-            return gtNewIconNode(opts.compSupports(InstructionSet_SSE41));
+            return gtNewIconNode(compSupports(InstructionSet_SSE41));
 
         default:
             return nullptr;
     }
 }
 
-GenTree* Compiler::impSSE42Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method)
+GenTree* Compiler::impSSE42Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
 {
     switch (intrinsic)
     {
         case NI_SSE42_IsSupported:
-            return gtNewIconNode(opts.compSupports(InstructionSet_SSE42));
+            return gtNewIconNode(compSupports(InstructionSet_SSE42));
 
         default:
             return nullptr;
     }
 }
 
-GenTree* Compiler::impAVXIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method)
+GenTree* Compiler::impAVXIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
 {
     switch (intrinsic)
     {
         case NI_AVX_IsSupported:
-            return gtNewIconNode(opts.compSupports(InstructionSet_AVX));
+            return gtNewIconNode(compSupports(InstructionSet_AVX));
 
         default:
             return nullptr;
     }
 }
 
-GenTree* Compiler::impAVX2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method)
+GenTree* Compiler::impAVX2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
 {
     switch (intrinsic)
     {
         case NI_AVX2_IsSupported:
-            return gtNewIconNode(opts.compSupports(InstructionSet_AVX2));
+            return gtNewIconNode(compSupports(InstructionSet_AVX2));
 
         default:
             return nullptr;
     }
 }
 
-GenTree* Compiler::impAESIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method)
+GenTree* Compiler::impAESIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
 {
     switch (intrinsic)
     {
         case NI_AES_IsSupported:
-            return gtNewIconNode(opts.compSupports(InstructionSet_AES));
+            return gtNewIconNode(compSupports(InstructionSet_AES));
 
         default:
             return nullptr;
     }
 }
 
-GenTree* Compiler::impBMI1Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method)
+GenTree* Compiler::impBMI1Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
 {
     switch (intrinsic)
     {
         case NI_BMI1_IsSupported:
-            return gtNewIconNode(opts.compSupports(InstructionSet_BMI1));
+            return gtNewIconNode(compSupports(InstructionSet_BMI1));
 
         default:
             return nullptr;
     }
 }
 
-GenTree* Compiler::impBMI2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method)
+GenTree* Compiler::impBMI2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
 {
     switch (intrinsic)
     {
         case NI_BMI2_IsSupported:
-            return gtNewIconNode(opts.compSupports(InstructionSet_BMI2));
+            return gtNewIconNode(compSupports(InstructionSet_BMI2));
 
         default:
             return nullptr;
     }
 }
 
-GenTree* Compiler::impFMAIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method)
+GenTree* Compiler::impFMAIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
 {
     switch (intrinsic)
     {
         case NI_FMA_IsSupported:
-            return gtNewIconNode(opts.compSupports(InstructionSet_FMA));
+            return gtNewIconNode(compSupports(InstructionSet_FMA));
 
         default:
             return nullptr;
     }
 }
 
-GenTree* Compiler::impLZCNTIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method)
+GenTree* Compiler::impLZCNTIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
 {
     switch (intrinsic)
     {
         case NI_LZCNT_IsSupported:
-            return gtNewIconNode(opts.compSupports(InstructionSet_LZCNT));
+            return gtNewIconNode(compSupports(InstructionSet_LZCNT));
 
         default:
             return nullptr;
     }
 }
 
-GenTree* Compiler::impPCLMULQDQIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method)
+GenTree* Compiler::impPCLMULQDQIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
 {
     switch (intrinsic)
     {
         case NI_PCLMULQDQ_IsSupported:
-            return gtNewIconNode(opts.compSupports(InstructionSet_PCLMULQDQ));
+            return gtNewIconNode(compSupports(InstructionSet_PCLMULQDQ));
 
         default:
             return nullptr;
     }
 }
 
-GenTree* Compiler::impPOPCNTIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method)
+GenTree* Compiler::impPOPCNTIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
 {
     switch (intrinsic)
     {
         case NI_POPCNT_IsSupported:
-            return gtNewIconNode(opts.compSupports(InstructionSet_POPCNT));
+            return gtNewIconNode(compSupports(InstructionSet_POPCNT));
 
         default:
             return nullptr;
index d16dfe3..714e6fe 100644 (file)
@@ -3322,9 +3322,11 @@ GenTreePtr Compiler::impIntrinsic(GenTreePtr            newobjThis,
     GenTreePtr retNode = nullptr;
 
     //
-    // We disable the inlining of instrinsics for MinOpts.
-    //
-    if (!mustExpand && (opts.compDbgCode || opts.MinOpts()))
+    // We disable the inlining of intrinsic for MinOpts,
+    // but we should always expand hardware intrinsics whose managed method body
+    // is a directly recursive call site. This design makes hardware intrinsic
+    // be able to work with debugger and reflection.
+    if (!mustExpand && (opts.compDbgCode || opts.MinOpts()) && !gtIsRecursiveCall(method))
     {
         *pIntrinsicID = CORINFO_INTRINSIC_Illegal;
         return retNode;
@@ -3738,7 +3740,7 @@ GenTreePtr Compiler::impIntrinsic(GenTreePtr            newobjThis,
 #ifdef _TARGET_XARCH_
         if (ni > NI_HW_INTRINSIC_START && ni < NI_HW_INTRINSIC_END)
         {
-            retNode = impX86HWIntrinsic(ni, method);
+            retNode = impX86HWIntrinsic(ni, method, sig);
         }
 #endif
         switch (ni)
index e364fbc..eac4256 100644 (file)
@@ -274,9 +274,6 @@ enum emitAttr : unsigned
 
 #define EmitSize(x)                 (EA_ATTR(genTypeSize(TypeGet(x))))
 
-// Enum specifying the instruction set for generating floating point or SIMD code.
-// These enums are ordered such that each one is inclusive of previous instruction sets
-// and the VM ensures this as well when setting the CONFIG flags.
 enum InstructionSet
 {
 #ifdef _TARGET_XARCH_
@@ -292,10 +289,12 @@ enum InstructionSet
     InstructionSet_AVX     = 8,
     InstructionSet_AVX2    = 9,
     // Linear order end
-    // Instruction sets have the linear order only in above area.
-    // Values of InstructionSet not in this area cannot be compared 
-    // (i.e. compiler->getSIMDInstructionSet() >= InstructionSet_SSE3_4).
-
+    // TODO - Instruction sets have the linear order only in above area.
+    // We should no long compare the return value of getSIMDInstructionSet()
+    // or getFloatingPointInstructionSet() to the InstructionSet values.
+    // Should refactor SIMD code only to be aware of SIMD feature levels 
+    // (SSE2, SSE3_4, AVX, and AVX2, etc.) rather than concrete ISA.
+    
     InstructionSet_AES     = 32,
     InstructionSet_BMI1    = 33,
     InstructionSet_BMI2    = 34,
index 17d7716..6bdc8cc 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System;
+using System.Runtime.Intrinsics;
 
 namespace System.Runtime.Intrinsics.X86
 {
index c9e71b3..21cae31 100644 (file)
@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 using System;
+using System.Runtime.Intrinsics;
 
 namespace System.Runtime.Intrinsics.X86
 {
index 8a96e68..adcf7bb 100644 (file)
@@ -1484,6 +1484,26 @@ MethodTableBuilder::BuildMethodTableThrowing(
         }
     }
 
+#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) 
+    // All the funtions in System.Runtime.Intrinsics.X86 are hardware intrinsics.
+    // We specially treat them here to reduce the disk footprint of mscorlib.
+    if (GetModule()->IsSystem() && !bmtGenerics->HasInstantiation())
+    {
+        LPCUTF8 x86className;
+        LPCUTF8 x86nameSpace;
+        HRESULT hr = GetMDImport()->GetNameOfTypeDef(bmtInternal->pType->GetTypeDefToken(), &x86className, &x86nameSpace);
+    
+        if (hr == S_OK && strcmp(x86nameSpace, "System.Runtime.Intrinsics.X86") == 0)
+        {
+            if (IsCompilationProcess())
+            {
+                // Disable AOT compiling for managed implementation of hardware intrinsics in mscorlib.
+                COMPlusThrow(kTypeLoadException, IDS_EE_HWINTRINSIC_NGEN_DISALLOWED);
+            }
+            bmtProp->fIsHardwareIntrinsic = true;
+        }
+    }
+#endif
 
 #ifdef FEATURE_COMINTEROP 
 
@@ -5090,19 +5110,7 @@ MethodTableBuilder::InitNewMethodDesc(
             NULL,
             NULL);
 
-        if (hr == S_OK)
-        {
-            pNewMD->SetIsJitIntrinsic();
-        }
-
-        // All the funtions in System.Runtime.Intrinsics.X86 are hardware intrinsics.
-        // We specially treat them here to reduce the disk footprint of mscorlib.
-        LPCUTF8 className;
-        LPCUTF8 nameSpace;
-
-        HRESULT hrns = GetMDImport()->GetNameOfTypeDef(bmtInternal->pType->GetTypeDefToken(), &className, &nameSpace);
-
-        if (hrns == S_OK && strcmp(nameSpace, "System.Runtime.Intrinsics.X86") == 0)
+        if (hr == S_OK || bmtProp->fIsHardwareIntrinsic)
         {
             pNewMD->SetIsJitIntrinsic();
         }
@@ -9402,7 +9410,7 @@ void MethodTableBuilder::CheckForSystemTypes()
     {
         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
     }
-    
+
     if (IsValueClass())
     {
         //
index a7d7bdd..c5ce09f 100644 (file)
@@ -1333,6 +1333,8 @@ private:
         bool fDynamicStatics;                   // Set to true if the statics will be allocated in the dynamic
         bool fGenericsStatics;                  // Set to true if the there are per-instantiation statics
 
+        bool fIsHardwareIntrinsic;              // Set to true if the class is a hardware intrinsic
+
         DWORD dwNonGCRegularStaticFieldBytes;
         DWORD dwNonGCThreadStaticFieldBytes;
 
index 96fa81f..98b9e92 100644 (file)
@@ -3560,6 +3560,12 @@ void ZapImage::Error(mdToken token, HRESULT hr, UINT resID,  LPCWSTR message)
         level = CORZAP_LOGLEVEL_INFO;
     }
 
+    if (resID == IDS_EE_HWINTRINSIC_NGEN_DISALLOWED)
+    {
+        // Supress printing of "Hardware intrinsics may not be used with ngen."
+        level = CORZAP_LOGLEVEL_INFO;
+    }
+
 #ifdef CROSSGEN_COMPILE
     if ((resID == IDS_IBC_MISSING_EXTERNAL_TYPE) ||
         (resID == IDS_IBC_MISSING_EXTERNAL_METHOD))
index e9d78ec..1e34f8a 100644 (file)
@@ -23,7 +23,7 @@
       <Version>$(CoreFxPackageVersion)</Version>
     </PackageReference>
     <PackageReference Include="System.Runtime.Intrinsics.X86">
-      <Version>4.5.0-preview1-25718-03</Version>
+      <Version>$(CoreFxPackageVersion)</Version>
     </PackageReference>
   </ItemGroup>
   <PropertyGroup>
index 9f6d924..7e92f18 100644 (file)
@@ -2,7 +2,9 @@
 // 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;
 using System.Runtime.Intrinsics.X86;
+using System.Numerics;
 
 namespace IntelHardwareIntrinsicTest
 {
@@ -50,15 +52,16 @@ namespace IntelHardwareIntrinsicTest
                         result = false;
                     }
                 }
-                if (Aes.IsSupported && Bmi1.IsSupported && Bmi2.IsSupported && Fma.IsSupported && 
-                        Lzcnt.IsSupported && Popcnt.IsSupported && Pclmulqdq.IsSupported)
-                    {
-                        result = result && true;
-                    }
-                    else
-                    {
-                        result = false;
-                    }
+            }
+
+            if (Vector<byte>.Count == 32 && !Avx2.IsSupported)
+            {
+                result = false;
+            }
+
+            if (Vector<byte>.Count == 16 && Vector.IsHardwareAccelerated && !Sse2.IsSupported)
+            {
+                result = false;
             }
 
             // Non-X86 platforms
@@ -82,6 +85,28 @@ namespace IntelHardwareIntrinsicTest
                     result = false;
                 }
             }
+
+            // Reflection call
+            var issupported = "get_IsSupported";
+            if (Convert.ToBoolean(typeof(Sse).GetMethod(issupported).Invoke(null, null)) != Sse.IsSupported ||
+                Convert.ToBoolean(typeof(Sse2).GetMethod(issupported).Invoke(null, null)) != Sse2.IsSupported ||
+                Convert.ToBoolean(typeof(Sse3).GetMethod(issupported).Invoke(null, null)) != Sse3.IsSupported ||
+                Convert.ToBoolean(typeof(Ssse3).GetMethod(issupported).Invoke(null, null)) != Ssse3.IsSupported ||
+                Convert.ToBoolean(typeof(Sse41).GetMethod(issupported).Invoke(null, null)) != Sse41.IsSupported ||
+                Convert.ToBoolean(typeof(Sse42).GetMethod(issupported).Invoke(null, null)) != Sse42.IsSupported ||
+                Convert.ToBoolean(typeof(Aes).GetMethod(issupported).Invoke(null, null)) != Aes.IsSupported ||
+                Convert.ToBoolean(typeof(Avx).GetMethod(issupported).Invoke(null, null)) != Avx.IsSupported ||
+                Convert.ToBoolean(typeof(Avx2).GetMethod(issupported).Invoke(null, null)) != Avx2.IsSupported ||
+                Convert.ToBoolean(typeof(Fma).GetMethod(issupported).Invoke(null, null)) != Fma.IsSupported ||
+                Convert.ToBoolean(typeof(Lzcnt).GetMethod(issupported).Invoke(null, null)) != Lzcnt.IsSupported ||
+                Convert.ToBoolean(typeof(Bmi1).GetMethod(issupported).Invoke(null, null)) != Bmi1.IsSupported ||
+                Convert.ToBoolean(typeof(Bmi2).GetMethod(issupported).Invoke(null, null)) != Bmi2.IsSupported ||
+                Convert.ToBoolean(typeof(Popcnt).GetMethod(issupported).Invoke(null, null)) != Popcnt.IsSupported ||
+                Convert.ToBoolean(typeof(Pclmulqdq).GetMethod(issupported).Invoke(null, null)) != Pclmulqdq.IsSupported
+            )
+            {
+                result = false;
+            }
             return result ? 100 : 0;
         }
 
diff --git a/tests/src/JIT/HardwareIntrinsics/IsSupported_r.csproj b/tests/src/JIT/HardwareIntrinsics/IsSupported_r.csproj
new file mode 100644 (file)
index 0000000..e77c5dc
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " />
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <PropertyGroup>
+    <DebugType>None</DebugType>
+    <Optimize></Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="IsSupported.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
\ No newline at end of file