Skip to content

Commit

Permalink
Make System.Math/MathF.Truncate an intrinsic (#65014)
Browse files Browse the repository at this point in the history
  • Loading branch information
MichalPetryka authored Feb 11, 2022
1 parent a01be04 commit a44b7c2
Show file tree
Hide file tree
Showing 14 changed files with 51 additions and 5 deletions.
7 changes: 6 additions & 1 deletion src/coreclr/jit/codegenarmarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ void CodeGen::genIntrinsic(GenTree* treeNode)
assert(varTypeIsFloating(srcNode));
assert(srcNode->TypeGet() == treeNode->TypeGet());

// Right now only Abs/Ceiling/Floor/Round/Sqrt are treated as math intrinsics.
// Right now only Abs/Ceiling/Floor/Truncate/Round/Sqrt are treated as math intrinsics.
//
switch (treeNode->AsIntrinsic()->gtIntrinsicName)
{
Expand All @@ -642,6 +642,11 @@ void CodeGen::genIntrinsic(GenTree* treeNode)
GetEmitter()->emitInsBinary(INS_frintm, emitActualTypeSize(treeNode), treeNode, srcNode);
break;

case NI_System_Math_Truncate:
genConsumeOperands(treeNode->AsOp());
GetEmitter()->emitInsBinary(INS_frintz, emitActualTypeSize(treeNode), treeNode, srcNode);
break;

case NI_System_Math_Round:
genConsumeOperands(treeNode->AsOp());
GetEmitter()->emitInsBinary(INS_frintn, emitActualTypeSize(treeNode), treeNode, srcNode);
Expand Down
9 changes: 7 additions & 2 deletions src/coreclr/jit/codegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7027,7 +7027,7 @@ void CodeGen::genSSE2BitwiseOp(GenTree* treeNode)
// ii) treeNode oper is a GT_INTRINSIC
// iii) treeNode type is a floating point type
// iv) treeNode is not used from memory
// v) tree oper is NI_System_Math{F}_Round, _Ceiling, or _Floor
// v) tree oper is NI_System_Math{F}_Round, _Ceiling, _Floor, or _Truncate
// vi) caller of this routine needs to call genProduceReg()
void CodeGen::genSSE41RoundOp(GenTreeOp* treeNode)
{
Expand Down Expand Up @@ -7055,7 +7055,7 @@ void CodeGen::genSSE41RoundOp(GenTreeOp* treeNode)

unsigned ival = 0;

// v) tree oper is NI_System_Math{F}_Round, _Ceiling, or _Floor
// v) tree oper is NI_System_Math{F}_Round, _Ceiling, _Floor, or _Truncate
switch (treeNode->AsIntrinsic()->gtIntrinsicName)
{
case NI_System_Math_Round:
Expand All @@ -7070,6 +7070,10 @@ void CodeGen::genSSE41RoundOp(GenTreeOp* treeNode)
ival = 9;
break;

case NI_System_Math_Truncate:
ival = 11;
break;

default:
ins = INS_invalid;
assert(!"genSSE41RoundOp: unsupported intrinsic");
Expand Down Expand Up @@ -7197,6 +7201,7 @@ void CodeGen::genIntrinsic(GenTree* treeNode)

case NI_System_Math_Ceiling:
case NI_System_Math_Floor:
case NI_System_Math_Truncate:
case NI_System_Math_Round:
genSSE41RoundOp(treeNode->AsOp());
break;
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3862,6 +3862,7 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree)
case NI_System_Math_Sqrt:
case NI_System_Math_Tan:
case NI_System_Math_Tanh:
case NI_System_Math_Truncate:
{
// Giving intrinsics a large fixed execution cost is because we'd like to CSE
// them, even if they are implemented by calls. This is different from modeling
Expand Down Expand Up @@ -10891,6 +10892,9 @@ void Compiler::gtDispTree(GenTree* tree,
case NI_System_Math_Tanh:
printf(" tanh");
break;
case NI_System_Math_Truncate:
printf(" truncate");
break;
case NI_System_Object_GetType:
printf(" objGetType");
break;
Expand Down
10 changes: 9 additions & 1 deletion src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4447,6 +4447,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
case NI_System_Math_Sqrt:
case NI_System_Math_Tan:
case NI_System_Math_Tanh:
case NI_System_Math_Truncate:
{
retNode = impMathIntrinsic(method, sig, callType, ni, tailCall);
break;
Expand Down Expand Up @@ -5093,6 +5094,10 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method)
{
result = NI_System_Math_Tanh;
}
else if (strcmp(methodName, "Truncate") == 0)
{
result = NI_System_Math_Truncate;
}
}
else if (strcmp(className, "GC") == 0)
{
Expand Down Expand Up @@ -20448,14 +20453,15 @@ bool Compiler::IsTargetIntrinsic(NamedIntrinsic intrinsicName)
switch (intrinsicName)
{
// AMD64/x86 has SSE2 instructions to directly compute sqrt/abs and SSE4.1
// instructions to directly compute round/ceiling/floor.
// instructions to directly compute round/ceiling/floor/truncate.

case NI_System_Math_Abs:
case NI_System_Math_Sqrt:
return true;

case NI_System_Math_Ceiling:
case NI_System_Math_Floor:
case NI_System_Math_Truncate:
case NI_System_Math_Round:
return compOpportunisticallyDependsOn(InstructionSet_SSE41);

Expand All @@ -20471,6 +20477,7 @@ bool Compiler::IsTargetIntrinsic(NamedIntrinsic intrinsicName)
case NI_System_Math_Abs:
case NI_System_Math_Ceiling:
case NI_System_Math_Floor:
case NI_System_Math_Truncate:
case NI_System_Math_Round:
case NI_System_Math_Sqrt:
return true;
Expand Down Expand Up @@ -20544,6 +20551,7 @@ bool Compiler::IsMathIntrinsic(NamedIntrinsic intrinsicName)
case NI_System_Math_Sqrt:
case NI_System_Math_Tan:
case NI_System_Math_Tanh:
case NI_System_Math_Truncate:
{
assert((intrinsicName > NI_SYSTEM_MATH_START) && (intrinsicName < NI_SYSTEM_MATH_END));
return true;
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/jit/lowerxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5275,7 +5275,8 @@ void Lowering::ContainCheckIntrinsic(GenTreeOp* node)
NamedIntrinsic intrinsicName = node->AsIntrinsic()->gtIntrinsicName;

if ((intrinsicName == NI_System_Math_Ceiling) || (intrinsicName == NI_System_Math_Floor) ||
(intrinsicName == NI_System_Math_Round) || (intrinsicName == NI_System_Math_Sqrt))
(intrinsicName == NI_System_Math_Truncate) || (intrinsicName == NI_System_Math_Round) ||
(intrinsicName == NI_System_Math_Sqrt))
{
GenTree* op1 = node->gtGetOp1();

Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/lsraarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ int LinearScan::BuildNode(GenTree* tree)
noway_assert((tree->AsIntrinsic()->gtIntrinsicName == NI_System_Math_Abs) ||
(tree->AsIntrinsic()->gtIntrinsicName == NI_System_Math_Ceiling) ||
(tree->AsIntrinsic()->gtIntrinsicName == NI_System_Math_Floor) ||
(tree->AsIntrinsic()->gtIntrinsicName == NI_System_Math_Truncate) ||
(tree->AsIntrinsic()->gtIntrinsicName == NI_System_Math_Round) ||
(tree->AsIntrinsic()->gtIntrinsicName == NI_System_Math_Sqrt));

Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/lsraxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1826,6 +1826,7 @@ int LinearScan::BuildIntrinsic(GenTree* tree)

case NI_System_Math_Ceiling:
case NI_System_Math_Floor:
case NI_System_Math_Truncate:
case NI_System_Math_Round:
case NI_System_Math_Sqrt:
break;
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/namedintrinsiclist.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ enum NamedIntrinsic : unsigned short
NI_System_Math_Sqrt,
NI_System_Math_Tan,
NI_System_Math_Tanh,
NI_System_Math_Truncate,
NI_SYSTEM_MATH_END,

NI_System_Collections_Generic_Comparer_get_Default,
Expand Down
11 changes: 11 additions & 0 deletions src/coreclr/jit/valuenum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5294,6 +5294,10 @@ ValueNum ValueNumStore::EvalMathFuncUnary(var_types typ, NamedIntrinsic gtMathFN
res = tanh(arg0Val);
break;

case NI_System_Math_Truncate:
res = trunc(arg0Val);
break;

default:
// the above are the only math intrinsics at the time of this writing.
unreached();
Expand Down Expand Up @@ -5398,6 +5402,10 @@ ValueNum ValueNumStore::EvalMathFuncUnary(var_types typ, NamedIntrinsic gtMathFN
res = tanhf(arg0Val);
break;

case NI_System_Math_Truncate:
res = truncf(arg0Val);
break;

default:
// the above are the only math intrinsics at the time of this writing.
unreached();
Expand Down Expand Up @@ -5552,6 +5560,9 @@ ValueNum ValueNumStore::EvalMathFuncUnary(var_types typ, NamedIntrinsic gtMathFN
case NI_System_Math_Tanh:
vnf = VNF_Tanh;
break;
case NI_System_Math_Truncate:
vnf = VNF_Truncate;
break;
default:
unreached(); // the above are the only math intrinsics at the time of this writing.
}
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/valuenumfuncs.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ ValueNumFuncDef(Sinh, 1, false, false, false)
ValueNumFuncDef(Sqrt, 1, false, false, false)
ValueNumFuncDef(Tan, 1, false, false, false)
ValueNumFuncDef(Tanh, 1, false, false, false)
ValueNumFuncDef(Truncate, 1, false, false, false)

ValueNumFuncDef(ManagedThreadId, 0, false, false, false)

Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/pal/inc/pal.h
Original file line number Diff line number Diff line change
Expand Up @@ -4222,6 +4222,7 @@ PALIMPORT double __cdecl sinh(double);
PALIMPORT double __cdecl sqrt(double);
PALIMPORT double __cdecl tan(double);
PALIMPORT double __cdecl tanh(double);
PALIMPORT double __cdecl trunc(double);

PALIMPORT int __cdecl _finitef(float);
PALIMPORT int __cdecl _isnanf(float);
Expand Down Expand Up @@ -4254,6 +4255,7 @@ PALIMPORT float __cdecl sinhf(float);
PALIMPORT float __cdecl sqrtf(float);
PALIMPORT float __cdecl tanf(float);
PALIMPORT float __cdecl tanhf(float);
PALIMPORT float __cdecl truncf(float);
#endif // !PAL_STDCPP_COMPAT

#ifndef PAL_STDCPP_COMPAT
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/pal/src/include/pal/palinternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ function_name() to call the system's implementation
#define sqrt DUMMY_sqrt
#define tan DUMMY_tan
#define tanh DUMMY_tanh
#define trunc DUMMY_trunc
#define ceilf DUMMY_ceilf
#define cosf DUMMY_cosf
#define coshf DUMMY_coshf
Expand All @@ -233,6 +234,7 @@ function_name() to call the system's implementation
#define sqrtf DUMMY_sqrtf
#define tanf DUMMY_tanf
#define tanhf DUMMY_tanhf
#define truncf DUMMY_truncf

/* RAND_MAX needed to be renamed to avoid duplicate definition when including
stdlib.h header files. PAL_RAND_MAX should have the same value as RAND_MAX
Expand Down Expand Up @@ -464,6 +466,7 @@ function_name() to call the system's implementation
#undef sqrt
#undef tan
#undef tanh
#undef trunc
#undef acosf
#undef acoshf
#undef asinf
Expand Down Expand Up @@ -492,6 +495,7 @@ function_name() to call the system's implementation
#undef sqrtf
#undef tanf
#undef tanhf
#undef truncf
#undef rand
#undef srand
#undef errno
Expand Down
1 change: 1 addition & 0 deletions src/libraries/System.Private.CoreLib/src/System/Math.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1452,6 +1452,7 @@ public static decimal Truncate(decimal d)
return decimal.Truncate(d);
}

[Intrinsic]
public static unsafe double Truncate(double d)
{
ModF(d, &d);
Expand Down
1 change: 1 addition & 0 deletions src/libraries/System.Private.CoreLib/src/System/MathF.cs
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ public static int Sign(float x)
return Math.Sign(x);
}

[Intrinsic]
public static unsafe float Truncate(float x)
{
ModF(x, &x);
Expand Down

0 comments on commit a44b7c2

Please sign in to comment.