Use HW-intrinsics in BitConverter for double <-> long / float <-> int (#33476)
authorGünther Foidl <gue@korporal.at>
Fri, 20 Mar 2020 15:31:20 +0000 (16:31 +0100)
committerGitHub <noreply@github.com>
Fri, 20 Mar 2020 15:31:20 +0000 (08:31 -0700)
* Use hw-intrinsics in BitConverter for double <-> long and float <-> int to emit movd instead of using the stack

* Added comment for workaround

Cf. https://github.com/dotnet/runtime/pull/33476#issuecomment-600937760

src/libraries/System.Private.CoreLib/src/System/BitConverter.cs

index 25719466ddb09231a8944d2c4180f22e580944e4..bf604f41a97d60a3c873e7e53079f69342f87e0f 100644 (file)
@@ -4,6 +4,8 @@
 
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
 
 using Internal.Runtime.CompilerServices;
 
@@ -449,24 +451,52 @@ namespace System
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static unsafe long DoubleToInt64Bits(double value)
         {
+            // Workaround for https://github.com/dotnet/runtime/issues/11413
+            if (Sse2.X64.IsSupported)
+            {
+                Vector128<long> vec = Vector128.CreateScalarUnsafe(value).AsInt64();
+                return Sse2.X64.ConvertToInt64(vec);
+            }
+
             return *((long*)&value);
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static unsafe double Int64BitsToDouble(long value)
         {
+            // Workaround for https://github.com/dotnet/runtime/issues/11413
+            if (Sse2.X64.IsSupported)
+            {
+                Vector128<double> vec = Vector128.CreateScalarUnsafe(value).AsDouble();
+                return vec.ToScalar();
+            }
+
             return *((double*)&value);
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static unsafe int SingleToInt32Bits(float value)
         {
+            // Workaround for https://github.com/dotnet/runtime/issues/11413
+            if (Sse2.IsSupported)
+            {
+                Vector128<int> vec = Vector128.CreateScalarUnsafe(value).AsInt32();
+                return Sse2.ConvertToInt32(vec);
+            }
+
             return *((int*)&value);
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static unsafe float Int32BitsToSingle(int value)
         {
+            // Workaround for https://github.com/dotnet/runtime/issues/11413
+            if (Sse2.IsSupported)
+            {
+                Vector128<float> vec = Vector128.CreateScalarUnsafe(value).AsSingle();
+                return vec.ToScalar();
+            }
+
             return *((float*)&value);
         }
     }