goto CNS_LONG;
case TYP_FLOAT:
+ {
+#if defined(TARGET_64BIT)
+ if (tree->IsUnsigned())
+ {
+ f1 = (float)UINT32(i1);
+ }
+ else
+ {
+ f1 = (float)INT32(i1);
+ }
+#else
+ // 32-bit currently does a 2-step conversion, which is incorrect
+ // but which we are going to take a breaking change around early
+ // in a release cycle.
+
if (tree->IsUnsigned())
{
f1 = forceCastToFloat(UINT32(i1));
{
f1 = forceCastToFloat(INT32(i1));
}
+#endif
+
d1 = f1;
goto CNS_DOUBLE;
+ }
case TYP_DOUBLE:
+ {
if (tree->IsUnsigned())
{
d1 = (double)UINT32(i1);
d1 = (double)INT32(i1);
}
goto CNS_DOUBLE;
+ }
default:
assert(!"Bad CastToType() in gtFoldExprConst() for a cast from int");
goto CNS_LONG;
case TYP_FLOAT:
- case TYP_DOUBLE:
+ {
+#if defined(TARGET_64BIT)
if (tree->IsUnsigned() && (lval1 < 0))
{
- d1 = FloatingPointUtils::convertUInt64ToDouble((unsigned __int64)lval1);
+ f1 = FloatingPointUtils::convertUInt64ToFloat((unsigned __int64)lval1);
}
else
{
- d1 = (double)lval1;
+ f1 = (float)lval1;
+ }
+#else
+ // 32-bit currently does a 2-step conversion, which is incorrect
+ // but which we are going to take a breaking change around early
+ // in a release cycle.
+
+ if (tree->IsUnsigned() && (lval1 < 0))
+ {
+ f1 = forceCastToFloat(
+ FloatingPointUtils::convertUInt64ToDouble((unsigned __int64)lval1));
+ }
+ else
+ {
+ f1 = forceCastToFloat((double)lval1);
}
+#endif
+
+ d1 = f1;
+ goto CNS_DOUBLE;
+ }
- if (tree->CastToType() == TYP_FLOAT)
+ case TYP_DOUBLE:
+ {
+ if (tree->IsUnsigned() && (lval1 < 0))
+ {
+ d1 = FloatingPointUtils::convertUInt64ToDouble((unsigned __int64)lval1);
+ }
+ else
{
- f1 = forceCastToFloat(d1); // truncate precision
- d1 = f1;
+ d1 = (double)lval1;
}
goto CNS_DOUBLE;
+ }
default:
assert(!"Bad CastToType() in gtFoldExprConst() for a cast from long");
return tree;
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+public class Runtime_90323
+{
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static float ConvertToSingle(long value) => (float)value;
+
+ // 32-bit currently performs a 2-step conversion which causes a different result to be produced
+ [ConditionalFact(typeof(TestLibrary.PlatformDetection), nameof(TestLibrary.PlatformDetection.Is64BitProcess))]
+ public static int TestEntryPoint()
+ {
+ bool passed = true;
+
+ long value = 0x4000_0040_0000_0001L;
+
+ if (ConvertToSingle(value) != (float)(value))
+ {
+ Console.WriteLine($"Mismatch between codegen and constant folding: {ConvertToSingle(value)} != {(float)(value)}");
+ passed = false;
+ }
+
+ if (BitConverter.SingleToUInt32Bits((float)(value)) != 0x5E80_0001) // 4.6116866E+18f
+ {
+ Console.WriteLine($"Mismatch between constant folding and expected value: {(float)(value)} != 4.6116866E+18f; 0x{BitConverter.SingleToUInt32Bits((float)(value)):X8} != 0x5E800001");
+ passed = false;
+ }
+
+ return passed ? 100 : 0;
+ }
+}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <Optimize>True</Optimize>
+ <!-- Needed for CLRTestEnvironmentVariable -->
+ <RequiresProcessIsolation>true</RequiresProcessIsolation>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="$(MSBuildProjectName).cs" />
+ <CLRTestEnvironmentVariable Include="DOTNET_TieredCompilation" Value="1" />
+ <ProjectReference Include="$(TestLibraryProjectPath)" />
+ </ItemGroup>
+</Project>