From 94db6145bca291313156eec40cb16518f7f9fc1d Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 27 Mar 2019 03:33:56 -0700 Subject: [PATCH] Fixing the codegen for x64 intrinsics to use EA_8BYTE where needed. (#23461) --- src/jit/hwintrinsiccodegenxarch.cpp | 14 +- src/jit/hwintrinsiclistxarch.h | 6 +- .../X86/Regression/GitHub_23438/GitHub_23438.cs | 184 +++++++++++++++++++++ .../Regression/GitHub_23438/GitHub_23438_r.csproj | 34 ++++ .../Regression/GitHub_23438/GitHub_23438_ro.csproj | 34 ++++ 5 files changed, 268 insertions(+), 4 deletions(-) create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Regression/GitHub_23438/GitHub_23438.cs create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Regression/GitHub_23438/GitHub_23438_r.csproj create mode 100644 tests/src/JIT/HardwareIntrinsics/X86/Regression/GitHub_23438/GitHub_23438_ro.csproj diff --git a/src/jit/hwintrinsiccodegenxarch.cpp b/src/jit/hwintrinsiccodegenxarch.cpp index 9eada1e..aa30f76 100644 --- a/src/jit/hwintrinsiccodegenxarch.cpp +++ b/src/jit/hwintrinsiccodegenxarch.cpp @@ -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); diff --git a/src/jit/hwintrinsiclistxarch.h b/src/jit/hwintrinsiclistxarch.h index 6434831..de177f3 100644 --- a/src/jit/hwintrinsiclistxarch.h +++ b/src/jit/hwintrinsiclistxarch.h @@ -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 index 0000000..6f31d1a --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Regression/GitHub_23438/GitHub_23438.cs @@ -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 val = Sse.X64.ConvertScalarToVector128Single(Vector128.Zero, long.MaxValue); + float result = val.GetElement(0); + return AreEqual(0x5F000000, BitConverter.SingleToInt32Bits(result)); + } + + private static bool TestSseX64ConvertToInt64() + { + Vector128 val = Vector128.CreateScalar((float)long.MaxValue); + long result = Sse.X64.ConvertToInt64(val); + return AreEqual(long.MinValue, result); + } + + private static bool TestSseX64ConvertToInt64WithTruncation() + { + Vector128 val = Vector128.CreateScalar((float)long.MaxValue); + long result = Sse.X64.ConvertToInt64WithTruncation(val); + return AreEqual(long.MinValue, result); + } + + private static bool TestSse2X64ConvertScalarToVector128Double() + { + Vector128 val = Sse2.X64.ConvertScalarToVector128Double(Vector128.Zero, long.MaxValue); + double result = val.GetElement(0); + return AreEqual(0x43E0000000000000, BitConverter.DoubleToInt64Bits(result)); + } + + private static bool TestSse2X64ConvertScalarToVector128Int64() + { + Vector128 val = Sse2.X64.ConvertScalarToVector128Int64(long.MaxValue); + long result = val.GetElement(0); + return AreEqual(long.MaxValue, result); + } + + private static bool TestSse2X64ConvertScalarToVector128UInt64() + { + Vector128 val = Sse2.X64.ConvertScalarToVector128UInt64(ulong.MaxValue); + ulong result = val.GetElement(0); + return AreEqual(ulong.MaxValue, result); + } + + private static bool TestSse2X64ConvertToInt64_Vector128Double() + { + Vector128 val = Vector128.CreateScalar((double)long.MaxValue); + long result = Sse2.X64.ConvertToInt64(val); + return AreEqual(long.MinValue, result); + } + + private static bool TestSse2X64ConvertToInt64_Vector128Int64() + { + Vector128 val = Vector128.CreateScalar(long.MaxValue); + long result = Sse2.X64.ConvertToInt64(val); + return AreEqual(long.MaxValue, result); + } + + private static bool TestSse2X64ConvertToInt64WithTruncation() + { + Vector128 val = Vector128.CreateScalar((double)long.MaxValue); + long result = Sse2.X64.ConvertToInt64WithTruncation(val); + return AreEqual(long.MinValue, result); + } + + private static bool TestSse2X64ConvertToUInt64() + { + Vector128 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 val = Vector128.CreateScalar(long.MaxValue); + long result = Sse41.X64.Extract(val, 0); + return AreEqual(long.MaxValue, result); + } + + private static bool TestSse41X64Extract_UInt64() + { + Vector128 val = Vector128.CreateScalar(ulong.MaxValue); + ulong result = Sse41.X64.Extract(val, 0); + return AreEqual(ulong.MaxValue, result); + } + + private static bool TestSse41X64Insert_Int64() + { + Vector128 val = Sse41.X64.Insert(Vector128.Zero, long.MaxValue, 0); + long result = val.GetElement(0); + return AreEqual(long.MaxValue, result); + } + + private static bool TestSse41X64Insert_UInt64() + { + Vector128 val = Sse41.X64.Insert(Vector128.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 index 0000000..fd5351a --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Regression/GitHub_23438/GitHub_23438_r.csproj @@ -0,0 +1,34 @@ + + + + + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + true + + + + + + + False + + + + Embedded + + + + + + + + + + + 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 index 0000000..a0cae72 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/X86/Regression/GitHub_23438/GitHub_23438_ro.csproj @@ -0,0 +1,34 @@ + + + + + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + true + + + + + + + False + + + + Embedded + True + + + + + + + + + + -- 2.7.4