Skip to content

Commit

Permalink
Rewrite floating point mod and round math jit helpers to managed code
Browse files Browse the repository at this point in the history
  • Loading branch information
MichalPetryka authored and jkotas committed Mar 25, 2024
1 parent d8c3db7 commit e90f62f
Show file tree
Hide file tree
Showing 11 changed files with 65 additions and 242 deletions.
4 changes: 2 additions & 2 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -397,8 +397,8 @@ enum CorInfoHelpFunc
CORINFO_HELP_DBL2ULNG_OVF,
CORINFO_HELP_FLTREM,
CORINFO_HELP_DBLREM,
CORINFO_HELP_FLTROUND,
CORINFO_HELP_DBLROUND,
CORINFO_HELP_FLTROUND, // unused, remove once MINIMUM_READYTORUN_MAJOR_VERSION > 9
CORINFO_HELP_DBLROUND, // unused, remove once MINIMUM_READYTORUN_MAJOR_VERSION > 9

/* Allocating a new object. Always use ICorClassInfo::getNewHelper() to decide
which is the right helper to use to allocate an object of a given type. */
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jithelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@
JITHELPER(CORINFO_HELP_DBL2UINT_OVF, JIT_Dbl2UIntOvf, CORINFO_HELP_SIG_8_STACK)
JITHELPER(CORINFO_HELP_DBL2ULNG, JIT_Dbl2ULng, CORINFO_HELP_SIG_8_STACK)
JITHELPER(CORINFO_HELP_DBL2ULNG_OVF, JIT_Dbl2ULngOvf, CORINFO_HELP_SIG_8_STACK)
JITHELPER(CORINFO_HELP_FLTREM, JIT_FltRem, CORINFO_HELP_SIG_8_STACK)
JITHELPER(CORINFO_HELP_DBLREM, JIT_DblRem, CORINFO_HELP_SIG_16_STACK)
JITHELPER(CORINFO_HELP_FLTROUND, JIT_FloatRound, CORINFO_HELP_SIG_8_STACK)
JITHELPER(CORINFO_HELP_DBLROUND, JIT_DoubleRound, CORINFO_HELP_SIG_16_STACK)
DYNAMICJITHELPER(CORINFO_HELP_FLTREM, NULL, CORINFO_HELP_SIG_8_STACK)
DYNAMICJITHELPER(CORINFO_HELP_DBLREM, NULL, CORINFO_HELP_SIG_16_STACK)
DYNAMICJITHELPER(CORINFO_HELP_FLTROUND, NULL, CORINFO_HELP_SIG_8_STACK)
DYNAMICJITHELPER(CORINFO_HELP_DBLROUND, NULL, CORINFO_HELP_SIG_16_STACK)

// Allocating a new object
JITHELPER(CORINFO_HELP_NEWFAST, JIT_New, CORINFO_HELP_SIG_REG_ONLY)
Expand Down Expand Up @@ -203,7 +203,7 @@
JITHELPER(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE, JIT_GetSharedNonGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR, JIT_GetSharedGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR, JIT_GetSharedNonGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS, JIT_GetSharedGCThreadStaticBaseDynamicClass, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS, JIT_GetSharedGCThreadStaticBaseDynamicClass, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS, JIT_GetSharedNonGCThreadStaticBaseDynamicClass, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED, JIT_GetSharedGCThreadStaticBaseOptimized, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED, JIT_GetSharedNonGCThreadStaticBaseOptimized, CORINFO_HELP_SIG_REG_ONLY)
Expand Down
59 changes: 8 additions & 51 deletions src/coreclr/nativeaot/Runtime/MathHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,57 +30,6 @@ FCIMPLEND
#undef max
#include <cmath>

FCIMPL2_FF(float, RhpFltRem, float dividend, float divisor)
{
//
// From the ECMA standard:
//
// If [divisor] is zero or [dividend] is infinity
// the result is NaN.
// If [divisor] is infinity,
// the result is [dividend] (negated for -infinity***).
//
// ***"negated for -infinity" has been removed from the spec
//

if (divisor==0 || !std::isfinite(dividend))
{
return -nanf("");
}
else if (!std::isfinite(divisor) && !std::isnan(divisor))
{
return dividend;
}
// else...
return fmodf(dividend,divisor);
}
FCIMPLEND

FCIMPL2_DD(double, RhpDblRem, double dividend, double divisor)
{
//
// From the ECMA standard:
//
// If [divisor] is zero or [dividend] is infinity
// the result is NaN.
// If [divisor] is infinity,
// the result is [dividend] (negated for -infinity***).
//
// ***"negated for -infinity" has been removed from the spec
//
if (divisor==0 || !std::isfinite(dividend))
{
return -nan("");
}
else if (!std::isfinite(divisor) && !std::isnan(divisor))
{
return dividend;
}
// else...
return(fmod(dividend,divisor));
}
FCIMPLEND

#ifndef HOST_64BIT
EXTERN_C int64_t QCALLTYPE RhpLDiv(int64_t i, int64_t j)
{
Expand Down Expand Up @@ -363,6 +312,14 @@ FCIMPL1_F(float, tanhf, float x)
return std::tanhf(x);
FCIMPLEND

FCIMPL2_DD(double, fmod, double x, double y)
return std::fmod(x, y);
FCIMPLEND

FCIMPL2_FF(float, fmodf, float x, float y)
return std::fmodf(x, y);
FCIMPLEND

FCIMPL3_DDD(double, fma, double x, double y, double z)
return std::fma(x, y, z);
FCIMPLEND
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,10 @@ public static void GetEntryPoint(TypeSystemContext context, ReadyToRunHelper id,
break;

case ReadyToRunHelper.DblRem:
mangledName = "RhpDblRem";
methodDesc = context.SystemModule.GetKnownType("System", "Math").GetKnownMethod("FMod", null);
break;
case ReadyToRunHelper.FltRem:
mangledName = "RhpFltRem";
methodDesc = context.SystemModule.GetKnownType("System", "MathF").GetKnownMethod("FMod", null);
break;

case ReadyToRunHelper.LMul:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1224,7 +1224,7 @@ private void ImportBinaryOperation(ILOpcode opcode)
break;
case ILOpcode.mul_ovf:
case ILOpcode.mul_ovf_un:
if (_compilation.TypeSystemContext.Target.Architecture == TargetArchitecture.ARM)
if (_compilation.TypeSystemContext.Target.PointerSize == 4)
{
_dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.LMulOfv), "_lmulovf");
_dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.ULMulOvf), "_ulmulovf");
Expand All @@ -1244,6 +1244,10 @@ private void ImportBinaryOperation(ILOpcode opcode)
else if (_compilation.TypeSystemContext.Target.Architecture == TargetArchitecture.ARM64)
{
_dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.ThrowDivZero), "_divbyzero");
if (opcode == ILOpcode.div)
{
_dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.Overflow), "_ovf");
}
}
break;
case ILOpcode.rem:
Expand All @@ -1258,7 +1262,14 @@ private void ImportBinaryOperation(ILOpcode opcode)
else if (_compilation.TypeSystemContext.Target.Architecture == TargetArchitecture.ARM64)
{
_dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.ThrowDivZero), "_divbyzero");
if (opcode == ILOpcode.rem)
{
_dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.Overflow), "_ovf");
}
}

_dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.DblRem), "rem");
_dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.FltRem), "rem");
break;
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/vm/corelib.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,14 @@ DEFINE_METHOD(DELEGATE, GET_INVOKE_METHOD, GetInvokeMethod,
DEFINE_CLASS(INT128, System, Int128)
DEFINE_CLASS(UINT128, System, UInt128)

DEFINE_CLASS(MATH, System, Math)
DEFINE_METHOD(MATH, ROUND, Round, SM_Dbl_RetDbl)
DEFINE_METHOD(MATH, FMOD, FMod, NoSig)

DEFINE_CLASS(MATHF, System, MathF)
DEFINE_METHOD(MATHF, ROUND, Round, SM_Flt_RetFlt)
DEFINE_METHOD(MATHF, FMOD, FMod, NoSig)

DEFINE_CLASS(DYNAMICMETHOD, ReflectionEmit, DynamicMethod)

DEFINE_CLASS(DYNAMICRESOLVER, ReflectionEmit, DynamicResolver)
Expand Down
16 changes: 16 additions & 0 deletions src/coreclr/vm/ecall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,22 @@ void ECall::PopulateManagedHelpers()
pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__SPAN_HELPERS__MEMCOPY));
pDest = pMD->GetMultiCallableAddrOfCode();
SetJitHelperFunction(CORINFO_HELP_MEMCPY, pDest);

pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__MATH__FMOD));
pDest = pMD->GetMultiCallableAddrOfCode();
SetJitHelperFunction(CORINFO_HELP_DBLREM, pDest);

pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__MATHF__FMOD));
pDest = pMD->GetMultiCallableAddrOfCode();
SetJitHelperFunction(CORINFO_HELP_FLTREM, pDest);

pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__MATH__ROUND));
pDest = pMD->GetMultiCallableAddrOfCode();
SetJitHelperFunction(CORINFO_HELP_DBLROUND, pDest);

pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__MATHF__ROUND));
pDest = pMD->GetMultiCallableAddrOfCode();
SetJitHelperFunction(CORINFO_HELP_FLTROUND, pDest);
}

static CrstStatic gFCallLock;
Expand Down
33 changes: 0 additions & 33 deletions src/coreclr/vm/i386/jithelp.asm
Original file line number Diff line number Diff line change
Expand Up @@ -1214,39 +1214,6 @@ JIT_TailCallVSDLeave:

JIT_TailCall ENDP


;------------------------------------------------------------------------------

; HCIMPL2_VV(float, JIT_FltRem, float dividend, float divisor)
@JIT_FltRem@8 proc public
fld dword ptr [esp+4] ; divisor
fld dword ptr [esp+8] ; dividend
fremloop:
fprem
fstsw ax
fwait
sahf
jp fremloop ; Continue while the FPU status bit C2 is set
fxch ; swap, so divisor is on top and result is in st(1)
fstp ST(0) ; Pop the divisor from the FP stack
retn 8 ; Return value is in st(0)
@JIT_FltRem@8 endp

; HCIMPL2_VV(float, JIT_DblRem, float dividend, float divisor)
@JIT_DblRem@16 proc public
fld qword ptr [esp+4] ; divisor
fld qword ptr [esp+12] ; dividend
fremloopd:
fprem
fstsw ax
fwait
sahf
jp fremloopd ; Continue while the FPU status bit C2 is set
fxch ; swap, so divisor is on top and result is in st(1)
fstp ST(0) ; Pop the divisor from the FP stack
retn 16 ; Return value is in st(0)
@JIT_DblRem@16 endp

;------------------------------------------------------------------------------

; PatchedCodeStart and PatchedCodeEnd are used to determine bounds of patched code.
Expand Down
139 changes: 0 additions & 139 deletions src/coreclr/vm/jithelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,57 +510,6 @@ HCIMPL1_V(double, JIT_Lng2Dbl, INT64 val)
}
HCIMPLEND

//--------------------------------------------------------------------------
template <class ftype>
ftype modftype(ftype value, ftype *iptr);
template <> float modftype(float value, float *iptr) { return modff(value, iptr); }
template <> double modftype(double value, double *iptr) { return modf(value, iptr); }

// round to nearest, round to even if tied
template <class ftype>
ftype BankersRound(ftype value)
{
if (value < 0.0) return -BankersRound <ftype> (-value);

ftype integerPart;
modftype( value, &integerPart );

// if decimal part is exactly .5
if ((value -(integerPart +0.5)) == 0.0)
{
// round to even
if (fmod(ftype(integerPart), ftype(2.0)) == 0.0)
return integerPart;

// Else return the nearest even integer
return (ftype)copysign(ceil(fabs(value+0.5)),
value);
}

// Otherwise round to closest
return (ftype)copysign(floor(fabs(value)+0.5),
value);
}


/*********************************************************************/
// round double to nearest int (as double)
HCIMPL1_V(double, JIT_DoubleRound, double val)
{
FCALL_CONTRACT;
return BankersRound(val);
}
HCIMPLEND

/*********************************************************************/
// round float to nearest int (as float)
HCIMPL1_V(float, JIT_FloatRound, float val)
{
FCALL_CONTRACT;
return BankersRound(val);
}
HCIMPLEND

/*********************************************************************/
// Call fast Dbl2Lng conversion - used by functions below
FORCEINLINE INT64 FastDbl2Lng(double val)
Expand Down Expand Up @@ -674,94 +623,6 @@ HCIMPL1_V(INT64, JIT_Dbl2LngOvf, double val)
}
HCIMPLEND

#ifndef TARGET_WINDOWS
namespace
{
bool isnan(float val)
{
UINT32 bits = *reinterpret_cast<UINT32*>(&val);
return (bits & 0x7FFFFFFFU) > 0x7F800000U;
}
bool isnan(double val)
{
UINT64 bits = *reinterpret_cast<UINT64*>(&val);
return (bits & 0x7FFFFFFFFFFFFFFFULL) > 0x7FF0000000000000ULL;
}
bool isfinite(float val)
{
UINT32 bits = *reinterpret_cast<UINT32*>(&val);
return (~bits & 0x7F800000U) != 0;
}
bool isfinite(double val)
{
UINT64 bits = *reinterpret_cast<UINT64*>(&val);
return (~bits & 0x7FF0000000000000ULL) != 0;
}
}
#endif

HCIMPL2_VV(float, JIT_FltRem, float dividend, float divisor)
{
FCALL_CONTRACT;

//
// From the ECMA standard:
//
// If [divisor] is zero or [dividend] is infinity
// the result is NaN.
// If [divisor] is infinity,
// the result is [dividend] (negated for -infinity***).
//
// ***"negated for -infinity" has been removed from the spec
//

if (divisor==0 || !isfinite(dividend))
{
UINT32 NaN = CLR_NAN_32;
return *(float *)(&NaN);
}
else if (!isfinite(divisor) && !isnan(divisor))
{
return dividend;
}
// else...
#if 0
// COMPILER BUG WITH FMODF() + /Oi, USE FMOD() INSTEAD
return fmodf(dividend,divisor);
#else
return (float)fmod((double)dividend,(double)divisor);
#endif
}
HCIMPLEND

HCIMPL2_VV(double, JIT_DblRem, double dividend, double divisor)
{
FCALL_CONTRACT;

//
// From the ECMA standard:
//
// If [divisor] is zero or [dividend] is infinity
// the result is NaN.
// If [divisor] is infinity,
// the result is [dividend] (negated for -infinity***).
//
// ***"negated for -infinity" has been removed from the spec
//
if (divisor==0 || !isfinite(dividend))
{
UINT64 NaN = CLR_NAN_64;
return *(double *)(&NaN);
}
else if (!isfinite(divisor) && !isnan(divisor))
{
return dividend;
}
// else...
return(fmod(dividend,divisor));
}
HCIMPLEND

#endif // !TARGET_X86 || TARGET_UNIX

#include <optdefault.h>
Expand Down
Loading

0 comments on commit e90f62f

Please sign in to comment.