Uh oh!
There was an error while loading. Please reload this page.
Add long/ulong->float cast helpers - #114597
Conversation
AaronRobinsonMSFT
commented
Apr 12, 2025
/cc @dotnet/jit-contrib |
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
Uh oh!
There was an error while loading. Please reload this page.
jit-format is failing due to changes from #114525. cc @kunalspathak (fixed in #114603) |
jkotas
commented
Apr 22, 2025
The VM side of the changes LGTM |
BruceForstall
commented
May 2, 2025
@saucecontrol Please merge and resolve conflicts. |
Uh oh!
There was an error while loading. Please reload this page.
tannergooding
left a comment
There was a problem hiding this comment.
CC. @dotnet/jit-contrib, @jakobbotsch for secondary review
EgorBo
left a comment
There was a problem hiding this comment.
LGTM, let's just in case kick off a few outerloops
EgorBo
commented
May 20, 2025
/azp run runtime-coreclr jitstress-isas-x86, runtime-coreclr jitstress-isas-arm, Fuzzlyn, runtime-coreclr jitstress-isas-avx512 |
|
Azure Pipelines successfully started running 4 pipeline(s). |
tannergooding
commented
May 22, 2025
Failures are unrelated. Logged issues for the new ones Fuzzlyn discovered |
* add long/ulong->float cast helpers * fix const folding
Resolves#106646
We currently have a few inconsistencies in the way long/ulong to float conversions are done in JIT.
Problem 1
On 64-bit platforms,
long->floatconversions have always been done directly with a native CPU instruction, while on 32-bit,long->floathas always been morphed tolong->double->floatso that it could useCORINFO_HELP_LNG2DBL.This can lead to different conversion results when the
long->doubleconversion rounds in a different direction thanlong->floatwould. Ex: sharplab.Similarly,
ulong->floatmay yield a different result thanulong->double->float.Problem 2
In CIL, there is no way to represent a conversion directly from unsigned to float or double. The IL instruction
conv.r.unspecifies unsigned conversion to IL typeFwhich is of indeterminate precision. Consequently, managed language compilers emit a pair of instructions for these casts:conv.r.un; conv.r4orconv.r.un; conv.r8.The JIT importer has always treated
conv.r.unasunsigned->double, so in the case ofconv.r.un; conv.r8, the second (double->double) cast is skipped, and the intention of the managed compiler is preserved.conv.r.un; conv.r4, on the other hand, imports asunsigned->double->float.As stated above, this could yield a different result than intended for
ulong.Problem 3
When Arm64 support was added to JIT, as an optimization to take advantage of the fact Arm64 has a direct
ulong->floatconversion instruction, recognition of theulong->double->floatpattern was added to JIT, and the intermediate cast was removed. This led to Arm64 having different cast behavior than all other platforms.#84384 extended the same optimization to x64 in .NET 8, using AVX-512 instructions. This led to further fragmentation of behavior since the presence or absence of AVX-512 could change results.
#111595 unified the behavior on x64 by emulating the direct
ulong->floatcast using SSE instructions.However, this still leaves problem 1 (32-bit still goes through
CORINFO_HELP_ULNG2DBL) and introduces another: The intermediate double cast may have actually been intentional, and the current optimization removes it without knowing. i.e.conv.r.un; conv.r4andconv.r.un; conv.r8; conv.r4are treated the same.The solution
This PR adds JIT helpers to perform
long->floatandulong->floatcasts directly for 32-bit platforms.It also modifies JIT to specifically look for the
conv.r.un; conv.r4sequence and import it asunsigned->float, and then calls the new helpers as appropriate.Next steps
Because this requires a JIT-EE GUID change, I have broken the solution into two parts.
This part solves problems 1 and 2 by making sure all platforms can consistently recognize and perform the long/ulong->float casts directly.
I will address problem 3 in a followup PR, along with some more cleanup, optimization, and added tests. The current bad optimization also catches some redundant casts that will need to be handled differently, and it will be easier to see the impact of all those changes if the SPMI asmdiff jobs work.