Fixing the codegen for x64 intrinsics to use EA_8BYTE where needed. (#23461)
authorTanner Gooding <tagoo@outlook.com>
Wed, 27 Mar 2019 10:33:56 +0000 (03:33 -0700)
committerGitHub <noreply@github.com>
Wed, 27 Mar 2019 10:33:56 +0000 (03:33 -0700)
src/jit/hwintrinsiccodegenxarch.cpp
src/jit/hwintrinsiclistxarch.h
tests/src/JIT/HardwareIntrinsics/X86/Regression/GitHub_23438/GitHub_23438.cs [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Regression/GitHub_23438/GitHub_23438_r.csproj [new file with mode: 0644]
tests/src/JIT/HardwareIntrinsics/X86/Regression/GitHub_23438/GitHub_23438_ro.csproj [new file with mode: 0644]

index 9eada1e..aa30f76 100644 (file)
@@ -1433,6 +1433,17 @@ void CodeGen::genSSEIntrinsic(GenTreeHWIntrinsic* node)
             break;
         }
 
+        case NI_SSE_X64_ConvertToInt64:
+        case NI_SSE_X64_ConvertToInt64WithTruncation:
+        {
+            assert(targetType == TYP_LONG);
+            assert(op1 != nullptr);
+            assert(op2 == nullptr);
+            instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
+            genHWIntrinsic_R_RM(node, ins, EA_8BYTE);
+            break;
+        }
+
         case NI_SSE_X64_ConvertScalarToVector128Single:
         {
             assert(baseType == TYP_LONG);
@@ -1623,8 +1634,9 @@ void CodeGen::genSSE2Intrinsic(GenTreeHWIntrinsic* node)
         case NI_SSE2_ConvertToInt32:
         case NI_SSE2_ConvertToInt32WithTruncation:
         case NI_SSE2_ConvertToUInt32:
-        case NI_SSE2_X64_ConvertToUInt64:
         case NI_SSE2_X64_ConvertToInt64:
+        case NI_SSE2_X64_ConvertToInt64WithTruncation:
+        case NI_SSE2_X64_ConvertToUInt64:
         {
             assert(op2 == nullptr);
             instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType);
index 6434831..de177f3 100644 (file)
@@ -160,8 +160,8 @@ HARDWARE_INTRINSIC(SSE_Xor,                                         "Xor",
 // ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
 //  SSE 64-bit-only Intrinsics
 HARDWARE_INTRINSIC(SSE_X64_IsSupported,                             "get_IsSupported",                              SSE_X64,      -1,               0,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_IsSupportedProperty,    HW_Flag_NoFlag)
-HARDWARE_INTRINSIC(SSE_X64_ConvertToInt64,                          "ConvertToInt64",                               SSE_X64,      -1,              16,           1,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_cvtss2si,       INS_invalid},           HW_Category_SIMDScalar,             HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE_X64_ConvertToInt64WithTruncation,            "ConvertToInt64WithTruncation",                 SSE_X64,      -1,              16,           1,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_cvttss2si,      INS_invalid},           HW_Category_SIMDScalar,             HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE_X64_ConvertToInt64,                          "ConvertToInt64",                               SSE_X64,      -1,              16,           1,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_cvtss2si,       INS_invalid},           HW_Category_SIMDScalar,             HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen)
+HARDWARE_INTRINSIC(SSE_X64_ConvertToInt64WithTruncation,            "ConvertToInt64WithTruncation",                 SSE_X64,      -1,              16,           1,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_cvttss2si,      INS_invalid},           HW_Category_SIMDScalar,             HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen)
 HARDWARE_INTRINSIC(SSE_X64_ConvertScalarToVector128Single,          "ConvertScalarToVector128Single",               SSE_X64,      -1,              16,           2,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_cvtsi2ss,       INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_SIMDScalar,             HW_Flag_BaseTypeFromSecondArg|HW_Flag_CopyUpperBits|HW_Flag_SpecialCodeGen)
 
 // ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
@@ -281,7 +281,7 @@ HARDWARE_INTRINSIC(SSE2_Xor,                                        "Xor",
 //  SSE2 64-bit-only Intrinsics
 HARDWARE_INTRINSIC(SSE2_X64_IsSupported,                            "get_IsSupported",                              SSE2_X64,     -1,               0,           0,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_IsSupportedProperty,    HW_Flag_NoFlag)
 HARDWARE_INTRINSIC(SSE2_X64_ConvertToInt64,                         "ConvertToInt64",                               SSE2_X64,     -1,              16,           1,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_mov_xmm2i,      INS_invalid,        INS_invalid,        INS_cvtsd2si},          HW_Category_SIMDScalar,             HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE2_X64_ConvertToInt64WithTruncation,           "ConvertToInt64WithTruncation",                 SSE2_X64,     -1,              16,           1,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_cvttsd2si},         HW_Category_SIMDScalar,             HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE2_X64_ConvertToInt64WithTruncation,           "ConvertToInt64WithTruncation",                 SSE2_X64,     -1,              16,           1,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_cvttsd2si},         HW_Category_SIMDScalar,             HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
 HARDWARE_INTRINSIC(SSE2_X64_ConvertToUInt64,                        "ConvertToUInt64",                              SSE2_X64,     -1,              16,           1,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_mov_xmm2i,      INS_invalid,        INS_invalid},           HW_Category_SIMDScalar,             HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
 HARDWARE_INTRINSIC(SSE2_X64_ConvertScalarToVector128Double,         "ConvertScalarToVector128Double",               SSE2_X64,     -1,              16,           2,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_cvtsi2sd,       INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_SIMDScalar,             HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg)
 HARDWARE_INTRINSIC(SSE2_X64_ConvertScalarToVector128Int64,          "ConvertScalarToVector128Int64",                SSE2_X64,     -1,              16,           1,     {INS_invalid,           INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_invalid,        INS_mov_i2xmm,      INS_invalid,        INS_invalid,        INS_invalid},           HW_Category_SIMDScalar,             HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen)
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Regression/GitHub_23438/GitHub_23438.cs b/tests/src/JIT/HardwareIntrinsics/X86/Regression/GitHub_23438/GitHub_23438.cs
new file mode 100644 (file)
index 0000000..6f31d1a
--- /dev/null
@@ -0,0 +1,184 @@
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace GitHub_23438
+{
+    public static class Program
+    {
+        private const int Pass = 100;
+        private const int Fail = 0;
+
+        public static int Main(string[] args)
+        {
+            bool succeeded = true;
+
+            if (Sse.X64.IsSupported)
+            {
+                succeeded &= TestSseX64ConvertScalarToVector128Single();
+                succeeded &= TestSseX64ConvertToInt64();
+                succeeded &= TestSseX64ConvertToInt64WithTruncation();
+            }
+
+            if (Sse2.X64.IsSupported)
+            {
+                succeeded &= TestSse2X64ConvertScalarToVector128Double();
+                succeeded &= TestSse2X64ConvertScalarToVector128Int64();
+                succeeded &= TestSse2X64ConvertScalarToVector128UInt64();
+                succeeded &= TestSse2X64ConvertToInt64_Vector128Double();
+                succeeded &= TestSse2X64ConvertToInt64_Vector128Int64();
+                succeeded &= TestSse2X64ConvertToInt64WithTruncation();
+                succeeded &= TestSse2X64ConvertToUInt64();
+                succeeded &= TestSse2X64StoreNonTemporal_Int64();
+                succeeded &= TestSse2X64StoreNonTemporal_UInt64();
+            }
+
+            if (Sse41.X64.IsSupported)
+            {
+                succeeded &= TestSse41X64Extract_Int64();
+                succeeded &= TestSse41X64Extract_UInt64();
+                succeeded &= TestSse41X64Insert_Int64();
+                succeeded &= TestSse41X64Insert_UInt64();
+            }
+
+            return succeeded ? Pass : Fail;
+        }
+
+        private static bool AreEqual(long expectedResult, long actualResult, [CallerMemberName] string methodName = "")
+        {
+            bool areEqual = (expectedResult == actualResult);
+
+            if (!areEqual)
+            {
+                Console.WriteLine($"{methodName} failed. Expected: {expectedResult}; Actual: {actualResult}");
+            }
+
+            return areEqual;
+        }
+
+        private static bool AreEqual(ulong expectedResult, ulong actualResult, [CallerMemberName] string methodName = "")
+        {
+            bool areEqual = (expectedResult == actualResult);
+
+            if (!areEqual)
+            {
+                Console.WriteLine($"{methodName} failed. Expected: {expectedResult}; Actual: {actualResult}");
+            }
+
+            return areEqual;
+        }
+
+        private static bool TestSseX64ConvertScalarToVector128Single()
+        {
+            Vector128<float> val = Sse.X64.ConvertScalarToVector128Single(Vector128<float>.Zero, long.MaxValue);
+            float result = val.GetElement(0);
+            return AreEqual(0x5F000000, BitConverter.SingleToInt32Bits(result));
+        }
+
+        private static bool TestSseX64ConvertToInt64()
+        {
+            Vector128<float> val = Vector128.CreateScalar((float)long.MaxValue);
+            long result = Sse.X64.ConvertToInt64(val);
+            return AreEqual(long.MinValue, result);
+        }
+
+        private static bool TestSseX64ConvertToInt64WithTruncation()
+        {
+            Vector128<float> val = Vector128.CreateScalar((float)long.MaxValue);
+            long result = Sse.X64.ConvertToInt64WithTruncation(val);
+            return AreEqual(long.MinValue, result);
+        }
+
+        private static bool TestSse2X64ConvertScalarToVector128Double()
+        {
+            Vector128<double> val = Sse2.X64.ConvertScalarToVector128Double(Vector128<double>.Zero, long.MaxValue);
+            double result = val.GetElement(0);
+            return AreEqual(0x43E0000000000000, BitConverter.DoubleToInt64Bits(result));
+        }
+
+        private static bool TestSse2X64ConvertScalarToVector128Int64()
+        {
+            Vector128<long> val = Sse2.X64.ConvertScalarToVector128Int64(long.MaxValue);
+            long result = val.GetElement(0);
+            return AreEqual(long.MaxValue, result);
+        }
+
+        private static bool TestSse2X64ConvertScalarToVector128UInt64()
+        {
+            Vector128<ulong> val = Sse2.X64.ConvertScalarToVector128UInt64(ulong.MaxValue);
+            ulong result = val.GetElement(0);
+            return AreEqual(ulong.MaxValue, result);
+        }
+
+        private static bool TestSse2X64ConvertToInt64_Vector128Double()
+        {
+            Vector128<double> val = Vector128.CreateScalar((double)long.MaxValue);
+            long result = Sse2.X64.ConvertToInt64(val);
+            return AreEqual(long.MinValue, result);
+        }
+
+        private static bool TestSse2X64ConvertToInt64_Vector128Int64()
+        {
+            Vector128<long> val = Vector128.CreateScalar(long.MaxValue);
+            long result = Sse2.X64.ConvertToInt64(val);
+            return AreEqual(long.MaxValue, result);
+        }
+
+        private static bool TestSse2X64ConvertToInt64WithTruncation()
+        {
+            Vector128<double> val = Vector128.CreateScalar((double)long.MaxValue);
+            long result = Sse2.X64.ConvertToInt64WithTruncation(val);
+            return AreEqual(long.MinValue, result);
+        }
+
+        private static bool TestSse2X64ConvertToUInt64()
+        {
+            Vector128<ulong> val = Vector128.CreateScalar(ulong.MaxValue);
+            ulong result = Sse2.X64.ConvertToUInt64(val);
+            return AreEqual(ulong.MaxValue, result);
+        }
+
+        private static unsafe bool TestSse2X64StoreNonTemporal_Int64()
+        {
+            long result;
+            Sse2.X64.StoreNonTemporal(&result, long.MaxValue);
+            return AreEqual(long.MaxValue, result);
+        }
+
+        private static unsafe bool TestSse2X64StoreNonTemporal_UInt64()
+        {
+            ulong result;
+            Sse2.X64.StoreNonTemporal(&result, ulong.MaxValue);
+            return AreEqual(ulong.MaxValue, result);
+        }
+
+        private static bool TestSse41X64Extract_Int64()
+        {
+            Vector128<long> val = Vector128.CreateScalar(long.MaxValue);
+            long result = Sse41.X64.Extract(val, 0);
+            return AreEqual(long.MaxValue, result);
+        }
+
+        private static bool TestSse41X64Extract_UInt64()
+        {
+            Vector128<ulong> val = Vector128.CreateScalar(ulong.MaxValue);
+            ulong result = Sse41.X64.Extract(val, 0);
+            return AreEqual(ulong.MaxValue, result);
+        }
+
+        private static bool TestSse41X64Insert_Int64()
+        {
+            Vector128<long> val = Sse41.X64.Insert(Vector128<long>.Zero, long.MaxValue, 0);
+            long result = val.GetElement(0);
+            return AreEqual(long.MaxValue, result);
+        }
+
+        private static bool TestSse41X64Insert_UInt64()
+        {
+            Vector128<ulong> val = Sse41.X64.Insert(Vector128<ulong>.Zero, ulong.MaxValue, 0);
+            ulong result = val.GetElement(0);
+            return AreEqual(ulong.MaxValue, result);
+        }
+    }
+}
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Regression/GitHub_23438/GitHub_23438_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Regression/GitHub_23438/GitHub_23438_r.csproj
new file mode 100644 (file)
index 0000000..fd5351a
--- /dev/null
@@ -0,0 +1,34 @@
+<?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>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </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>Embedded</DebugType>
+    <Optimize></Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="GitHub_23438.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Regression/GitHub_23438/GitHub_23438_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Regression/GitHub_23438/GitHub_23438_ro.csproj
new file mode 100644 (file)
index 0000000..a0cae72
--- /dev/null
@@ -0,0 +1,34 @@
+<?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>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </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>Embedded</DebugType>
+    <Optimize>True</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="GitHub_23438.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>