Skip to content
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

Make System.Math/MathF.Truncate an intrinsic #65014

Merged
merged 1 commit into from
Feb 11, 2022
Merged
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
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 @@ -3735,6 +3735,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 @@ -10764,6 +10765,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 @@ -4424,6 +4424,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 @@ -5070,6 +5071,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 @@ -20425,14 +20430,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 @@ -20448,6 +20454,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 @@ -20521,6 +20528,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 @@ -1817,6 +1817,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