Use JitFuncInfoLogFile to check if SIMD intrinsics are recognized.
authorCarol Eidt <carol.eidt@microsoft.com>
Tue, 17 May 2016 23:48:15 +0000 (16:48 -0700)
committerCarol Eidt <carol.eidt@microsoft.com>
Fri, 27 May 2016 17:44:16 +0000 (10:44 -0700)
Although COMPlus_JitFuncInfoLogFile was enabled as a "RETAIL" variable, it
was only opening the file (and not writing to it) in non-DEBUG.
In order to use it, we need to also enable eeGetMethodFullName in release,
which in turn requires type names.
Also, _wfsopen() is not supported in the PAL layer.
However, it appears to work fine without the sharing option, on both Windows
and Linux.
Add a utility class to use the log file to check whether a method has been compiled.
Use it to test that the SIMD intrinsics are not compiled when they are enabled.
Add dir.props to the SIMD test directory to set the COMPlus_JitFuncInfoLogFile
environment variable, and to delete the log file before each test.

Fix #2554

22 files changed:
src/jit/compiler.cpp
src/jit/eeinterface.cpp
src/jit/utils.cpp
tests/src/JIT/SIMD/Ctors.cs
tests/src/JIT/SIMD/Ctors_r.csproj
tests/src/JIT/SIMD/Ctors_ro.csproj
tests/src/JIT/SIMD/VectorAbs.cs
tests/src/JIT/SIMD/VectorAdd.cs
tests/src/JIT/SIMD/VectorArray.cs
tests/src/JIT/SIMD/VectorArrayInit.cs
tests/src/JIT/SIMD/VectorCopyToArray.cs
tests/src/JIT/SIMD/VectorDiv.cs
tests/src/JIT/SIMD/VectorDot.cs
tests/src/JIT/SIMD/VectorGet.cs
tests/src/JIT/SIMD/VectorInitN.cs
tests/src/JIT/SIMD/VectorMax.cs
tests/src/JIT/SIMD/VectorMin.cs
tests/src/JIT/SIMD/VectorMul.cs
tests/src/JIT/SIMD/VectorRelOp.cs
tests/src/JIT/SIMD/VectorUtil.cs
tests/src/JIT/SIMD/dir.props [new file with mode: 0644]
tests/src/JIT/SIMD/project.json

index e7fcb71..fc34013 100644 (file)
@@ -3921,13 +3921,16 @@ void                 Compiler::compCompile(void * * methodCodePtr,
     compFunctionTraceEnd(*methodCodePtr, *methodCodeSize, false);
 
 #if FUNC_INFO_LOGGING
-#ifdef DEBUG // We only have access to info.compFullName in DEBUG builds.
     if (compJitFuncInfoFile != NULL)
     {
         assert(!compIsForInlining());
+#ifdef DEBUG // We only have access to info.compFullName in DEBUG builds.
         fprintf(compJitFuncInfoFile, "%s\n", info.compFullName);
+#else
+        fprintf(compJitFuncInfoFile, " %s\n", eeGetMethodFullName(info.compMethodHnd));
+#endif
+        fprintf(compJitFuncInfoFile, "");         // in our logic this causes a flush
     }
-#endif // DEBUG
 #endif // FUNC_INFO_LOGGING
 }
 
@@ -4123,7 +4126,7 @@ int           Compiler::compCompile(CORINFO_METHOD_HANDLE methodHnd,
         if (oldFuncInfoFileName == NULL)
         {
             assert(compJitFuncInfoFile == NULL);
-            compJitFuncInfoFile = _wfsopen(compJitFuncInfoFilename, W("a"), _SH_DENYWR); // allow reading the file before the end of compilation
+            compJitFuncInfoFile = _wfopen(compJitFuncInfoFilename, W("a"));
         }
     }
 #endif // FUNC_INFO_LOGGING
index cd23b19..372e624 100644 (file)
@@ -20,8 +20,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 #pragma hdrstop
 #endif
 
-#if defined(DEBUG) || defined(FEATURE_JIT_METHOD_PERF)
-
 #pragma warning(push)
 #pragma warning(disable:4701) // difficult to get rid of C4701 with 'sig' below
 
@@ -199,6 +197,4 @@ const char* Compiler::eeGetMethodFullName (CORINFO_METHOD_HANDLE  hnd)
 
 #pragma warning(pop)
 
-#endif // DEBUG || FEATURE_JIT_METHOD_PERF
-
 /*****************************************************************************/
index cf7d4c6..37164c9 100644 (file)
@@ -99,7 +99,6 @@ const BYTE          opcodeArgKinds[] =
 };
 #endif
 
-#if defined(DEBUG) || defined(FEATURE_JIT_METHOD_PERF)
 /*****************************************************************************/
 
 const   char *      varTypeName(var_types vt)
@@ -116,7 +115,6 @@ const   char *      varTypeName(var_types vt)
 
     return  varTypeNames[vt];
 }
-#endif // DEBUG || FEATURE_JIT_METHOD_PERF
 
 #if defined(DEBUG) || defined(LATE_DISASM)
 /*****************************************************************************
index f639703..581e5be 100644 (file)
@@ -5,8 +5,11 @@ using System;
 using System.Collections.Generic;
 using System.Numerics;
 
-namespace VectorMathTests
+internal partial class VectorTest
 {
+    private const int Pass = 100;
+    private const int Fail = -1;
+
     class Program
     {          
         const float EPS = Single.Epsilon * 5;
@@ -70,9 +73,20 @@ namespace VectorMathTests
 
         static int Main(string[] args)
         {
+            int returnVal = Pass;
+            
             if (Vector2Ctors() != 100 || Vector3Ctors() != 100 || Vector4Ctors() != 100)
-                return 0;
-            return 100;
+            {
+                returnVal = Fail;
+            }
+
+            JitLog jitLog = new JitLog();
+            if (!jitLog.Check("System.Numerics.Vector2:.ctor(float,float)")) returnVal = Fail;
+            if (!jitLog.Check("System.Numerics.Vector3:.ctor(float,float,float)")) returnVal = Fail;
+            if (!jitLog.Check("System.Numerics.Vector4:.ctor(float,float,float,float)")) returnVal = Fail;
+            jitLog.Dispose();
+
+            return returnVal;
         }
     }
 }
index 4fe8970..6a2b6b9 100644 (file)
@@ -38,6 +38,7 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Ctors.cs" />
+    <Compile Include="VectorUtil.cs" />
   </ItemGroup>
   <!--  <PropertyGroup>
     <ProjectJson>$(JitPackagesConfigFileDirectory)threading+thread\project.json</ProjectJson>
index 488946d..6cc9bde 100644 (file)
@@ -38,6 +38,7 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Ctors.cs" />
+    <Compile Include="VectorUtil.cs" />
   </ItemGroup>
   <!--  <PropertyGroup>
     <ProjectJson>$(JitPackagesConfigFileDirectory)threading+thread\project.json</ProjectJson>
index 10ef289..64a7bde 100644 (file)
@@ -81,6 +81,22 @@ internal partial class VectorTest
         if (Vector2Test.VectorAbs() != Pass) returnVal = Fail;
         if (VectorAbsTest<ushort>.VectorAbs((ushort)0xffff, (ushort)0xffff) != Pass) returnVal = Fail;
         if (VectorAbsTest<byte>.VectorAbs((byte)0xff, (byte)0xff) != Pass) returnVal = Fail;
+        if (VectorAbsTest<uint>.VectorAbs(0x41000000u, 0x41000000u) != Pass) returnVal = Fail;
+        if (VectorAbsTest<ulong>.VectorAbs(0x4100000000000000ul, 0x4100000000000000ul) != Pass) returnVal = Fail;
+
+        JitLog jitLog = new JitLog();
+        if (!jitLog.Check("Abs", "Single")) returnVal = Fail;
+        if (!jitLog.Check("Abs", "Double")) returnVal = Fail;
+        // Abs is not an intrinsic for Int32 and Int64, but IS for UInt32 and UInt64
+        if (!jitLog.Check("System.Numerics.Vector4:Abs")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector3:Abs")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector2:Abs")) returnVal = Fail;
+        if (!jitLog.Check("Abs", "UInt16")) returnVal = Fail;
+        if (!jitLog.Check("Abs", "Byte")) returnVal = Fail;
+        if (!jitLog.Check("Abs", "UInt32")) returnVal = Fail;
+        if (!jitLog.Check("Abs", "UInt64")) returnVal = Fail;
+        jitLog.Dispose();
+
         return returnVal;
     }
 }
index d3dd305..eeaf163 100644 (file)
@@ -86,6 +86,23 @@ internal partial class VectorTest
         if (VectorAddTest<sbyte>.VectorAdd(-1, -2, (sbyte)(-1 - 2)) != Pass) returnVal = Fail;
         if (VectorAddTest<uint>.VectorAdd(0x41000000u, 0x42000000u, 0x41000000u + 0x42000000u) != Pass) returnVal = Fail;
         if (VectorAddTest<ulong>.VectorAdd(0x4100000000000000ul, 0x4200000000000000ul, 0x4100000000000000ul + 0x4200000000000000ul) != Pass) returnVal = Fail;
+
+        JitLog jitLog = new JitLog();
+        if (!jitLog.Check("op_Addition", "Single")) returnVal = Fail;
+        if (!jitLog.Check("op_Addition", "Double")) returnVal = Fail;
+        if (!jitLog.Check("op_Addition", "Int32")) returnVal = Fail;
+        if (!jitLog.Check("op_Addition", "Int64")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector4:op_Addition")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector3:op_Addition")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector2:op_Addition")) returnVal = Fail;
+        if (!jitLog.Check("op_Addition", "UInt16")) returnVal = Fail;
+        if (!jitLog.Check("op_Addition", "Byte")) returnVal = Fail;
+        if (!jitLog.Check("op_Addition", "Int16")) returnVal = Fail;
+        if (!jitLog.Check("op_Addition", "SByte")) returnVal = Fail;
+        if (!jitLog.Check("op_Addition", "UInt32")) returnVal = Fail;
+        if (!jitLog.Check("op_Addition", "UInt64")) returnVal = Fail;
+        jitLog.Dispose();
+
         return returnVal;
     }
 }
index 8c8c1ec..9d1417a 100644 (file)
@@ -159,6 +159,41 @@ internal partial class VectorTest
             if (VectorArrayTest<sbyte>.VectorArray(1) != Pass) returnVal = Fail;
             if (VectorArrayTest<uint>.VectorArray(1) != Pass) returnVal = Fail;
             if (VectorArrayTest<ulong>.VectorArray(1ul) != Pass) returnVal = Fail;
+
+            JitLog jitLog = new JitLog();
+            if (!jitLog.Check("get_Item", "Single")) returnVal = Fail;
+            if (!jitLog.Check("System.Numerics.Vector`1[Single][System.Single]:.ctor(float)")) returnVal = Fail;
+            if (!jitLog.Check("get_Item", "Double")) returnVal = Fail;
+            if (!jitLog.Check("System.Numerics.Vector`1[Double][System.Double]:.ctor(double)")) returnVal = Fail;
+            if (!jitLog.Check("get_Item", "Int32")) returnVal = Fail;
+            if (!jitLog.Check("System.Numerics.Vector`1[Int32][System.Int32]:.ctor(int)")) returnVal = Fail;
+            if (!jitLog.Check("get_Item", "Int64")) returnVal = Fail;
+            if (!jitLog.Check("System.Numerics.Vector`1[Int64][System.Int64]:.ctor(long)")) returnVal = Fail;
+            if (!jitLog.Check("System.Numerics.Vector4:.ctor(float)")) returnVal = Fail;
+            if (!jitLog.Check("System.Numerics.Vector3:.ctor(float)")) returnVal = Fail;
+            if (!jitLog.Check("System.Numerics.Vector2:.ctor(float)")) returnVal = Fail;
+            if (!jitLog.Check("get_Item", "UInt16")) returnVal = Fail;
+            // We are not currently recognizing the Vector<UInt16> constructor.
+            if (!Vector.IsHardwareAccelerated)
+                if (!jitLog.Check("System.Numerics.Vector`1[UInt16][System.UInt16]:.ctor(char)")) returnVal = Fail;
+            if (!jitLog.Check("get_Item", "Byte")) returnVal = Fail;
+            // We are not currently recognizing the Vector<Byte> constructor.
+            if (!Vector.IsHardwareAccelerated)
+                if (!jitLog.Check("System.Numerics.Vector`1[Byte][System.Byte]:.ctor(ubyte)")) returnVal = Fail;
+            if (!jitLog.Check("get_Item", "Int16")) returnVal = Fail;
+            // We are not currently recognizing the Vector<Int16> constructor.
+            if (!Vector.IsHardwareAccelerated)
+                if (!jitLog.Check("System.Numerics.Vector`1[Int16][System.Int16]:.ctor(short)")) returnVal = Fail;
+            if (!jitLog.Check("get_Item", "SByte")) returnVal = Fail;
+            // We are not currently recognizing the Vector<SByte> constructor.
+            if (!Vector.IsHardwareAccelerated)
+                if (!jitLog.Check("System.Numerics.Vector`1[SByte][System.SByte]:.ctor(byte)")) returnVal = Fail;
+            if (!jitLog.Check("get_Item", "UInt32")) returnVal = Fail;
+            if (!jitLog.Check("System.Numerics.Vector`1[UInt32][System.UInt32]:.ctor(int)")) returnVal = Fail;
+            if (!jitLog.Check("get_Item", "UInt64")) returnVal = Fail;
+            if (!jitLog.Check("System.Numerics.Vector`1[UInt64][System.UInt64]:.ctor(long)")) returnVal = Fail;
+            jitLog.Dispose();
+
         }
         catch (ArgumentException ex)
         {
index 85ebd4a..154e1e7 100644 (file)
@@ -143,6 +143,30 @@ internal partial class VectorTest
         if (VectorArrayInitTest<uint>.VectorArrayInit(17, random) == Fail) returnVal = Fail;
         if (VectorArrayInitTest<ulong>.VectorArrayInit(12, random) == Fail) returnVal = Fail;
         if (VectorArrayInitTest<ulong>.VectorArrayInit(17, random) == Fail) returnVal = Fail;
+
+        JitLog jitLog = new JitLog();
+        if (!jitLog.Check(".ctor(ref)", "Single")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref,int)", "Single")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref)", "Double")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref,int)", "Double")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref)", "Int32")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref,int)", "Int32")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref)", "Int64")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref,int)", "Int64")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref)", "UInt16")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref,int)", "UInt16")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref)", "Byte")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref,int)", "Byte")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref)", "Int16")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref,int)", "Int16")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref)", "SByte")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref,int)", "SByte")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref)", "UInt32")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref,int)", "UInt32")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref)", "UInt64")) returnVal = Fail;
+        if (!jitLog.Check(".ctor(ref,int)", "UInt64")) returnVal = Fail;
+        jitLog.Dispose();
+
         return returnVal;
     }
 }
index b141cfd..3a931fb 100644 (file)
@@ -144,6 +144,30 @@ internal partial class VectorTest
         if (VectorCopyToArrayTest<uint>.VectorCopyToArray(17, random) == Fail) returnVal = Fail;
         if (VectorCopyToArrayTest<ulong>.VectorCopyToArray(12, random) == Fail) returnVal = Fail;
         if (VectorCopyToArrayTest<ulong>.VectorCopyToArray(17, random) == Fail) returnVal = Fail;
+
+        JitLog jitLog = new JitLog();
+        if (!jitLog.Check("CopyTo(ref)", "Single")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref,int)", "Single")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref)", "Double")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref,int)", "Double")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref)", "Int32")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref,int)", "Int32")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref)", "Int64")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref,int)", "Int64")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref)", "UInt16")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref,int)", "UInt16")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref)", "Byte")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref,int)", "Byte")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref)", "Int16")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref,int)", "Int16")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref)", "SByte")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref,int)", "SByte")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref)", "UInt32")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref,int)", "UInt32")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref)", "UInt64")) returnVal = Fail;
+        if (!jitLog.Check("CopyTo(ref,int)", "UInt64")) returnVal = Fail;
+        jitLog.Dispose();
+
         return returnVal;
     }
 }
index 031a7d8..fcc4f79 100644 (file)
@@ -107,6 +107,16 @@ internal partial class VectorTest
         if (VectorMulTest<sbyte>.VectorDiv(6, -3, -2) != Pass) returnVal = Fail;
         if (VectorMulTest<uint>.VectorDiv(6u, 3u, 2u) != Pass) returnVal = Fail;
         if (VectorMulTest<ulong>.VectorDiv(8ul, 2ul, 4ul) != Pass) returnVal = Fail;
+
+        JitLog jitLog = new JitLog();
+        // Division is only recognized as an intrinsic for floating point element types.
+        if (!jitLog.Check("op_Division", "Single")) returnVal = Fail;
+        if (!jitLog.Check("op_Division", "Double")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector4:op_Division")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector3:op_Division")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector2:op_Division")) returnVal = Fail;
+        jitLog.Dispose();
+
         return returnVal;
     }
 }
index 95a2e92..2efe79e 100644 (file)
@@ -111,6 +111,16 @@ internal partial class VectorTest
         if (VectorDotTest<sbyte>.VectorDot(3, 2, (sbyte)(6 * Vector<sbyte>.Count)) != Pass) returnVal = Fail;
         if (VectorDotTest<uint>.VectorDot(3u, 2u, (uint)(6 * Vector<uint>.Count)) != Pass) returnVal = Fail;
         if (VectorDotTest<ulong>.VectorDot(3ul, 2ul, 6ul * (ulong)Vector<ulong>.Count) != Pass) returnVal = Fail;
+
+        JitLog jitLog = new JitLog();
+        // Dot is only recognized as an intrinsic for floating point element types.
+        if (!jitLog.Check("Dot", "Single")) returnVal = Fail;
+        if (!jitLog.Check("Dot", "Double")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector4:Dot")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector3:Dot")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector2:Dot")) returnVal = Fail;
+        jitLog.Dispose();
+
         return returnVal;
     }
 }
index 2e9cb25..a61ce81 100644 (file)
@@ -173,6 +173,36 @@ internal partial class VectorTest
         if (VectorGetTest<sbyte>.VectorGet(101, 1) == Fail) returnVal = Fail;
         if (VectorGetTest<sbyte>.VectorGet(-100, 1) == Fail) returnVal = Fail;
         if (VectorGetTest<sbyte>.VectorGetIndexerOutOfRange(-100, 1) == Fail) returnVal = Fail;
+        if (VectorGetTest<uint>.VectorGet(101, 1) == Fail) returnVal = Fail;
+        if (VectorGetTest<uint>.VectorGet(100, 1) == Fail) returnVal = Fail;
+        if (VectorGetTest<uint>.VectorGetIndexerOutOfRange(100, 1) == Fail) returnVal = Fail;
+        if (VectorGetTest<ulong>.VectorGet(101, 1) == Fail) returnVal = Fail;
+        if (VectorGetTest<ulong>.VectorGet(100, 1) == Fail) returnVal = Fail;
+        if (VectorGetTest<ulong>.VectorGetIndexerOutOfRange(100, 1) == Fail) returnVal = Fail;
+
+        JitLog jitLog = new JitLog();
+        if (!jitLog.Check("get_Item", "Double")) returnVal = Fail;
+        if (!jitLog.Check("get_Count", "Double")) returnVal = Fail;
+        if (!jitLog.Check("get_Item", "Single")) returnVal = Fail;
+        if (!jitLog.Check("get_Count", "Single")) returnVal = Fail;
+        if (!jitLog.Check("get_Item", "Int32")) returnVal = Fail;
+        if (!jitLog.Check("get_Count", "Int32")) returnVal = Fail;
+        if (!jitLog.Check("get_Item", "Int64")) returnVal = Fail;
+        if (!jitLog.Check("get_Count", "Int64")) returnVal = Fail;
+        if (!jitLog.Check("get_Item", "UInt16")) returnVal = Fail;
+        if (!jitLog.Check("get_Count", "UInt16")) returnVal = Fail;
+        if (!jitLog.Check("get_Item", "Byte")) returnVal = Fail;
+        if (!jitLog.Check("get_Count", "Byte")) returnVal = Fail;
+        if (!jitLog.Check("get_Item", "Int16")) returnVal = Fail;
+        if (!jitLog.Check("get_Count", "Int16")) returnVal = Fail;
+        if (!jitLog.Check("get_Item", "SByte")) returnVal = Fail;
+        if (!jitLog.Check("get_Count", "SByte")) returnVal = Fail;
+        if (!jitLog.Check("get_Item", "UInt32")) returnVal = Fail;
+        if (!jitLog.Check("get_Count", "UInt32")) returnVal = Fail;
+        if (!jitLog.Check("get_Item", "UInt64")) returnVal = Fail;
+        if (!jitLog.Check("get_Count", "UInt64")) returnVal = Fail;
+        jitLog.Dispose();
+
         return returnVal;
     }
 }
index 1807885..c0930b6 100644 (file)
@@ -104,6 +104,13 @@ internal partial class VectorTest
         int returnVal = Pass;
 
         if (VectorInitNTest.VectorInitN(0.5f, -0.5f, 0f, 1.0f) == Fail) returnVal = Fail;
+
+        JitLog jitLog = new JitLog();
+        if (!jitLog.Check("System.Numerics.Vector2:.ctor(float,float)")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector3:.ctor(float,float,float)")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector4:.ctor(float,float,float,float)")) returnVal = Fail;
+        jitLog.Dispose();
+
         return returnVal;
     }
 }
index 11133b8..f6237e6 100644 (file)
@@ -87,6 +87,23 @@ internal partial class VectorTest
         if (VectorMaxTest<sbyte>.VectorMax(-2, 3, 3) != Pass) returnVal = Fail;
         if (VectorMaxTest<uint>.VectorMax(0x80000000u, 0x40000000u, 0x80000000u) != Pass) returnVal = Fail;
         if (VectorMaxTest<ulong>.VectorMax(2ul, 3ul, 3ul) != Pass) returnVal = Fail;
+
+        JitLog jitLog = new JitLog();
+        if (!jitLog.Check("Max", "Single")) returnVal = Fail;
+        if (!jitLog.Check("Max", "Double")) returnVal = Fail;
+        if (!jitLog.Check("Max", "Int32")) returnVal = Fail;
+        if (!jitLog.Check("Max", "Int64")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector4:Max")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector3:Max")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector2:Max")) returnVal = Fail;
+        if (!jitLog.Check("Max", "UInt16")) returnVal = Fail;
+        if (!jitLog.Check("Max", "Byte")) returnVal = Fail;
+        if (!jitLog.Check("Max", "Int16")) returnVal = Fail;
+        if (!jitLog.Check("Max", "SByte")) returnVal = Fail;
+        if (!jitLog.Check("Max", "UInt32")) returnVal = Fail;
+        if (!jitLog.Check("Max", "UInt64")) returnVal = Fail;
+        jitLog.Dispose();
+
         return returnVal;
     }
 }
index c67f122..8757eba 100644 (file)
@@ -86,6 +86,23 @@ internal partial class VectorTest
         if (VectorMinTest<sbyte>.VectorMin(-2, 3, -2) != Pass) returnVal = Fail;
         if (VectorMinTest<uint>.VectorMin(0x80000000u, 0x40000000u, 0x40000000u) != Pass) returnVal = Fail;
         if (VectorMinTest<ulong>.VectorMin(2ul, 3ul, 2ul) != Pass) returnVal = Fail;
+
+        JitLog jitLog = new JitLog();
+        if (!jitLog.Check("Min", "Single")) returnVal = Fail;
+        if (!jitLog.Check("Min", "Double")) returnVal = Fail;
+        if (!jitLog.Check("Min", "Int32")) returnVal = Fail;
+        if (!jitLog.Check("Min", "Int64")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector4:Min")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector3:Min")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector2:Min")) returnVal = Fail;
+        if (!jitLog.Check("Min", "UInt16")) returnVal = Fail;
+        if (!jitLog.Check("Min", "Byte")) returnVal = Fail;
+        if (!jitLog.Check("Min", "Int16")) returnVal = Fail;
+        if (!jitLog.Check("Min", "SByte")) returnVal = Fail;
+        if (!jitLog.Check("Min", "UInt32")) returnVal = Fail;
+        if (!jitLog.Check("Min", "UInt64")) returnVal = Fail;
+        jitLog.Dispose();
+
         return returnVal;
     }
 }
index e191f25..64698ad 100644 (file)
@@ -119,6 +119,18 @@ internal partial class VectorTest
             returnVal = Fail;
         if (VectorMulTest<ulong>.VectorMul(2ul, 3ul, 2ul * 3ul, (2ul * 3ul) * (2ul * 3ul), (3ul * 3ul)) != Pass)
             returnVal = Fail;
+
+        JitLog jitLog = new JitLog();
+        // Multiply is supported only for float, double, int and short
+        if (!jitLog.Check("op_Multiply", "Single")) returnVal = Fail;
+        if (!jitLog.Check("op_Multiply", "Double")) returnVal = Fail;
+        if (!jitLog.Check("op_Multiply", "Int32")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector4:op_Multiply")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector3:op_Multiply")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector2:op_Multiply")) returnVal = Fail;
+        if (!jitLog.Check("op_Multiply", "Int16")) returnVal = Fail;
+        jitLog.Dispose();
+
         return returnVal;
     }
 }
index 70342f3..dc5c2a9 100644 (file)
@@ -155,6 +155,128 @@ internal partial class VectorTest
         if (VectorRelopTest<sbyte>.VectorRelOp(-2, -3) != Pass) returnVal = Fail;
         if (VectorRelopTest<uint>.VectorRelOp(3u, 2u) != Pass) returnVal = Fail;
         if (VectorRelopTest<ulong>.VectorRelOp(3ul, 2ul) != Pass) returnVal = Fail;
+
+        JitLog jitLog = new JitLog();
+
+        // ConditionalSelect, LessThanOrEqual and GreaterThanOrEqual are defined
+        // on the Vector type, so the overloads can't be distinguished.
+        // 
+        if (!jitLog.Check("System.Numerics.Vector:ConditionalSelect(struct,struct,struct):struct")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector:LessThanOrEqual(struct,struct):struct")) returnVal = Fail;
+        if (!jitLog.Check("System.Numerics.Vector:GreaterThanOrEqual(struct,struct):struct")) returnVal = Fail;
+
+        if (!jitLog.Check("Equals", "Single")) returnVal = Fail;
+        if (!jitLog.Check("LessThan", "Single")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "Single")) returnVal = Fail;
+        if (!jitLog.Check("op_BitwiseAnd", "Single")) returnVal = Fail;
+        if (!jitLog.Check("op_ExclusiveOr", "Single")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "Single")) returnVal = Fail;
+        // This relies on an implementation detail - i.e. that the One and Zero property are implemented
+        // in the library by GetOneValue and GetZeroValue, respectively.
+        if (!jitLog.Check("GetOneValue", "Single")) returnVal = Fail;
+        if (!jitLog.Check("GetZeroValue", "Single")) returnVal = Fail;
+
+        if (!jitLog.Check("Equals", "Double")) returnVal = Fail;
+        if (!jitLog.Check("LessThan", "Double")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "Double")) returnVal = Fail;
+        if (!jitLog.Check("op_BitwiseAnd", "Double")) returnVal = Fail;
+        if (!jitLog.Check("op_ExclusiveOr", "Double")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "Double")) returnVal = Fail;
+        // This relies on an implementation detail - i.e. that the One and Zero property are implemented
+        // in the library by GetOneValue and GetZeroValue, respectively.
+        if (!jitLog.Check("GetOneValue", "Double")) returnVal = Fail;
+        if (!jitLog.Check("GetZeroValue", "Double")) returnVal = Fail;
+
+        if (!jitLog.Check("Equals", "Int32")) returnVal = Fail;
+        if (!jitLog.Check("LessThan", "Int32")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "Int32")) returnVal = Fail;
+        if (!jitLog.Check("op_BitwiseAnd", "Int32")) returnVal = Fail;
+        if (!jitLog.Check("op_ExclusiveOr", "Int32")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "Int32")) returnVal = Fail;
+        // This relies on an implementation detail - i.e. that the One and Zero property are implemented
+        // in the library by GetOneValue and GetZeroValue, respectively.
+        if (!jitLog.Check("GetOneValue", "Int32")) returnVal = Fail;
+        if (!jitLog.Check("GetZeroValue", "Int32")) returnVal = Fail;
+
+        if (!jitLog.Check("Equals", "Int64")) returnVal = Fail;
+        if (!jitLog.Check("LessThan", "Int64")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "Int64")) returnVal = Fail;
+        if (!jitLog.Check("op_BitwiseAnd", "Int64")) returnVal = Fail;
+        if (!jitLog.Check("op_ExclusiveOr", "Int64")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "Int64")) returnVal = Fail;
+        // This relies on an implementation detail - i.e. that the One and Zero property are implemented
+        // in the library by GetOneValue and GetZeroValue, respectively.
+        if (!jitLog.Check("GetOneValue", "Int64")) returnVal = Fail;
+        if (!jitLog.Check("GetZeroValue", "Int64")) returnVal = Fail;
+
+        if (!jitLog.Check("Equals", "UInt16")) returnVal = Fail;
+        if (!jitLog.Check("LessThan", "UInt16")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "UInt16")) returnVal = Fail;
+        if (!jitLog.Check("op_BitwiseAnd", "UInt16")) returnVal = Fail;
+        if (!jitLog.Check("op_ExclusiveOr", "UInt16")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "UInt16")) returnVal = Fail;
+        // This relies on an implementation detail - i.e. that the One and Zero property are implemented
+        // in the library by GetOneValue and GetZeroValue, respectively.
+        if (!jitLog.Check("GetOneValue", "UInt16")) returnVal = Fail;
+        if (!jitLog.Check("GetZeroValue", "UInt16")) returnVal = Fail;
+
+        if (!jitLog.Check("Equals", "Byte")) returnVal = Fail;
+        if (!jitLog.Check("LessThan", "Byte")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "Byte")) returnVal = Fail;
+        if (!jitLog.Check("op_BitwiseAnd", "Byte")) returnVal = Fail;
+        if (!jitLog.Check("op_ExclusiveOr", "Byte")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "Byte")) returnVal = Fail;
+        // This relies on an implementation detail - i.e. that the One and Zero property are implemented
+        // in the library by GetOneValue and GetZeroValue, respectively.
+        if (!jitLog.Check("GetOneValue", "Byte")) returnVal = Fail;
+        if (!jitLog.Check("GetZeroValue", "Byte")) returnVal = Fail;
+
+        if (!jitLog.Check("Equals", "Int16")) returnVal = Fail;
+        if (!jitLog.Check("LessThan", "Int16")) returnVal = Fail;
+        if (!jitLog.Check("op_BitwiseAnd", "Int16")) returnVal = Fail;
+        if (!jitLog.Check("op_ExclusiveOr", "Int16")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "Int16")) returnVal = Fail;
+        // This relies on an implementation detail - i.e. that the One and Zero property are implemented
+        // in the library by GetOneValue and GetZeroValue, respectively.
+        if (!jitLog.Check("GetOneValue", "Int16")) returnVal = Fail;
+        if (!jitLog.Check("GetZeroValue", "Int16")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "Int16")) returnVal = Fail;
+
+        if (!jitLog.Check("Equals", "SByte")) returnVal = Fail;
+        if (!jitLog.Check("LessThan", "SByte")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "SByte")) returnVal = Fail;
+        if (!jitLog.Check("op_BitwiseAnd", "SByte")) returnVal = Fail;
+        if (!jitLog.Check("op_ExclusiveOr", "SByte")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "SByte")) returnVal = Fail;
+        // This relies on an implementation detail - i.e. that the One and Zero property are implemented
+        // in the library by GetOneValue and GetZeroValue, respectively.
+        if (!jitLog.Check("GetOneValue", "SByte")) returnVal = Fail;
+        if (!jitLog.Check("GetZeroValue", "SByte")) returnVal = Fail;
+
+        if (!jitLog.Check("Equals", "UInt32")) returnVal = Fail;
+        if (!jitLog.Check("LessThan", "UInt32")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "UInt32")) returnVal = Fail;
+        if (!jitLog.Check("op_BitwiseAnd", "UInt32")) returnVal = Fail;
+        if (!jitLog.Check("op_ExclusiveOr", "UInt32")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "UInt32")) returnVal = Fail;
+        // This relies on an implementation detail - i.e. that the One and Zero property are implemented
+        // in the library by GetOneValue and GetZeroValue, respectively.
+        if (!jitLog.Check("GetOneValue", "UInt32")) returnVal = Fail;
+        if (!jitLog.Check("GetZeroValue", "UInt32")) returnVal = Fail;
+
+        if (!jitLog.Check("Equals", "UInt64")) returnVal = Fail;
+        if (!jitLog.Check("LessThan", "UInt64")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "UInt64")) returnVal = Fail;
+        if (!jitLog.Check("op_BitwiseAnd", "UInt64")) returnVal = Fail;
+        if (!jitLog.Check("op_ExclusiveOr", "UInt64")) returnVal = Fail;
+        if (!jitLog.Check("GreaterThan", "UInt64")) returnVal = Fail;
+        // This relies on an implementation detail - i.e. that the One and Zero property are implemented
+        // in the library by GetOneValue and GetZeroValue, respectively.
+        if (!jitLog.Check("GetOneValue", "UInt64")) returnVal = Fail;
+        if (!jitLog.Check("GetZeroValue", "UInt64")) returnVal = Fail;
+
+        jitLog.Dispose();
+
         return returnVal;
     }
 }
index a84e0c3..d1b669d 100644 (file)
@@ -5,6 +5,7 @@
 
 using System;
 using System.Numerics;
+using System.IO;
 
 internal partial class VectorTest
 {
@@ -212,4 +213,141 @@ internal partial class VectorTest
         }
         return result;
     }
+
+}
+
+class JitLog : IDisposable
+{
+    FileStream      fileStream;
+    bool            simdIntrinsicsSupported;
+
+    private static String GetLogFileName()
+    {
+        String jitLogFileName = Environment.GetEnvironmentVariable("COMPlus_JitFuncInfoLogFile");
+        return jitLogFileName;
+    }
+
+    public JitLog()
+    {
+        fileStream = null;
+        simdIntrinsicsSupported = Vector.IsHardwareAccelerated;
+        String jitLogFileName = GetLogFileName();
+        if (jitLogFileName == null)
+        {
+            Console.WriteLine("No JitLogFile");
+            return;
+        }
+        if (!File.Exists(jitLogFileName))
+        {
+            Console.WriteLine("JitLogFile " + jitLogFileName + " not found.");
+            return;
+        }
+        File.Copy(jitLogFileName, "Temp.log", true);
+        fileStream = new FileStream("Temp.log", FileMode.Open, FileAccess.Read, FileShare.Read);
+    }
+
+    public void Dispose()
+    {
+        if (fileStream != null)
+        {
+            fileStream.Dispose();
+        }
+    }
+    public bool IsEnabled()
+    {
+        return (fileStream != null);
+    }
+
+    //------------------------------------------------------------------------
+    // Check: Check to see whether 'method' was recognized as an intrinsic by the JIT.
+    //
+    // Arguments:
+    //    method - The method name, as a string
+    //
+    // Return Value:
+    //    If the JitLog is not enabled (either the environment variable is not set,
+    //    or the file was not found, e.g. if the JIT doesn't support it):
+    //     - Returns true
+    //    If SIMD intrinsics are enabled:
+    //     - Returns true if the method was NOT compiled, otherwise false
+    //    Else (if SIMD intrinsics are NOT enabled):
+    //     - Returns true.
+    //       Note that it might be useful to return false if the method was not compiled,
+    //       but it will not be logged as compiled if it is inlined.
+    //
+    // Assumptions:
+    //    The JitLog constructor queries Vector.IsHardwareAccelerated to determine
+    //    if SIMD intrinsics are enabled, and depends on its correctness.
+    //
+    // Notes:
+    //    It searches for the string verbatim. If 'method' is not fully qualified
+    //    or its signature is not provided, it may result in false matches.
+    //
+    // Example:
+    //    CheckJitLog("System.Numerics.Vector4:op_Addition(struct,struct):struct");
+    //
+    public bool Check(String method)
+    {
+        // Console.WriteLine("Checking for " + method + ":");
+        if (!IsEnabled())
+        {
+            Console.WriteLine("JitLog not enabled.");
+            return true;
+        }
+        try
+        {
+            fileStream.Position = 0;
+            StreamReader reader = new StreamReader(fileStream);
+            bool methodFound = false;
+            while ((reader.Peek() >= 0) && (methodFound == false))
+            {
+                String s = reader.ReadLine();
+                if (s.IndexOf(method) != -1)
+                {
+                    methodFound = true;
+                }
+            }
+            if (simdIntrinsicsSupported && methodFound)
+            {
+                Console.WriteLine("Method " + method + " was compiled but should not have been\n");
+                return false;
+            }
+            // Useful when developing / debugging just to be sure that we reached here:
+            // Console.WriteLine(method + ((methodFound) ? " WAS COMPILED" : " WAS NOT COMPILED"));
+            return true;
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine("Error checking JitLogFile: " + e.Message);
+            return false;
+        }
+    }
+
+    // Check: Check to see Vector<'elementType'>:'method' was recognized as an
+    //        intrinsic by the JIT.
+    //
+    // Arguments:
+    //    method - The method name, without its containing type (which is Vector<T>)
+    //    elementType - The type with which Vector<T> is instantiated.
+    //
+    // Return Value:
+    //    See the other overload, above.
+    //
+    // Assumptions:
+    //    The JitLog constructor queries Vector.IsHardwareAccelerated to determine
+    //    if SIMD intrinsics are enabled, and depends on its correctness.
+    //
+    // Notes:
+    //    It constructs the search string based on the way generic types are currently
+    //    dumped by the CLR. If the signature is not provided for the method, it
+    //    may result in false matches.
+    //
+    // Example:
+    //    CheckJitLog("op_Addition(struct,struct):struct", "Single");
+    //
+    public bool Check(String method, String elementType)
+    {
+        String checkString = "System.Numerics.Vector`1[" + elementType + "][System." + elementType + "]:" + method;
+        return Check(checkString);
+    }
 }
diff --git a/tests/src/JIT/SIMD/dir.props b/tests/src/JIT/SIMD/dir.props
new file mode 100644 (file)
index 0000000..1ddaf2f
--- /dev/null
@@ -0,0 +1,21 @@
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\dir.props" />
+
+  <PropertyGroup>
+    <CLRTestBatchPreCommands>
+      <![CDATA[
+$(CLRTestBatchPreCommands)
+set COMPlus_JitFuncInfoLogFile=SIMD.log
+if EXIST SIMD.log (del SIMD.log)
+]]>
+    </CLRTestBatchPreCommands>
+    <BashCLRTestPreCommands>
+      <![CDATA[
+$(BashCLRTestPreCommands)
+export COMPlus_JitFuncInfoLogFile=SIMD.log
+rm -f SIMD.log
+]]>
+    </BashCLRTestPreCommands>
+  </PropertyGroup>
+
+</Project>
index e126d13..42239af 100644 (file)
@@ -9,7 +9,9 @@
     "System.Runtime.Extensions": "4.0.10",
     "System.Runtime.InteropServices": "4.1.0-rc3-24117-00",
     "System.Threading": "4.0.10",
-    "System.Threading.Thread": "4.0.0-rc3-24117-00"
+    "System.Threading.Thread": "4.0.0-rc3-24117-00",
+    "System.IO": "4.0.10",
+    "System.IO.FileSystem": "4.0.1-rc3-24117-00",
   },
   "frameworks": {
     "dnxcore50": {}