Skip to content

Add long/ulong->float cast helpers #114597

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions docs/design/coreclr/botr/readytorun-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,7 @@ enum ReadyToRunHelper
READYTORUN_HELPER_GetString = 0x50,

// Used by /Tuning for Profile optimizations
READYTORUN_HELPER_LogMethodEnter = 0x51,
READYTORUN_HELPER_LogMethodEnter = 0x51, // Unused since READYTORUN_MAJOR_VERSION 10.0

// Reflection helpers
READYTORUN_HELPER_GetRuntimeTypeHandle = 0x54,
Expand Down Expand Up @@ -870,12 +870,14 @@ enum ReadyToRunHelper
READYTORUN_HELPER_Dbl2UIntOvf = 0xD5,
READYTORUN_HELPER_Dbl2ULng = 0xD6,
READYTORUN_HELPER_Dbl2ULngOvf = 0xD7,
READYTORUN_HELPER_Lng2Flt = 0xD8,
READYTORUN_HELPER_ULng2Flt = 0xD9,

// Floating point ops
READYTORUN_HELPER_DblRem = 0xE0,
READYTORUN_HELPER_FltRem = 0xE1,
READYTORUN_HELPER_DblRound = 0xE2,
READYTORUN_HELPER_FltRound = 0xE3,
READYTORUN_HELPER_DblRound = 0xE2, // Unused since READYTORUN_MAJOR_VERSION 10.0
READYTORUN_HELPER_FltRound = 0xE3, // Unused since READYTORUN_MAJOR_VERSION 10.0

#ifndef _TARGET_X86_
// Personality routines
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,9 @@ enum CorInfoHelpFunc
CORINFO_HELP_LMOD,
CORINFO_HELP_ULDIV,
CORINFO_HELP_ULMOD,
CORINFO_HELP_LNG2FLT, // Convert a signed int64 to a float
CORINFO_HELP_LNG2DBL, // Convert a signed int64 to a double
CORINFO_HELP_ULNG2FLT, // Convert a unsigned int64 to a float
CORINFO_HELP_ULNG2DBL, // Convert a unsigned int64 to a double
CORINFO_HELP_DBL2INT,
CORINFO_HELP_DBL2INT_OVF,
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@

#include <minipal/guid.h>

constexpr GUID JITEEVersionIdentifier = { /* 72704ed3-9bc5-4e07-bfe9-a4e091812ba8 */
0x72704ed3,
0x9bc5,
0x4e07,
{0xbf, 0xe9, 0xa4, 0xe0, 0x91, 0x81, 0x2b, 0xa8}
constexpr GUID JITEEVersionIdentifier = { /* 7ce8764d-ac60-4e05-a6e4-448c1eb8cf35 */
0x7ce8764d,
0xac60,
0x4e05,
{0xa6, 0xe4, 0x44, 0x8c, 0x1e, 0xb8, 0xcf, 0x35}
};

#endif // JIT_EE_VERSIONING_GUID_H
2 changes: 2 additions & 0 deletions src/coreclr/inc/jithelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@
JITHELPER(CORINFO_HELP_ULDIV, NULL, METHOD__NIL)
JITHELPER(CORINFO_HELP_ULMOD, NULL, METHOD__NIL)
#endif // TARGET_64BIT
JITHELPER(CORINFO_HELP_LNG2FLT, JIT_Lng2Flt, METHOD__NIL)
JITHELPER(CORINFO_HELP_LNG2DBL, JIT_Lng2Dbl, METHOD__NIL)
JITHELPER(CORINFO_HELP_ULNG2FLT, JIT_ULng2Flt, METHOD__NIL)
JITHELPER(CORINFO_HELP_ULNG2DBL, JIT_ULng2Dbl, METHOD__NIL)
JITHELPER(CORINFO_HELP_DBL2INT, JIT_Dbl2Int, METHOD__NIL)
DYNAMICJITHELPER(CORINFO_HELP_DBL2INT_OVF, NULL, METHOD__MATH__CONVERT_TO_INT32_CHECKED)
Expand Down
4 changes: 3 additions & 1 deletion src/coreclr/inc/readytorun.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
// If you update this, ensure you run `git grep MINIMUM_READYTORUN_MAJOR_VERSION`
// and handle pending work.
#define READYTORUN_MAJOR_VERSION 13
#define READYTORUN_MINOR_VERSION 0x0000
#define READYTORUN_MINOR_VERSION 0x0001

#define MINIMUM_READYTORUN_MAJOR_VERSION 13

Expand Down Expand Up @@ -408,6 +408,8 @@ enum ReadyToRunHelper
READYTORUN_HELPER_Dbl2UIntOvf = 0xD5,
READYTORUN_HELPER_Dbl2ULng = 0xD6,
READYTORUN_HELPER_Dbl2ULngOvf = 0xD7,
READYTORUN_HELPER_Lng2Flt = 0xD8,
READYTORUN_HELPER_ULng2Flt = 0xD9,

// Floating point ops
READYTORUN_HELPER_DblRem = 0xE0,
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/inc/readytorunhelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ HELPER(READYTORUN_HELPER_Dbl2UInt, CORINFO_HELP_DBL2UINT,
HELPER(READYTORUN_HELPER_Dbl2UIntOvf, CORINFO_HELP_DBL2UINT_OVF, )
HELPER(READYTORUN_HELPER_Dbl2ULng, CORINFO_HELP_DBL2ULNG, )
HELPER(READYTORUN_HELPER_Dbl2ULngOvf, CORINFO_HELP_DBL2ULNG_OVF, )
HELPER(READYTORUN_HELPER_Lng2Flt, CORINFO_HELP_LNG2FLT, )
HELPER(READYTORUN_HELPER_ULng2Flt, CORINFO_HELP_ULNG2FLT, )

HELPER(READYTORUN_HELPER_FltRem, CORINFO_HELP_FLTREM, )
HELPER(READYTORUN_HELPER_DblRem, CORINFO_HELP_DBLREM, )
Expand Down
6 changes: 5 additions & 1 deletion src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8144,7 +8144,11 @@ void Compiler::impImportBlockCode(BasicBlock* block)
goto CONV;

case CEE_CONV_R_UN:
lclTyp = TYP_DOUBLE;
// Because there is no IL instruction conv.r4.un, compilers consistently
// emit conv.r.un followed immediately by conv.r4 for unsigned->float casts.
// We recognize this pattern and create the intended cast.
// Otherwise, conv.r.un is treated as a cast to double.
lclTyp = ((OPCODE)getU1LittleEndian(codeAddr) == CEE_CONV_R4) ? TYP_FLOAT : TYP_DOUBLE;
goto CONV_UN;

CONV_UN:
Expand Down
54 changes: 15 additions & 39 deletions src/coreclr/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,22 +442,16 @@ GenTree* Compiler::fgMorphExpandCast(GenTreeCast* tree)
// converts long/ulong --> float/double casts into helper calls.
else if (varTypeIsFloating(dstType) && varTypeIsLong(srcType))
{
CorInfoHelpFunc helper = CORINFO_HELP_UNDEF;
if (dstType == TYP_FLOAT)
{
// there is only a double helper, so we
// - change the dsttype to double
// - insert a cast from double to float
// - recurse into the resulting tree
tree->CastToType() = TYP_DOUBLE;
tree->gtType = TYP_DOUBLE;

tree = gtNewCastNode(TYP_FLOAT, tree, false, TYP_FLOAT);

return fgMorphTree(tree);
helper = tree->IsUnsigned() ? CORINFO_HELP_ULNG2FLT : CORINFO_HELP_LNG2FLT;
}
else
{
helper = tree->IsUnsigned() ? CORINFO_HELP_ULNG2DBL : CORINFO_HELP_LNG2DBL;
}
if (tree->gtFlags & GTF_UNSIGNED)
return fgMorphCastIntoHelper(tree, CORINFO_HELP_ULNG2DBL, oper);
return fgMorphCastIntoHelper(tree, CORINFO_HELP_LNG2DBL, oper);
return fgMorphCastIntoHelper(tree, helper, oper);
}
#endif // TARGET_ARM

Expand Down Expand Up @@ -488,41 +482,23 @@ GenTree* Compiler::fgMorphExpandCast(GenTreeCast* tree)

if (srcType == TYP_ULONG)
{
return fgMorphCastIntoHelper(tree, CORINFO_HELP_ULNG2DBL, oper);
CorInfoHelpFunc helper = (dstType == TYP_FLOAT) ? CORINFO_HELP_ULNG2FLT : CORINFO_HELP_ULNG2DBL;
return fgMorphCastIntoHelper(tree, helper, oper);
}
else if (srcType == TYP_UINT && !canUseEvexEncoding())
{
oper = gtNewCastNode(TYP_LONG, oper, true, TYP_LONG);
oper->gtFlags |= (tree->gtFlags & (GTF_OVERFLOW | GTF_EXCEPT));
tree->gtFlags &= ~GTF_UNSIGNED;
return fgMorphCastIntoHelper(tree, CORINFO_HELP_LNG2DBL, oper);
tree->ClearUnsigned();

CorInfoHelpFunc helper = (dstType == TYP_FLOAT) ? CORINFO_HELP_LNG2FLT : CORINFO_HELP_LNG2DBL;
return fgMorphCastIntoHelper(tree, helper, oper);
}
}
else if (!tree->IsUnsigned() && (srcType == TYP_LONG) && varTypeIsFloating(dstType))
{
oper = fgMorphCastIntoHelper(tree, CORINFO_HELP_LNG2DBL, oper);

// Since we don't have a Jit Helper that converts to a TYP_FLOAT
// we just use the one that converts to a TYP_DOUBLE
// and then add a cast to TYP_FLOAT
//
if ((dstType == TYP_FLOAT) && oper->OperIs(GT_CALL))
{
// Fix the return type to be TYP_DOUBLE
//
oper->gtType = TYP_DOUBLE;
oper->SetMorphed(this);

// Add a Cast to TYP_FLOAT
//
tree = gtNewCastNode(TYP_FLOAT, oper, false, TYP_FLOAT);
tree->SetMorphed(this);
return tree;
}
else
{
return oper;
}
CorInfoHelpFunc helper = (dstType == TYP_FLOAT) ? CORINFO_HELP_LNG2FLT : CORINFO_HELP_LNG2DBL;
return fgMorphCastIntoHelper(tree, helper, oper);
}
#endif // TARGET_X86
else if (varTypeIsGC(srcType) != varTypeIsGC(dstType))
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/jit/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1529,7 +1529,9 @@ void HelperCallProperties::init()
isNoGC = true;
FALLTHROUGH;
case CORINFO_HELP_LMUL:
case CORINFO_HELP_LNG2FLT:
case CORINFO_HELP_LNG2DBL:
case CORINFO_HELP_ULNG2FLT:
case CORINFO_HELP_ULNG2DBL:
case CORINFO_HELP_DBL2INT:
case CORINFO_HELP_DBL2LNG:
Expand Down
13 changes: 13 additions & 0 deletions src/coreclr/jit/valuenum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13781,11 +13781,22 @@ void Compiler::fgValueNumberCastHelper(GenTreeCall* call)

switch (helpFunc)
{
case CORINFO_HELP_LNG2FLT:
castToType = TYP_FLOAT;
castFromType = TYP_LONG;
break;

case CORINFO_HELP_LNG2DBL:
castToType = TYP_DOUBLE;
castFromType = TYP_LONG;
break;

case CORINFO_HELP_ULNG2FLT:
castToType = TYP_FLOAT;
castFromType = TYP_LONG;
srcIsUnsigned = true;
break;

case CORINFO_HELP_ULNG2DBL:
castToType = TYP_DOUBLE;
castFromType = TYP_LONG;
Expand Down Expand Up @@ -14133,7 +14144,9 @@ bool Compiler::fgValueNumberHelperCall(GenTreeCall* call)

switch (helpFunc)
{
case CORINFO_HELP_LNG2FLT:
case CORINFO_HELP_LNG2DBL:
case CORINFO_HELP_ULNG2FLT:
case CORINFO_HELP_ULNG2DBL:
case CORINFO_HELP_DBL2INT:
case CORINFO_HELP_DBL2INT_OVF:
Expand Down
12 changes: 12 additions & 0 deletions src/coreclr/nativeaot/Runtime/MathHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,18 @@ FCIMPL1_L(double, RhpULng2Dbl, uint64_t val)
}
FCIMPLEND

FCIMPL1_L(float, RhpLng2Flt, int64_t val)
{
return (float)val;
}
FCIMPLEND

FCIMPL1_L(float, RhpULng2Flt, uint64_t val)
{
return (float)val;
}
FCIMPLEND

#endif

#ifndef HOST_64BIT
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct ReadyToRunHeaderConstants
static const uint32_t Signature = 0x00525452; // 'RTR'

static const uint32_t CurrentMajorVersion = 13;
static const uint32_t CurrentMinorVersion = 0;
static const uint32_t CurrentMinorVersion = 1;
};

struct ReadyToRunHeader
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal struct ReadyToRunHeaderConstants
public const uint Signature = 0x00525452; // 'RTR'

public const ushort CurrentMajorVersion = 13;
public const ushort CurrentMinorVersion = 0;
public const ushort CurrentMinorVersion = 1;
}
#if READYTORUN
#pragma warning disable 0169
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,8 @@ public enum ReadyToRunHelper
Dbl2UIntOvf = 0xD5,
Dbl2ULng = 0xD6,
Dbl2ULngOvf = 0xD7,
Lng2Flt = 0xD8,
ULng2Flt = 0xD9,

// Floating point ops
DblRem = 0xE0,
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ public enum CorInfoHelpFunc
CORINFO_HELP_LMOD,
CORINFO_HELP_ULDIV,
CORINFO_HELP_ULMOD,
CORINFO_HELP_LNG2FLT, // Convert a signed int64 to a float
CORINFO_HELP_LNG2DBL, // Convert a signed int64 to a double
CORINFO_HELP_ULNG2FLT, // Convert a unsigned int64 to a float
CORINFO_HELP_ULNG2DBL, // Convert a unsigned int64 to a double
CORINFO_HELP_DBL2INT,
CORINFO_HELP_DBL2INT_OVF,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,12 @@ public static void GetEntryPoint(TypeSystemContext context, ReadyToRunHelper id,
case ReadyToRunHelper.ULng2Dbl:
mangledName = "RhpULng2Dbl";
break;
case ReadyToRunHelper.Lng2Flt:
mangledName = "RhpLng2Flt";
break;
case ReadyToRunHelper.ULng2Flt:
mangledName = "RhpULng2Flt";
break;

case ReadyToRunHelper.Dbl2Lng:
mangledName = "RhpDbl2Lng";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,12 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum)
case CorInfoHelpFunc.CORINFO_HELP_ULNG2DBL:
id = ReadyToRunHelper.ULng2Dbl;
break;
case CorInfoHelpFunc.CORINFO_HELP_LNG2FLT:
id = ReadyToRunHelper.Lng2Flt;
break;
case CorInfoHelpFunc.CORINFO_HELP_ULNG2FLT:
id = ReadyToRunHelper.ULng2Flt;
break;

case CorInfoHelpFunc.CORINFO_HELP_DIV:
id = ReadyToRunHelper.Div;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1929,6 +1929,14 @@ private void ParseHelper(StringBuilder builder)
builder.Append("DBL2ULNGOVF");
break;

case ReadyToRunHelper.Lng2Flt:
builder.Append("LNG2FLT");
break;

case ReadyToRunHelper.ULng2Flt:
builder.Append("ULNG2FLT");
break;

// Floating point ops
case ReadyToRunHelper.DblRem:
builder.Append("DBL_REM");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,12 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum)
case CorInfoHelpFunc.CORINFO_HELP_DBL2ULNG_OVF:
id = ReadyToRunHelper.Dbl2ULngOvf;
break;
case CorInfoHelpFunc.CORINFO_HELP_LNG2FLT:
id = ReadyToRunHelper.Lng2Flt;
break;
case CorInfoHelpFunc.CORINFO_HELP_ULNG2FLT:
id = ReadyToRunHelper.ULng2Flt;
break;

case CorInfoHelpFunc.CORINFO_HELP_FLTREM:
id = ReadyToRunHelper.FltRem;
Expand Down
16 changes: 16 additions & 0 deletions src/coreclr/vm/jithelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,14 @@ HCIMPLEND

#include <optsmallperfcritical.h>

/*********************************************************************/
HCIMPL1_V(float, JIT_ULng2Flt, uint64_t val)
{
FCALL_CONTRACT;
return (float)val;
}
HCIMPLEND

/*********************************************************************/
HCIMPL1_V(double, JIT_ULng2Dbl, uint64_t val)
{
Expand All @@ -171,6 +179,14 @@ HCIMPL1_V(double, JIT_ULng2Dbl, uint64_t val)
}
HCIMPLEND

/*********************************************************************/
HCIMPL1_V(float, JIT_Lng2Flt, int64_t val)
{
FCALL_CONTRACT;
return (float)val;
}
HCIMPLEND

/*********************************************************************/
HCIMPL1_V(double, JIT_Lng2Dbl, int64_t val)
{
Expand Down
12 changes: 2 additions & 10 deletions src/tests/JIT/Regression/JitBlue/Runtime_106338/Runtime_106338.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,7 @@ public static void TestEntryPoint()
float vr11 = 4294967295U | vr10;
uint result = BitConverter.SingleToUInt32Bits(vr11);

if ((RuntimeInformation.ProcessArchitecture == Architecture.Arm64) || (RuntimeInformation.ProcessArchitecture == Architecture.X64))
{
// Expected to cast ulong -> float directly
Assert.Equal(1600094603U, result);
}
else
{
// Expected to cast ulong -> double -> float
Assert.Equal(1600094604U, result);
}
// Expected to cast ulong -> float directly
Assert.Equal(1600094603U, result);
}
}
Loading