[MethodImpl(MethodImplOptions.InternalCall)]
public static extern double Cbrt(double d);
+ [Intrinsic]
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern double Ceiling(double a);
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern double Exp(double d);
+ [Intrinsic]
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern double Floor(double d);
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern float Cbrt(float x);
+ [Intrinsic]
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern float Ceiling(float x);
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern float Exp(float x);
+ [Intrinsic]
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern float Floor(float x);
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
-constexpr GUID JITEEVersionIdentifier = { /* 164b4e4f-21f6-4d05-b560-3728395404f2 */
- 0x164b4e4f,
- 0x21f6,
- 0x4d05,
- { 0xb5, 0x60, 0x37, 0x28, 0x39, 0x54, 0x04, 0xf2 }
+constexpr GUID JITEEVersionIdentifier = { /* a5eec3a4-4176-43a7-8c2b-a05b551d4f49 */
+ 0xa5eec3a4,
+ 0x4176,
+ 0x43a7,
+ {0x8c, 0x2b, 0xa0, 0x5b, 0x55, 0x1d, 0x4f, 0x49}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
enum CorInfoIntrinsics
{
- CORINFO_INTRINSIC_Sin,
- CORINFO_INTRINSIC_Cos,
- CORINFO_INTRINSIC_Cbrt,
- CORINFO_INTRINSIC_Sqrt,
- CORINFO_INTRINSIC_Abs,
- CORINFO_INTRINSIC_Round,
- CORINFO_INTRINSIC_Cosh,
- CORINFO_INTRINSIC_Sinh,
- CORINFO_INTRINSIC_Tan,
- CORINFO_INTRINSIC_Tanh,
- CORINFO_INTRINSIC_Asin,
- CORINFO_INTRINSIC_Asinh,
- CORINFO_INTRINSIC_Acos,
- CORINFO_INTRINSIC_Acosh,
- CORINFO_INTRINSIC_Atan,
- CORINFO_INTRINSIC_Atan2,
- CORINFO_INTRINSIC_Atanh,
- CORINFO_INTRINSIC_Log10,
- CORINFO_INTRINSIC_Pow,
- CORINFO_INTRINSIC_Exp,
- CORINFO_INTRINSIC_Ceiling,
- CORINFO_INTRINSIC_Floor,
CORINFO_INTRINSIC_GetChar, // fetch character out of string
CORINFO_INTRINSIC_Array_GetDimLength, // Get number of elements in a given dimension of an array
CORINFO_INTRINSIC_Array_Get, // Get the value of an element in an array
// Right now only Abs/Ceiling/Floor/Round/Sqrt are treated as math intrinsics.
//
- switch (treeNode->AsIntrinsic()->gtIntrinsicId)
+ switch (treeNode->AsIntrinsic()->gtIntrinsicName)
{
- case CORINFO_INTRINSIC_Abs:
+ case NI_System_Math_Abs:
genConsumeOperands(treeNode->AsOp());
GetEmitter()->emitInsBinary(INS_ABS, emitActualTypeSize(treeNode), treeNode, srcNode);
break;
#ifdef TARGET_ARM64
- case CORINFO_INTRINSIC_Ceiling:
+ case NI_System_Math_Ceiling:
genConsumeOperands(treeNode->AsOp());
GetEmitter()->emitInsBinary(INS_frintp, emitActualTypeSize(treeNode), treeNode, srcNode);
break;
- case CORINFO_INTRINSIC_Floor:
+ case NI_System_Math_Floor:
genConsumeOperands(treeNode->AsOp());
GetEmitter()->emitInsBinary(INS_frintm, emitActualTypeSize(treeNode), treeNode, srcNode);
break;
- case CORINFO_INTRINSIC_Round:
+ case NI_System_Math_Round:
genConsumeOperands(treeNode->AsOp());
GetEmitter()->emitInsBinary(INS_frintn, emitActualTypeSize(treeNode), treeNode, srcNode);
break;
#endif // TARGET_ARM64
- case CORINFO_INTRINSIC_Sqrt:
+ case NI_System_Math_Sqrt:
genConsumeOperands(treeNode->AsOp());
GetEmitter()->emitInsBinary(INS_SQRT, emitActualTypeSize(treeNode), treeNode, srcNode);
break;
break;
case GT_INTRINSIC:
- assert(treeNode->AsIntrinsic()->gtIntrinsicId == CORINFO_INTRINSIC_Abs);
+ assert(treeNode->AsIntrinsic()->gtIntrinsicName == NI_System_Math_Abs);
// Abs(x) = set sign-bit to zero
// Abs(f) = f & 0x7fffffff
// 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 CORINFO_INTRINSIC_Round, _Ceiling, or _Floor
+// v) tree oper is NI_System_Math{F}_Round, _Ceiling, or _Floor
// vi) caller of this routine needs to call genProduceReg()
void CodeGen::genSSE41RoundOp(GenTreeOp* treeNode)
{
unsigned ival = 0;
- // v) tree oper is CORINFO_INTRINSIC_Round, _Ceiling, or _Floor
- switch (treeNode->AsIntrinsic()->gtIntrinsicId)
+ // v) tree oper is NI_System_Math{F}_Round, _Ceiling, or _Floor
+ switch (treeNode->AsIntrinsic()->gtIntrinsicName)
{
- case CORINFO_INTRINSIC_Round:
+ case NI_System_Math_Round:
ival = 4;
break;
- case CORINFO_INTRINSIC_Ceiling:
+ case NI_System_Math_Ceiling:
ival = 10;
break;
- case CORINFO_INTRINSIC_Floor:
+ case NI_System_Math_Floor:
ival = 9;
break;
void CodeGen::genIntrinsic(GenTree* treeNode)
{
// Right now only Sqrt/Abs are treated as math intrinsics.
- switch (treeNode->AsIntrinsic()->gtIntrinsicId)
+ switch (treeNode->AsIntrinsic()->gtIntrinsicName)
{
- case CORINFO_INTRINSIC_Sqrt:
+ case NI_System_Math_Sqrt:
{
// Both operand and its result must be of the same floating point type.
GenTree* srcNode = treeNode->AsOp()->gtOp1;
break;
}
- case CORINFO_INTRINSIC_Abs:
+ case NI_System_Math_Abs:
genSSE2BitwiseOp(treeNode);
break;
- case CORINFO_INTRINSIC_Round:
- case CORINFO_INTRINSIC_Ceiling:
- case CORINFO_INTRINSIC_Floor:
+ case NI_System_Math_Round:
+ case NI_System_Math_Ceiling:
+ case NI_System_Math_Floor:
genSSE41RoundOp(treeNode->AsOp());
break;
GenTree* impMathIntrinsic(CORINFO_METHOD_HANDLE method,
CORINFO_SIG_INFO* sig,
var_types callType,
- CorInfoIntrinsics intrinsicID,
+ NamedIntrinsic intrinsicName,
bool tailCall);
NamedIntrinsic lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method);
GenTree* impUnsupportedNamedIntrinsic(unsigned helper,
bool VarTypeIsMultiByteAndCanEnreg(
var_types type, CORINFO_CLASS_HANDLE typeClass, unsigned* typeSize, bool forReturn, bool isVarArg);
- bool IsIntrinsicImplementedByUserCall(CorInfoIntrinsics intrinsicId);
- bool IsTargetIntrinsic(CorInfoIntrinsics intrinsicId);
- bool IsMathIntrinsic(CorInfoIntrinsics intrinsicId);
+ bool IsIntrinsicImplementedByUserCall(NamedIntrinsic intrinsicName);
+ bool IsTargetIntrinsic(NamedIntrinsic intrinsicName);
+ bool IsMathIntrinsic(NamedIntrinsic intrinsicName);
bool IsMathIntrinsic(GenTree* tree);
private:
bool compIsVarArgs : 1; // Does the method have varargs parameters?
bool compInitMem : 1; // Is the CORINFO_OPT_INIT_LOCALS bit set in the method info options?
bool compProfilerCallback : 1; // JIT inserted a profiler Enter callback
- bool compPublishStubParam : 1; // EAX captured in prolog will be available through an instrinsic
+ bool compPublishStubParam : 1; // EAX captured in prolog will be available through an intrinsic
bool compRetBuffDefStack : 1; // The ret buff argument definitely points into the stack.
bool compHasNextCallRetAddr : 1; // The NextCallReturnAddress intrinsic is used.
level = gtSetEvalOrder(op1);
+ GenTreeIntrinsic* intrinsic;
+
/* Special handling for some operators */
switch (oper)
break;
case GT_INTRINSIC:
- // GT_INTRINSIC intrinsics Sin, Cos, Sqrt, Abs ... have higher costs.
- // TODO: tune these costs target specific as some of these are
- // target intrinsics and would cost less to generate code.
- switch (tree->AsIntrinsic()->gtIntrinsicId)
+ intrinsic = tree->AsIntrinsic();
+ if (intrinsic->gtIntrinsicId == CORINFO_INTRINSIC_Illegal)
{
- default:
- assert(!"missing case for gtIntrinsicId");
- costEx = 12;
- costSz = 12;
- break;
+ // named intrinsic
+ assert(intrinsic->gtIntrinsicName != NI_Illegal);
- case CORINFO_INTRINSIC_Sin:
- case CORINFO_INTRINSIC_Cos:
- case CORINFO_INTRINSIC_Sqrt:
- case CORINFO_INTRINSIC_Cbrt:
- case CORINFO_INTRINSIC_Cosh:
- case CORINFO_INTRINSIC_Sinh:
- case CORINFO_INTRINSIC_Tan:
- case CORINFO_INTRINSIC_Tanh:
- case CORINFO_INTRINSIC_Asin:
- case CORINFO_INTRINSIC_Asinh:
- case CORINFO_INTRINSIC_Acos:
- case CORINFO_INTRINSIC_Acosh:
- case CORINFO_INTRINSIC_Atan:
- case CORINFO_INTRINSIC_Atanh:
- case CORINFO_INTRINSIC_Atan2:
- case CORINFO_INTRINSIC_Log10:
- case CORINFO_INTRINSIC_Pow:
- case CORINFO_INTRINSIC_Exp:
- case CORINFO_INTRINSIC_Ceiling:
- case CORINFO_INTRINSIC_Floor:
- case CORINFO_INTRINSIC_Object_GetType:
- // 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
- // user calls since we never CSE user calls.
- costEx = 36;
- costSz = 4;
- break;
+ // GT_INTRINSIC intrinsics Sin, Cos, Sqrt, Abs ... have higher costs.
+ // TODO: tune these costs target specific as some of these are
+ // target intrinsics and would cost less to generate code.
+ switch (intrinsic->gtIntrinsicName)
+ {
+ default:
+ assert(!"missing case for gtIntrinsicName");
+ costEx = 12;
+ costSz = 12;
+ break;
- case CORINFO_INTRINSIC_Abs:
- costEx = 5;
- costSz = 15;
- break;
+ case NI_System_Math_Sin:
+ case NI_System_Math_Cos:
+ case NI_System_Math_Sqrt:
+ case NI_System_Math_Cbrt:
+ case NI_System_Math_Cosh:
+ case NI_System_Math_Sinh:
+ case NI_System_Math_Tan:
+ case NI_System_Math_Tanh:
+ case NI_System_Math_Asin:
+ case NI_System_Math_Asinh:
+ case NI_System_Math_Acos:
+ case NI_System_Math_Acosh:
+ case NI_System_Math_Atan:
+ case NI_System_Math_Atanh:
+ case NI_System_Math_Atan2:
+ case NI_System_Math_Log10:
+ case NI_System_Math_Pow:
+ case NI_System_Math_Exp:
+ case NI_System_Math_Ceiling:
+ case NI_System_Math_Floor:
+ // 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
+ // user calls since we never CSE user calls.
+ costEx = 36;
+ costSz = 4;
+ break;
- case CORINFO_INTRINSIC_Round:
- costEx = 3;
- costSz = 4;
- break;
+ case NI_System_Math_Abs:
+ costEx = 5;
+ costSz = 15;
+ break;
+
+ case NI_System_Math_Round:
+ costEx = 3;
+ costSz = 4;
+ break;
+ }
+ }
+ else
+ {
+ // old style intrinsic
+ assert(intrinsic->gtIntrinsicName == NI_Illegal);
+
+ switch (intrinsic->gtIntrinsicId)
+ {
+ default:
+ assert(!"missing case for gtIntrinsicId");
+ costEx = 12;
+ costSz = 12;
+ break;
+
+ case CORINFO_INTRINSIC_Object_GetType:
+ // 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
+ // user calls since we never CSE user calls.
+ costEx = 36;
+ costSz = 4;
+ break;
+ }
}
level++;
break;
case GT_INTRINSIC:
- switch (tree->AsIntrinsic()->gtIntrinsicId)
+ switch (tree->AsIntrinsic()->gtIntrinsicName)
{
- case CORINFO_INTRINSIC_Atan2:
- case CORINFO_INTRINSIC_Pow:
+ case NI_System_Math_Atan2:
+ case NI_System_Math_Pow:
// These math intrinsics are actually implemented by user calls.
// Increase the Sethi 'complexity' by two to reflect the argument
// register requirement.
// so if possible it was set above.
tryToSwap = false;
}
- else if ((oper == GT_INTRINSIC) && IsIntrinsicImplementedByUserCall(tree->AsIntrinsic()->gtIntrinsicId))
+ else if ((oper == GT_INTRINSIC) && IsIntrinsicImplementedByUserCall(tree->AsIntrinsic()->gtIntrinsicName))
{
// We do not swap operand execution order for intrinsics that are implemented by user calls
// because of trickiness around ensuring the execution order does not change during rationalization.
return true;
case GT_INTRINSIC:
- return comp->IsIntrinsicImplementedByUserCall(this->AsIntrinsic()->gtIntrinsicId);
+ return comp->IsIntrinsicImplementedByUserCall(this->AsIntrinsic()->gtIntrinsicName);
#if FEATURE_FIXED_OUT_ARGS && !defined(TARGET_64BIT)
case GT_LSH:
case GT_INTRINSIC:
copy = new (this, GT_INTRINSIC)
GenTreeIntrinsic(tree->TypeGet(), tree->AsOp()->gtOp1, tree->AsOp()->gtOp2,
- tree->AsIntrinsic()->gtIntrinsicId, tree->AsIntrinsic()->gtMethodHandle);
+ tree->AsIntrinsic()->gtIntrinsicId, tree->AsIntrinsic()->gtIntrinsicName,
+ tree->AsIntrinsic()->gtMethodHandle);
#ifdef FEATURE_READYTORUN_COMPILER
copy->AsIntrinsic()->gtEntryPoint = tree->AsIntrinsic()->gtEntryPoint;
#endif
if (tree->gtOper == GT_INTRINSIC)
{
- switch (tree->AsIntrinsic()->gtIntrinsicId)
+ GenTreeIntrinsic* intrinsic = tree->AsIntrinsic();
+
+ if (intrinsic->gtIntrinsicId == CORINFO_INTRINSIC_Illegal)
{
- case CORINFO_INTRINSIC_Sin:
- printf(" sin");
- break;
- case CORINFO_INTRINSIC_Cos:
- printf(" cos");
- break;
- case CORINFO_INTRINSIC_Cbrt:
- printf(" cbrt");
- break;
- case CORINFO_INTRINSIC_Sqrt:
- printf(" sqrt");
- break;
- case CORINFO_INTRINSIC_Abs:
- printf(" abs");
- break;
- case CORINFO_INTRINSIC_Round:
- printf(" round");
- break;
- case CORINFO_INTRINSIC_Cosh:
- printf(" cosh");
- break;
- case CORINFO_INTRINSIC_Sinh:
- printf(" sinh");
- break;
- case CORINFO_INTRINSIC_Tan:
- printf(" tan");
- break;
- case CORINFO_INTRINSIC_Tanh:
- printf(" tanh");
- break;
- case CORINFO_INTRINSIC_Asin:
- printf(" asin");
- break;
- case CORINFO_INTRINSIC_Asinh:
- printf(" asinh");
- break;
- case CORINFO_INTRINSIC_Acos:
- printf(" acos");
- break;
- case CORINFO_INTRINSIC_Acosh:
- printf(" acosh");
- break;
- case CORINFO_INTRINSIC_Atan:
- printf(" atan");
- break;
- case CORINFO_INTRINSIC_Atan2:
- printf(" atan2");
- break;
- case CORINFO_INTRINSIC_Atanh:
- printf(" atanh");
- break;
- case CORINFO_INTRINSIC_Log10:
- printf(" log10");
- break;
- case CORINFO_INTRINSIC_Pow:
- printf(" pow");
- break;
- case CORINFO_INTRINSIC_Exp:
- printf(" exp");
- break;
- case CORINFO_INTRINSIC_Ceiling:
- printf(" ceiling");
- break;
- case CORINFO_INTRINSIC_Floor:
- printf(" floor");
- break;
- case CORINFO_INTRINSIC_Object_GetType:
- printf(" objGetType");
- break;
+ // named intrinsic
+ assert(intrinsic->gtIntrinsicName != NI_Illegal);
+ switch (intrinsic->gtIntrinsicName)
+ {
+ case NI_System_Math_Sin:
+ printf(" sin");
+ break;
+ case NI_System_Math_Cos:
+ printf(" cos");
+ break;
+ case NI_System_Math_Cbrt:
+ printf(" cbrt");
+ break;
+ case NI_System_Math_Sqrt:
+ printf(" sqrt");
+ break;
+ case NI_System_Math_Abs:
+ printf(" abs");
+ break;
+ case NI_System_Math_Round:
+ printf(" round");
+ break;
+ case NI_System_Math_Cosh:
+ printf(" cosh");
+ break;
+ case NI_System_Math_Sinh:
+ printf(" sinh");
+ break;
+ case NI_System_Math_Tan:
+ printf(" tan");
+ break;
+ case NI_System_Math_Tanh:
+ printf(" tanh");
+ break;
+ case NI_System_Math_Asin:
+ printf(" asin");
+ break;
+ case NI_System_Math_Asinh:
+ printf(" asinh");
+ break;
+ case NI_System_Math_Acos:
+ printf(" acos");
+ break;
+ case NI_System_Math_Acosh:
+ printf(" acosh");
+ break;
+ case NI_System_Math_Atan:
+ printf(" atan");
+ break;
+ case NI_System_Math_Atan2:
+ printf(" atan2");
+ break;
+ case NI_System_Math_Atanh:
+ printf(" atanh");
+ break;
+ case NI_System_Math_Log10:
+ printf(" log10");
+ break;
+ case NI_System_Math_Pow:
+ printf(" pow");
+ break;
+ case NI_System_Math_Exp:
+ printf(" exp");
+ break;
+ case NI_System_Math_Ceiling:
+ printf(" ceiling");
+ break;
+ case NI_System_Math_Floor:
+ printf(" floor");
+ break;
- default:
- unreached();
+ default:
+ unreached();
+ }
+ }
+ else
+ {
+ // old style intrinsic
+ assert(intrinsic->gtIntrinsicName == NI_Illegal);
+ switch (intrinsic->gtIntrinsicId)
+ {
+ case CORINFO_INTRINSIC_Object_GetType:
+ printf(" objGetType");
+ break;
+
+ default:
+ unreached();
+ }
}
}
}
}
-// Returns true for the SIMD Instrinsic instructions that have MemoryLoad semantics, false otherwise
+// Returns true for the SIMD Intrinsic instructions that have MemoryLoad semantics, false otherwise
bool GenTreeSIMD::OperIsMemoryLoad() const
{
if (gtSIMDIntrinsicID == SIMDIntrinsicInitArray)
GenTreeHWIntrinsic(type, gtNewArgList(op1, op2, op3), hwIntrinsicID, TYP_UNKNOWN, 0);
}
-// Returns true for the HW Instrinsic instructions that have MemoryLoad semantics, false otherwise
+// Returns true for the HW Intrinsic instructions that have MemoryLoad semantics, false otherwise
bool GenTreeHWIntrinsic::OperIsMemoryLoad() const
{
#if defined(TARGET_XARCH) || defined(TARGET_ARM64)
return false;
}
-// Returns true for the HW Instrinsic instructions that have MemoryStore semantics, false otherwise
+// Returns true for the HW Intrinsic instructions that have MemoryStore semantics, false otherwise
bool GenTreeHWIntrinsic::OperIsMemoryStore() const
{
#if defined(TARGET_XARCH) || defined(TARGET_ARM64)
return false;
}
-// Returns true for the HW Instrinsic instructions that have MemoryLoad semantics, false otherwise
+// Returns true for the HW Intrinsic instructions that have MemoryLoad semantics, false otherwise
bool GenTreeHWIntrinsic::OperIsMemoryLoadOrStore() const
{
#if defined(TARGET_XARCH) || defined(TARGET_ARM64)
struct GenTreeIntrinsic : public GenTreeOp
{
CorInfoIntrinsics gtIntrinsicId;
+ NamedIntrinsic gtIntrinsicName;
CORINFO_METHOD_HANDLE gtMethodHandle; // Method handle of the method which is treated as an intrinsic.
#ifdef FEATURE_READYTORUN_COMPILER
CORINFO_CONST_LOOKUP gtEntryPoint;
#endif
- GenTreeIntrinsic(var_types type, GenTree* op1, CorInfoIntrinsics intrinsicId, CORINFO_METHOD_HANDLE methodHandle)
- : GenTreeOp(GT_INTRINSIC, type, op1, nullptr), gtIntrinsicId(intrinsicId), gtMethodHandle(methodHandle)
+ GenTreeIntrinsic(var_types type,
+ GenTree* op1,
+ CorInfoIntrinsics intrinsicId,
+ NamedIntrinsic intrinsicName,
+ CORINFO_METHOD_HANDLE methodHandle)
+ : GenTreeOp(GT_INTRINSIC, type, op1, nullptr)
+ , gtIntrinsicId(intrinsicId)
+ , gtIntrinsicName(intrinsicName)
+ , gtMethodHandle(methodHandle)
{
+ assert(intrinsicId != CORINFO_INTRINSIC_Illegal || intrinsicName != NI_Illegal);
}
- GenTreeIntrinsic(
- var_types type, GenTree* op1, GenTree* op2, CorInfoIntrinsics intrinsicId, CORINFO_METHOD_HANDLE methodHandle)
- : GenTreeOp(GT_INTRINSIC, type, op1, op2), gtIntrinsicId(intrinsicId), gtMethodHandle(methodHandle)
+ GenTreeIntrinsic(var_types type,
+ GenTree* op1,
+ GenTree* op2,
+ CorInfoIntrinsics intrinsicId,
+ NamedIntrinsic intrinsicName,
+ CORINFO_METHOD_HANDLE methodHandle)
+ : GenTreeOp(GT_INTRINSIC, type, op1, op2)
+ , gtIntrinsicId(intrinsicId)
+ , gtIntrinsicName(intrinsicName)
+ , gtMethodHandle(methodHandle)
{
+ assert(intrinsicId != CORINFO_INTRINSIC_Illegal || intrinsicName != NI_Illegal);
}
#if DEBUGGABLE_GENTREE
gtSIMDIntrinsicID = simdIntrinsicID;
}
- bool OperIsMemoryLoad() const; // Returns true for the SIMD Instrinsic instructions that have MemoryLoad semantics,
+ bool OperIsMemoryLoad() const; // Returns true for the SIMD Intrinsic instructions that have MemoryLoad semantics,
// false otherwise
#if DEBUGGABLE_GENTREE
}
}
- // Note that HW Instrinsic instructions are a sub class of GenTreeOp which only supports two operands
- // However there are HW Instrinsic instructions that have 3 or even 4 operands and this is
+ // Note that HW Intrinsic instructions are a sub class of GenTreeOp which only supports two operands
+ // However there are HW Intrinsic instructions that have 3 or even 4 operands and this is
// supported using a single op1 and using an ArgList for it: gtNewArgList(op1, op2, op3)
- bool OperIsMemoryLoad() const; // Returns true for the HW Instrinsic instructions that have MemoryLoad semantics,
+ bool OperIsMemoryLoad() const; // Returns true for the HW Intrinsic instructions that have MemoryLoad semantics,
// false otherwise
- bool OperIsMemoryStore() const; // Returns true for the HW Instrinsic instructions that have MemoryStore semantics,
+ bool OperIsMemoryStore() const; // Returns true for the HW Intrinsic instructions that have MemoryStore semantics,
// false otherwise
- bool OperIsMemoryLoadOrStore() const; // Returns true for the HW Instrinsic instructions that have MemoryLoad or
+ bool OperIsMemoryLoadOrStore() const; // Returns true for the HW Intrinsic instructions that have MemoryLoad or
// MemoryStore semantics, false otherwise
#if DEBUGGABLE_GENTREE
{
int numArgs = HWIntrinsicInfo::lookupNumArgs(hwIntrinsicID);
- // HW Instrinsic's with -1 for numArgs have a varying number of args, so we currently
+ // HW Intrinsic's with -1 for numArgs have a varying number of args, so we currently
// give themm a unique value number them, and don't add an extra argument.
//
if (numArgs == -1)
return false;
}
- // We iterate over all of the different baseType's for this instrinsic in the HWIntrinsicInfo table
+ // We iterate over all of the different baseType's for this intrinsic in the HWIntrinsicInfo table
// We set diffInsCount to the number of instructions that can execute differently.
//
unsigned diffInsCount = 0;
GenTree* op1;
GenTree* op2;
- case CORINFO_INTRINSIC_Sin:
- case CORINFO_INTRINSIC_Cbrt:
- case CORINFO_INTRINSIC_Sqrt:
- case CORINFO_INTRINSIC_Abs:
- case CORINFO_INTRINSIC_Cos:
- case CORINFO_INTRINSIC_Round:
- case CORINFO_INTRINSIC_Cosh:
- case CORINFO_INTRINSIC_Sinh:
- case CORINFO_INTRINSIC_Tan:
- case CORINFO_INTRINSIC_Tanh:
- case CORINFO_INTRINSIC_Asin:
- case CORINFO_INTRINSIC_Asinh:
- case CORINFO_INTRINSIC_Acos:
- case CORINFO_INTRINSIC_Acosh:
- case CORINFO_INTRINSIC_Atan:
- case CORINFO_INTRINSIC_Atan2:
- case CORINFO_INTRINSIC_Atanh:
- case CORINFO_INTRINSIC_Log10:
- case CORINFO_INTRINSIC_Pow:
- case CORINFO_INTRINSIC_Exp:
- case CORINFO_INTRINSIC_Ceiling:
- case CORINFO_INTRINSIC_Floor:
- retNode = impMathIntrinsic(method, sig, callType, intrinsicID, tailCall);
- break;
-
#if defined(TARGET_XARCH) || defined(TARGET_ARM64)
// TODO-ARM-CQ: reenable treating Interlocked operation as intrinsic
{
JITDUMP("Expanding as special intrinsic\n");
impPopStack();
- op1 = new (this, GT_INTRINSIC) GenTreeIntrinsic(genActualType(callType), op1, intrinsicID, method);
+ op1 = new (this, GT_INTRINSIC) GenTreeIntrinsic(genActualType(callType), op1, intrinsicID, ni, method);
// Set the CALL flag to indicate that the operator is implemented by a call.
// Set also the EXCEPTION flag because the native implementation of
#ifdef FEATURE_HW_INTRINSICS
case NI_System_Math_FusedMultiplyAdd:
- case NI_System_MathF_FusedMultiplyAdd:
{
#ifdef TARGET_XARCH
if (compExactlyDependsOn(InstructionSet_FMA) && supportSIMDTypes())
}
#endif // FEATURE_HW_INTRINSICS
+ case NI_System_Math_Sin:
+ case NI_System_Math_Cbrt:
+ case NI_System_Math_Sqrt:
+ case NI_System_Math_Abs:
+ case NI_System_Math_Cos:
case NI_System_Math_Round:
- case NI_System_MathF_Round:
- {
- // Math.Round and MathF.Round used to be a traditional JIT intrinsic. In order
- // to simplify the transition, we will just treat it as if it was still the
- // old intrinsic, CORINFO_INTRINSIC_Round. This should end up flowing properly
- // everywhere else.
-
- retNode = impMathIntrinsic(method, sig, callType, CORINFO_INTRINSIC_Round, tailCall);
+ case NI_System_Math_Cosh:
+ case NI_System_Math_Sinh:
+ case NI_System_Math_Tan:
+ case NI_System_Math_Tanh:
+ case NI_System_Math_Asin:
+ case NI_System_Math_Asinh:
+ case NI_System_Math_Acos:
+ case NI_System_Math_Acosh:
+ case NI_System_Math_Atan:
+ case NI_System_Math_Atan2:
+ case NI_System_Math_Atanh:
+ case NI_System_Math_Log10:
+ case NI_System_Math_Pow:
+ case NI_System_Math_Exp:
+ case NI_System_Math_Ceiling:
+ case NI_System_Math_Floor:
+ {
+ retNode = impMathIntrinsic(method, sig, callType, ni, tailCall);
break;
}
GenTree* Compiler::impMathIntrinsic(CORINFO_METHOD_HANDLE method,
CORINFO_SIG_INFO* sig,
var_types callType,
- CorInfoIntrinsics intrinsicID,
+ NamedIntrinsic intrinsicName,
bool tailCall)
{
GenTree* op1;
GenTree* op2;
assert(callType != TYP_STRUCT);
- assert(IsMathIntrinsic(intrinsicID));
+ assert(IsMathIntrinsic(intrinsicName));
op1 = nullptr;
// a) For back compatibility reasons on desktop .NET Framework 4.6 / 4.6.1
// b) It will be non-trivial task or too late to re-materialize a surviving
// tail prefixed GT_INTRINSIC as tail call in rationalizer.
- if (!IsIntrinsicImplementedByUserCall(intrinsicID) || !tailCall)
+ if (!IsIntrinsicImplementedByUserCall(intrinsicName) || !tailCall)
#else
// On x86 RyuJIT, importing intrinsics that are implemented as user calls can cause incorrect calculation
// of the depth of the stack if these intrinsics are used as arguments to another call. This causes bad
// code generation for certain EH constructs.
- if (!IsIntrinsicImplementedByUserCall(intrinsicID))
+ if (!IsIntrinsicImplementedByUserCall(intrinsicName))
#endif
{
switch (sig->numArgs)
op1 = gtNewCastNode(callType, op1, false, callType);
}
- op1 = new (this, GT_INTRINSIC) GenTreeIntrinsic(genActualType(callType), op1, intrinsicID, method);
+ op1 = new (this, GT_INTRINSIC)
+ GenTreeIntrinsic(genActualType(callType), op1, CORINFO_INTRINSIC_Illegal, intrinsicName, method);
break;
case 2:
op1 = gtNewCastNode(callType, op1, false, callType);
}
- op1 = new (this, GT_INTRINSIC) GenTreeIntrinsic(genActualType(callType), op1, op2, intrinsicID, method);
+ op1 = new (this, GT_INTRINSIC) GenTreeIntrinsic(genActualType(callType), op1, op2,
+ CORINFO_INTRINSIC_Illegal, intrinsicName, method);
break;
default:
- NO_WAY("Unsupported number of args for Math Instrinsic");
+ NO_WAY("Unsupported number of args for Math Intrinsic");
}
- if (IsIntrinsicImplementedByUserCall(intrinsicID))
+ if (IsIntrinsicImplementedByUserCall(intrinsicName))
{
op1->gtFlags |= GTF_CALL;
}
{
result = NI_System_Enum_HasFlag;
}
- else if (strncmp(className, "Math", 4) == 0)
+ else if (strcmp(className, "Math") == 0 || strcmp(className, "MathF") == 0)
{
- className += 4;
-
- if (className[0] == '\0')
+ if (strcmp(methodName, "FusedMultiplyAdd") == 0)
{
- if (strcmp(methodName, "FusedMultiplyAdd") == 0)
- {
- result = NI_System_Math_FusedMultiplyAdd;
- }
- else if (strcmp(methodName, "Round") == 0)
- {
- result = NI_System_Math_Round;
- }
+ result = NI_System_Math_FusedMultiplyAdd;
}
- else if (strcmp(className, "F") == 0)
+ else if (strcmp(methodName, "Round") == 0)
{
- if (strcmp(methodName, "FusedMultiplyAdd") == 0)
- {
- result = NI_System_MathF_FusedMultiplyAdd;
- }
- else if (strcmp(methodName, "Round") == 0)
- {
- result = NI_System_MathF_Round;
- }
+ result = NI_System_Math_Round;
+ }
+ else if (strcmp(methodName, "Sin") == 0)
+ {
+ result = NI_System_Math_Sin;
+ }
+ else if (strcmp(methodName, "Cos") == 0)
+ {
+ result = NI_System_Math_Cos;
+ }
+ else if (strcmp(methodName, "Cbrt") == 0)
+ {
+ result = NI_System_Math_Cbrt;
+ }
+ else if (strcmp(methodName, "Sqrt") == 0)
+ {
+ result = NI_System_Math_Sqrt;
+ }
+ else if (strcmp(methodName, "Abs") == 0)
+ {
+ result = NI_System_Math_Abs;
+ }
+ else if (strcmp(methodName, "Cosh") == 0)
+ {
+ result = NI_System_Math_Cosh;
+ }
+ else if (strcmp(methodName, "Sinh") == 0)
+ {
+ result = NI_System_Math_Sinh;
+ }
+ else if (strcmp(methodName, "Tan") == 0)
+ {
+ result = NI_System_Math_Tan;
+ }
+ else if (strcmp(methodName, "Tanh") == 0)
+ {
+ result = NI_System_Math_Tanh;
+ }
+ else if (strcmp(methodName, "Asin") == 0)
+ {
+ result = NI_System_Math_Asin;
+ }
+ else if (strcmp(methodName, "Asinh") == 0)
+ {
+ result = NI_System_Math_Asinh;
+ }
+ else if (strcmp(methodName, "Acos") == 0)
+ {
+ result = NI_System_Math_Acos;
+ }
+ else if (strcmp(methodName, "Acosh") == 0)
+ {
+ result = NI_System_Math_Acosh;
+ }
+ else if (strcmp(methodName, "Atan") == 0)
+ {
+ result = NI_System_Math_Atan;
+ }
+ else if (strcmp(methodName, "Atan2") == 0)
+ {
+ result = NI_System_Math_Atan2;
+ }
+ else if (strcmp(methodName, "Atanh") == 0)
+ {
+ result = NI_System_Math_Atanh;
+ }
+ else if (strcmp(methodName, "Log10") == 0)
+ {
+ result = NI_System_Math_Log10;
+ }
+ else if (strcmp(methodName, "Pow") == 0)
+ {
+ result = NI_System_Math_Pow;
+ }
+ else if (strcmp(methodName, "Exp") == 0)
+ {
+ result = NI_System_Math_Exp;
+ }
+ else if (strcmp(methodName, "Ceiling") == 0)
+ {
+ result = NI_System_Math_Ceiling;
+ }
+ else if (strcmp(methodName, "Floor") == 0)
+ {
+ result = NI_System_Math_Floor;
}
}
else if (strcmp(className, "GC") == 0)
// This is for a non-virtual, non-interface etc. call
call = gtNewCallNode(CT_USER_FUNC, callInfo->hMethod, callRetTyp, nullptr, ilOffset);
- // We remove the nullcheck for the GetType call instrinsic.
+ // We remove the nullcheck for the GetType call intrinsic.
// TODO-CQ: JIT64 does not introduce the null check for many more helper calls
- // and instrinsics.
+ // and intrinsics.
if (callInfo->nullInstanceCheck &&
!((mflags & CORINFO_FLG_INTRINSIC) != 0 && (intrinsicID == CORINFO_INTRINSIC_Object_GetType)))
{
// Returns true if the given intrinsic will be implemented by target-specific
// instructions
-bool Compiler::IsTargetIntrinsic(CorInfoIntrinsics intrinsicId)
+bool Compiler::IsTargetIntrinsic(NamedIntrinsic intrinsicName)
{
#if defined(TARGET_XARCH)
- switch (intrinsicId)
+ switch (intrinsicName)
{
// AMD64/x86 has SSE2 instructions to directly compute sqrt/abs and SSE4.1
// instructions to directly compute round/ceiling/floor.
// a CQ problem, it may be necessary to change the implementation of
// the helper calls to decrease call overhead or switch back to the
// x87 instructions. This is tracked by #7097.
- case CORINFO_INTRINSIC_Sqrt:
- case CORINFO_INTRINSIC_Abs:
+ case NI_System_Math_Sqrt:
+ case NI_System_Math_Abs:
return true;
- case CORINFO_INTRINSIC_Round:
- case CORINFO_INTRINSIC_Ceiling:
- case CORINFO_INTRINSIC_Floor:
+ case NI_System_Math_Round:
+ case NI_System_Math_Ceiling:
+ case NI_System_Math_Floor:
return compOpportunisticallyDependsOn(InstructionSet_SSE41);
default:
return false;
}
#elif defined(TARGET_ARM64)
- switch (intrinsicId)
+ switch (intrinsicName)
{
- case CORINFO_INTRINSIC_Sqrt:
- case CORINFO_INTRINSIC_Abs:
- case CORINFO_INTRINSIC_Round:
- case CORINFO_INTRINSIC_Floor:
- case CORINFO_INTRINSIC_Ceiling:
+ case NI_System_Math_Sqrt:
+ case NI_System_Math_Abs:
+ case NI_System_Math_Round:
+ case NI_System_Math_Floor:
+ case NI_System_Math_Ceiling:
return true;
default:
return false;
}
#elif defined(TARGET_ARM)
- switch (intrinsicId)
+ switch (intrinsicName)
{
- case CORINFO_INTRINSIC_Sqrt:
- case CORINFO_INTRINSIC_Abs:
- case CORINFO_INTRINSIC_Round:
+ case NI_System_Math_Sqrt:
+ case NI_System_Math_Abs:
+ case NI_System_Math_Round:
return true;
default:
// Returns true if the given intrinsic will be implemented by calling System.Math
// methods.
-bool Compiler::IsIntrinsicImplementedByUserCall(CorInfoIntrinsics intrinsicId)
+bool Compiler::IsIntrinsicImplementedByUserCall(NamedIntrinsic intrinsicName)
{
// Currently, if a math intrinsic is not implemented by target-specific
// instructions, it will be implemented by a System.Math call. In the
// future, if we turn to implementing some of them with helper calls,
// this predicate needs to be revisited.
- return !IsTargetIntrinsic(intrinsicId);
+ return !IsTargetIntrinsic(intrinsicName);
}
-bool Compiler::IsMathIntrinsic(CorInfoIntrinsics intrinsicId)
+bool Compiler::IsMathIntrinsic(NamedIntrinsic intrinsicName)
{
- switch (intrinsicId)
- {
- case CORINFO_INTRINSIC_Sin:
- case CORINFO_INTRINSIC_Cbrt:
- case CORINFO_INTRINSIC_Sqrt:
- case CORINFO_INTRINSIC_Abs:
- case CORINFO_INTRINSIC_Cos:
- case CORINFO_INTRINSIC_Round:
- case CORINFO_INTRINSIC_Cosh:
- case CORINFO_INTRINSIC_Sinh:
- case CORINFO_INTRINSIC_Tan:
- case CORINFO_INTRINSIC_Tanh:
- case CORINFO_INTRINSIC_Asin:
- case CORINFO_INTRINSIC_Asinh:
- case CORINFO_INTRINSIC_Acos:
- case CORINFO_INTRINSIC_Acosh:
- case CORINFO_INTRINSIC_Atan:
- case CORINFO_INTRINSIC_Atan2:
- case CORINFO_INTRINSIC_Atanh:
- case CORINFO_INTRINSIC_Log10:
- case CORINFO_INTRINSIC_Pow:
- case CORINFO_INTRINSIC_Exp:
- case CORINFO_INTRINSIC_Ceiling:
- case CORINFO_INTRINSIC_Floor:
+ switch (intrinsicName)
+ {
+ case NI_System_Math_Sin:
+ case NI_System_Math_Cbrt:
+ case NI_System_Math_Sqrt:
+ case NI_System_Math_Abs:
+ case NI_System_Math_Cos:
+ case NI_System_Math_Round:
+ case NI_System_Math_Cosh:
+ case NI_System_Math_Sinh:
+ case NI_System_Math_Tan:
+ case NI_System_Math_Tanh:
+ case NI_System_Math_Asin:
+ case NI_System_Math_Asinh:
+ case NI_System_Math_Acos:
+ case NI_System_Math_Acosh:
+ case NI_System_Math_Atan:
+ case NI_System_Math_Atan2:
+ case NI_System_Math_Atanh:
+ case NI_System_Math_Log10:
+ case NI_System_Math_Pow:
+ case NI_System_Math_Exp:
+ case NI_System_Math_Ceiling:
+ case NI_System_Math_Floor:
return true;
default:
return false;
bool Compiler::IsMathIntrinsic(GenTree* tree)
{
- return (tree->OperGet() == GT_INTRINSIC) && IsMathIntrinsic(tree->AsIntrinsic()->gtIntrinsicId);
+ return (tree->OperGet() == GT_INTRINSIC) && IsMathIntrinsic(tree->AsIntrinsic()->gtIntrinsicName);
}
//------------------------------------------------------------------------
{
assert(node->OperIs(GT_INTRINSIC));
- CorInfoIntrinsics intrinsicId = node->AsIntrinsic()->gtIntrinsicId;
+ NamedIntrinsic intrinsicName = node->AsIntrinsic()->gtIntrinsicName;
- if (intrinsicId == CORINFO_INTRINSIC_Sqrt || intrinsicId == CORINFO_INTRINSIC_Round ||
- intrinsicId == CORINFO_INTRINSIC_Ceiling || intrinsicId == CORINFO_INTRINSIC_Floor)
+ if (intrinsicName == NI_System_Math_Sqrt || intrinsicName == NI_System_Math_Round ||
+ intrinsicName == NI_System_Math_Ceiling || intrinsicName == NI_System_Math_Floor)
{
GenTree* op1 = node->gtGetOp1();
if (IsContainableMemoryOp(op1) || op1->IsCnsNonZeroFltOrDbl())
BuildUse(op1);
srcCount = 1;
- switch (tree->AsIntrinsic()->gtIntrinsicId)
+ switch (tree->AsIntrinsic()->gtIntrinsicName)
{
- case CORINFO_INTRINSIC_Abs:
- case CORINFO_INTRINSIC_Sqrt:
+ case NI_System_Math_Abs:
+ case NI_System_Math_Sqrt:
assert(dstCount == 1);
BuildDef(tree);
break;
case GT_INTRINSIC:
{
- noway_assert((tree->AsIntrinsic()->gtIntrinsicId == CORINFO_INTRINSIC_Abs) ||
- (tree->AsIntrinsic()->gtIntrinsicId == CORINFO_INTRINSIC_Ceiling) ||
- (tree->AsIntrinsic()->gtIntrinsicId == CORINFO_INTRINSIC_Floor) ||
- (tree->AsIntrinsic()->gtIntrinsicId == CORINFO_INTRINSIC_Round) ||
- (tree->AsIntrinsic()->gtIntrinsicId == CORINFO_INTRINSIC_Sqrt));
+ 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_Round) ||
+ (tree->AsIntrinsic()->gtIntrinsicName == NI_System_Math_Sqrt));
// Both operand and its result must be of the same floating point type.
GenTree* op1 = tree->gtGetOp1();
assert(op1->TypeGet() == tree->TypeGet());
RefPosition* internalFloatDef = nullptr;
- switch (tree->AsIntrinsic()->gtIntrinsicId)
+ switch (tree->AsIntrinsic()->gtIntrinsicName)
{
- case CORINFO_INTRINSIC_Abs:
+ case NI_System_Math_Abs:
// Abs(float x) = x & 0x7fffffff
// Abs(double x) = x & 0x7ffffff ffffffff
break;
#ifdef TARGET_X86
- case CORINFO_INTRINSIC_Cos:
- case CORINFO_INTRINSIC_Sin:
+ case NI_System_Math_Cos:
+ case NI_System_Math_Sin:
NYI_X86("Math intrinsics Cos and Sin");
break;
#endif // TARGET_X86
- case CORINFO_INTRINSIC_Sqrt:
- case CORINFO_INTRINSIC_Round:
- case CORINFO_INTRINSIC_Ceiling:
- case CORINFO_INTRINSIC_Floor:
+ case NI_System_Math_Sqrt:
+ case NI_System_Math_Round:
+ case NI_System_Math_Ceiling:
+ case NI_System_Math_Floor:
break;
default:
}
#ifdef FEATURE_SIMD
- // if this field belongs to simd struct, translate it to simd instrinsic.
+ // if this field belongs to simd struct, translate it to simd intrinsic.
if (mac == nullptr)
{
GenTree* newTree = fgMorphFieldToSIMDIntrinsicGet(tree);
#ifdef TARGET_ARM
case GT_INTRINSIC:
- if (tree->AsIntrinsic()->gtIntrinsicId == CORINFO_INTRINSIC_Round)
+ if (tree->AsIntrinsic()->gtIntrinsicName == NI_System_Math_Round)
{
switch (tree->TypeGet())
{
NI_System_Enum_HasFlag,
NI_System_Math_FusedMultiplyAdd,
+ NI_System_Math_Sin,
+ NI_System_Math_Cos,
+ NI_System_Math_Cbrt,
+ NI_System_Math_Sqrt,
+ NI_System_Math_Abs,
NI_System_Math_Round,
- NI_System_MathF_FusedMultiplyAdd,
- NI_System_MathF_Round,
+ NI_System_Math_Cosh,
+ NI_System_Math_Sinh,
+ NI_System_Math_Tan,
+ NI_System_Math_Tanh,
+ NI_System_Math_Asin,
+ NI_System_Math_Asinh,
+ NI_System_Math_Acos,
+ NI_System_Math_Acosh,
+ NI_System_Math_Atan,
+ NI_System_Math_Atan2,
+ NI_System_Math_Atanh,
+ NI_System_Math_Log10,
+ NI_System_Math_Pow,
+ NI_System_Math_Exp,
+ NI_System_Math_Ceiling,
+ NI_System_Math_Floor,
NI_System_Collections_Generic_EqualityComparer_get_Default,
NI_System_Buffers_Binary_BinaryPrimitives_ReverseEndianness,
NI_System_GC_KeepAlive,
case GT_INTRINSIC:
// Non-target intrinsics should have already been rewritten back into user calls.
- assert(comp->IsTargetIntrinsic(node->AsIntrinsic()->gtIntrinsicId));
+ assert(comp->IsTargetIntrinsic(node->AsIntrinsic()->gtIntrinsicName));
break;
#ifdef FEATURE_SIMD
{
GenTree* const node = *use;
if (node->OperGet() == GT_INTRINSIC &&
- m_rationalizer.comp->IsIntrinsicImplementedByUserCall(node->AsIntrinsic()->gtIntrinsicId))
+ m_rationalizer.comp->IsIntrinsicImplementedByUserCall(node->AsIntrinsic()->gtIntrinsicName))
{
m_rationalizer.RewriteIntrinsicAsUserCall(use, this->m_ancestors);
}
m_checkedBoundVNs.AddOrUpdate(vn, true);
}
-ValueNum ValueNumStore::EvalMathFuncUnary(var_types typ, CorInfoIntrinsics gtMathFN, ValueNum arg0VN)
+ValueNum ValueNumStore::EvalMathFuncUnary(var_types typ, NamedIntrinsic gtMathFN, ValueNum arg0VN)
{
assert(arg0VN == VNNormalValue(arg0VN));
double res = 0.0;
switch (gtMathFN)
{
- case CORINFO_INTRINSIC_Sin:
+ case NI_System_Math_Sin:
res = sin(arg0Val);
break;
- case CORINFO_INTRINSIC_Cos:
+ case NI_System_Math_Cos:
res = cos(arg0Val);
break;
- case CORINFO_INTRINSIC_Sqrt:
+ case NI_System_Math_Sqrt:
res = sqrt(arg0Val);
break;
- case CORINFO_INTRINSIC_Abs:
+ case NI_System_Math_Abs:
res = fabs(arg0Val);
break;
- case CORINFO_INTRINSIC_Ceiling:
+ case NI_System_Math_Ceiling:
res = ceil(arg0Val);
break;
- case CORINFO_INTRINSIC_Floor:
+ case NI_System_Math_Floor:
res = floor(arg0Val);
break;
- case CORINFO_INTRINSIC_Round:
+ case NI_System_Math_Round:
res = FloatingPointUtils::round(arg0Val);
break;
default:
float res = 0.0f;
switch (gtMathFN)
{
- case CORINFO_INTRINSIC_Sin:
+ case NI_System_Math_Sin:
res = sinf(arg0Val);
break;
- case CORINFO_INTRINSIC_Cos:
+ case NI_System_Math_Cos:
res = cosf(arg0Val);
break;
- case CORINFO_INTRINSIC_Sqrt:
+ case NI_System_Math_Sqrt:
res = sqrtf(arg0Val);
break;
- case CORINFO_INTRINSIC_Abs:
+ case NI_System_Math_Abs:
res = fabsf(arg0Val);
break;
- case CORINFO_INTRINSIC_Ceiling:
+ case NI_System_Math_Ceiling:
res = ceilf(arg0Val);
break;
- case CORINFO_INTRINSIC_Floor:
+ case NI_System_Math_Floor:
res = floorf(arg0Val);
break;
- case CORINFO_INTRINSIC_Round:
+ case NI_System_Math_Round:
res = FloatingPointUtils::round(arg0Val);
break;
default:
}
else
{
- // CORINFO_INTRINSIC_Round is currently the only intrinsic that takes floating-point arguments
- // and that returns a non floating-point result.
+ // NI_System_Math{F}_Round are currently the only intrinsic that take floating-point arguments
+ // and return a non floating-point result.
assert(typ == TYP_INT);
- assert(gtMathFN == CORINFO_INTRINSIC_Round);
+ assert(gtMathFN == NI_System_Math_Round);
int res = 0;
}
else
{
- assert(typ == TYP_DOUBLE || typ == TYP_FLOAT || (typ == TYP_INT && gtMathFN == CORINFO_INTRINSIC_Round));
+ assert(typ == TYP_DOUBLE || typ == TYP_FLOAT || typ == TYP_INT && gtMathFN == NI_System_Math_Round);
VNFunc vnf = VNF_Boundary;
switch (gtMathFN)
{
- case CORINFO_INTRINSIC_Sin:
+ case NI_System_Math_Sin:
vnf = VNF_Sin;
break;
- case CORINFO_INTRINSIC_Cos:
+ case NI_System_Math_Cos:
vnf = VNF_Cos;
break;
- case CORINFO_INTRINSIC_Cbrt:
+ case NI_System_Math_Cbrt:
vnf = VNF_Cbrt;
break;
- case CORINFO_INTRINSIC_Sqrt:
+ case NI_System_Math_Sqrt:
vnf = VNF_Sqrt;
break;
- case CORINFO_INTRINSIC_Abs:
+ case NI_System_Math_Abs:
vnf = VNF_Abs;
break;
- case CORINFO_INTRINSIC_Round:
+ case NI_System_Math_Round:
if (typ == TYP_DOUBLE)
{
vnf = VNF_RoundDouble;
noway_assert(!"Invalid INTRINSIC_Round");
}
break;
- case CORINFO_INTRINSIC_Cosh:
+ case NI_System_Math_Cosh:
vnf = VNF_Cosh;
break;
- case CORINFO_INTRINSIC_Sinh:
+ case NI_System_Math_Sinh:
vnf = VNF_Sinh;
break;
- case CORINFO_INTRINSIC_Tan:
+ case NI_System_Math_Tan:
vnf = VNF_Tan;
break;
- case CORINFO_INTRINSIC_Tanh:
+ case NI_System_Math_Tanh:
vnf = VNF_Tanh;
break;
- case CORINFO_INTRINSIC_Asin:
+ case NI_System_Math_Asin:
vnf = VNF_Asin;
break;
- case CORINFO_INTRINSIC_Asinh:
+ case NI_System_Math_Asinh:
vnf = VNF_Asinh;
break;
- case CORINFO_INTRINSIC_Acos:
+ case NI_System_Math_Acos:
vnf = VNF_Acos;
break;
- case CORINFO_INTRINSIC_Acosh:
+ case NI_System_Math_Acosh:
vnf = VNF_Acosh;
break;
- case CORINFO_INTRINSIC_Atan:
+ case NI_System_Math_Atan:
vnf = VNF_Atan;
break;
- case CORINFO_INTRINSIC_Atanh:
+ case NI_System_Math_Atanh:
vnf = VNF_Atanh;
break;
- case CORINFO_INTRINSIC_Log10:
+ case NI_System_Math_Log10:
vnf = VNF_Log10;
break;
- case CORINFO_INTRINSIC_Exp:
+ case NI_System_Math_Exp:
vnf = VNF_Exp;
break;
- case CORINFO_INTRINSIC_Ceiling:
+ case NI_System_Math_Ceiling:
vnf = VNF_Ceiling;
break;
- case CORINFO_INTRINSIC_Floor:
+ case NI_System_Math_Floor:
vnf = VNF_Floor;
break;
default:
}
}
-ValueNum ValueNumStore::EvalMathFuncBinary(var_types typ, CorInfoIntrinsics gtMathFN, ValueNum arg0VN, ValueNum arg1VN)
+ValueNum ValueNumStore::EvalMathFuncBinary(var_types typ, NamedIntrinsic gtMathFN, ValueNum arg0VN, ValueNum arg1VN)
{
assert(varTypeIsFloating(typ));
assert(arg0VN == VNNormalValue(arg0VN));
switch (gtMathFN)
{
- case CORINFO_INTRINSIC_Atan2:
+ case NI_System_Math_Atan2:
vnf = VNF_Atan2;
break;
- case CORINFO_INTRINSIC_Pow:
+ case NI_System_Math_Pow:
vnf = VNF_Pow;
break;
vnStore->VNPUnpackExc(intrinsic->AsOp()->gtOp2->gtVNPair, &arg1VNP, &arg1VNPx);
}
- if (IsMathIntrinsic(intrinsic->gtIntrinsicId))
+ if (IsMathIntrinsic(intrinsic->gtIntrinsicName))
{
// GT_INTRINSIC is a currently a subtype of binary operators. But most of
// the math intrinsics are actually unary operations.
if (intrinsic->AsOp()->gtOp2 == nullptr)
{
intrinsic->gtVNPair =
- vnStore->VNPWithExc(vnStore->EvalMathFuncUnary(tree->TypeGet(), intrinsic->gtIntrinsicId, arg0VNP),
+ vnStore->VNPWithExc(vnStore->EvalMathFuncUnary(tree->TypeGet(), intrinsic->gtIntrinsicName, arg0VNP),
arg0VNPx);
}
else
{
ValueNumPair newVNP =
- vnStore->EvalMathFuncBinary(tree->TypeGet(), intrinsic->gtIntrinsicId, arg0VNP, arg1VNP);
+ vnStore->EvalMathFuncBinary(tree->TypeGet(), intrinsic->gtIntrinsicName, arg0VNP, arg1VNP);
ValueNumPair excSet = vnStore->VNPExcSetUnion(arg0VNPx, arg1VNPx);
intrinsic->gtVNPair = vnStore->VNPWithExc(newVNP, excSet);
}
else if (tree->AsOp()->gtOp1->OperIs(GT_LIST) || (lookupNumArgs == -1))
{
// We have a HWINTRINSIC node in the GT_LIST form with 3 or more args
- // Or the numArgs was specified as -1 in the numArgs column in "hwinstrinsiclistxarch.h"
+ // Or the numArgs was specified as -1 in the numArgs column in "hwintrinsiclistxarch.h"
// For now we will generate a unique value number for this case.
// Generate unique VN
// "arg0VN". For binary ops, return the value number for the application of this function to "arg0VN" and
// "arg1VN".
- ValueNum EvalMathFuncUnary(var_types typ, CorInfoIntrinsics mthFunc, ValueNum arg0VN);
+ ValueNum EvalMathFuncUnary(var_types typ, NamedIntrinsic mthFunc, ValueNum arg0VN);
- ValueNum EvalMathFuncBinary(var_types typ, CorInfoIntrinsics mthFunc, ValueNum arg0VN, ValueNum arg1VN);
+ ValueNum EvalMathFuncBinary(var_types typ, NamedIntrinsic mthFunc, ValueNum arg0VN, ValueNum arg1VN);
- ValueNumPair EvalMathFuncUnary(var_types typ, CorInfoIntrinsics mthFunc, ValueNumPair arg0VNP)
+ ValueNumPair EvalMathFuncUnary(var_types typ, NamedIntrinsic mthFunc, ValueNumPair arg0VNP)
{
return ValueNumPair(EvalMathFuncUnary(typ, mthFunc, arg0VNP.GetLiberal()),
EvalMathFuncUnary(typ, mthFunc, arg0VNP.GetConservative()));
}
- ValueNumPair EvalMathFuncBinary(var_types typ,
- CorInfoIntrinsics mthFunc,
- ValueNumPair arg0VNP,
- ValueNumPair arg1VNP)
+ ValueNumPair EvalMathFuncBinary(var_types typ, NamedIntrinsic mthFunc, ValueNumPair arg0VNP, ValueNumPair arg1VNP)
{
return ValueNumPair(EvalMathFuncBinary(typ, mthFunc, arg0VNP.GetLiberal(), arg1VNP.GetLiberal()),
EvalMathFuncBinary(typ, mthFunc, arg0VNP.GetConservative(), arg1VNP.GetConservative()));
{
IntrinsicHashtable table = new IntrinsicHashtable();
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Sin, "Sin", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Sin, "Sin", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Cos, "Cos", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Cos, "Cos", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Cbrt, "Cbrt", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Cbrt, "Cbrt", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Sqrt, "Sqrt", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Sqrt, "Sqrt", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Abs, "Abs", "System", "Math");
- // No System.MathF entry for CORINFO_INTRTINSIC_Abs as System.Math exposes and handles both float and double
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Round, "Round", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Round, "Round", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Cosh, "Cosh", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Cosh, "Cosh", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Sinh, "Sinh", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Sinh, "Sinh", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Tan, "Tan", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Tan, "Tan", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Tanh, "Tanh", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Tanh, "Tanh", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Asin, "Asin", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Asin, "Asin", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Asinh, "Asinh", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Asinh, "Asinh", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Acos, "Acos", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Acos, "Acos", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Acosh, "Acosh", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Acosh, "Acosh", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Atan, "Atan", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Atan, "Atan", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Atan2, "Atan2", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Atan2, "Atan2", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Atanh, "Atanh", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Atanh, "Atanh", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Log10, "Log10", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Log10, "Log10", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Pow, "Pow", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Pow, "Pow", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Exp, "Exp", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Exp, "Exp", "System", "MathF");
-#if !READYTORUN
- // These are normally handled via the SSE4.1 instructions ROUNDSS/ROUNDSD.
- // However, we don't know the ISAs the target machine supports so we should
- // fallback to the method call implementation instead.
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Ceiling, "Ceiling", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Ceiling, "Ceiling", "System", "MathF");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Floor, "Floor", "System", "Math");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Floor, "Floor", "System", "MathF");
-#endif
// table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_GetChar, null, null, null); // unused
// table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Array_GetDimLength, "GetLength", "System", "Array"); // not handled
table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Array_Get, "Get", null, null);
table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_GetRawHandle, "AllocatorOf", "System", "Activator");
// If this assert fails, make sure to add the new intrinsics to the table above and update the expected count below.
- Debug.Assert((int)CorInfoIntrinsics.CORINFO_INTRINSIC_Count == 56, "Please update intrinsic hash table");
+ Debug.Assert((int)CorInfoIntrinsics.CORINFO_INTRINSIC_Count == 34, "Please update intrinsic hash table");
return table;
}
CorInfoIntrinsics id = entry.Id;
switch (id)
{
- case CorInfoIntrinsics.CORINFO_INTRINSIC_Abs:
- {
- // RyuJIT handles floating point overloads only
- var returnTypeCategory = method.Signature.ReturnType.Category;
- if (returnTypeCategory != TypeFlags.Double && returnTypeCategory != TypeFlags.Single)
- return CorInfoIntrinsics.CORINFO_INTRINSIC_Illegal;
- }
- break;
case CorInfoIntrinsics.CORINFO_INTRINSIC_Array_Get:
case CorInfoIntrinsics.CORINFO_INTRINSIC_Array_Address:
case CorInfoIntrinsics.CORINFO_INTRINSIC_Array_Set:
// do a dynamic check instead.
if (
!HardwareIntrinsicHelpers.IsIsSupportedMethod(method)
- || !_compilation.IsHardwareInstrinsicWithRuntimeDeterminedSupport(method))
+ || !_compilation.IsHardwareIntrinsicWithRuntimeDeterminedSupport(method))
#endif
{
result |= CorInfoFlag.CORINFO_FLG_JIT_INTRINSIC;
public enum CorInfoIntrinsics
{
- CORINFO_INTRINSIC_Sin,
- CORINFO_INTRINSIC_Cos,
- CORINFO_INTRINSIC_Cbrt,
- CORINFO_INTRINSIC_Sqrt,
- CORINFO_INTRINSIC_Abs,
- CORINFO_INTRINSIC_Round,
- CORINFO_INTRINSIC_Cosh,
- CORINFO_INTRINSIC_Sinh,
- CORINFO_INTRINSIC_Tan,
- CORINFO_INTRINSIC_Tanh,
- CORINFO_INTRINSIC_Asin,
- CORINFO_INTRINSIC_Asinh,
- CORINFO_INTRINSIC_Acos,
- CORINFO_INTRINSIC_Acosh,
- CORINFO_INTRINSIC_Atan,
- CORINFO_INTRINSIC_Atan2,
- CORINFO_INTRINSIC_Atanh,
- CORINFO_INTRINSIC_Log10,
- CORINFO_INTRINSIC_Pow,
- CORINFO_INTRINSIC_Exp,
- CORINFO_INTRINSIC_Ceiling,
- CORINFO_INTRINSIC_Floor,
CORINFO_INTRINSIC_GetChar, // fetch character out of string
CORINFO_INTRINSIC_Array_GetDimLength, // Get number of elements in a given dimension of an array
CORINFO_INTRINSIC_Array_Get, // Get the value of an element in an array
uint64_t corJitFlags;
};
-static const GUID JITEEVersionIdentifier = { /* 164b4e4f-21f6-4d05-b560-3728395404f2 */
- 0x164b4e4f,
- 0x21f6,
- 0x4d05,
- { 0xb5, 0x60, 0x37, 0x28, 0x39, 0x54, 0x04, 0xf2 }
+static const GUID JITEEVersionIdentifier = { /* a5eec3a4-4176-43a7-8c2b-a05b551d4f49 */
+ 0xa5eec3a4,
+ 0x4176,
+ 0x43a7,
+ {0x8c, 0x2b, 0xa0, 0x5b, 0x55, 0x1d, 0x4f, 0x49}
};
class Jit
FCFuncEnd()
FCFuncStart(gMathFuncs)
- FCIntrinsicSig("Abs", &gsig_SM_Dbl_RetDbl, COMDouble::Abs, CORINFO_INTRINSIC_Abs)
- FCIntrinsicSig("Abs", &gsig_SM_Flt_RetFlt, COMSingle::Abs, CORINFO_INTRINSIC_Abs)
- FCIntrinsic("Acos", COMDouble::Acos, CORINFO_INTRINSIC_Acos)
- FCIntrinsic("Acosh", COMDouble::Acosh, CORINFO_INTRINSIC_Acosh)
- FCIntrinsic("Asin", COMDouble::Asin, CORINFO_INTRINSIC_Asin)
- FCIntrinsic("Asinh", COMDouble::Asinh, CORINFO_INTRINSIC_Asinh)
- FCIntrinsic("Atan", COMDouble::Atan, CORINFO_INTRINSIC_Atan)
- FCIntrinsic("Atanh", COMDouble::Atanh, CORINFO_INTRINSIC_Atanh)
- FCIntrinsic("Atan2", COMDouble::Atan2, CORINFO_INTRINSIC_Atan2)
- FCIntrinsic("Cbrt", COMDouble::Cbrt, CORINFO_INTRINSIC_Cbrt)
- FCIntrinsic("Ceiling", COMDouble::Ceil, CORINFO_INTRINSIC_Ceiling)
- FCIntrinsic("Cos", COMDouble::Cos, CORINFO_INTRINSIC_Cos)
- FCIntrinsic("Cosh", COMDouble::Cosh, CORINFO_INTRINSIC_Cosh)
- FCIntrinsic("Exp", COMDouble::Exp, CORINFO_INTRINSIC_Exp)
- FCIntrinsic("Floor", COMDouble::Floor, CORINFO_INTRINSIC_Floor)
+ FCFuncElementSig("Abs", &gsig_SM_Dbl_RetDbl, COMDouble::Abs)
+ FCFuncElementSig("Abs", &gsig_SM_Flt_RetFlt, COMSingle::Abs)
+ FCFuncElement("Acos", COMDouble::Acos)
+ FCFuncElement("Acosh", COMDouble::Acosh)
+ FCFuncElement("Asin", COMDouble::Asin)
+ FCFuncElement("Asinh", COMDouble::Asinh)
+ FCFuncElement("Atan", COMDouble::Atan)
+ FCFuncElement("Atanh", COMDouble::Atanh)
+ FCFuncElement("Atan2", COMDouble::Atan2)
+ FCFuncElement("Cbrt", COMDouble::Cbrt)
+ FCFuncElement("Ceiling", COMDouble::Ceil)
+ FCFuncElement("Cos", COMDouble::Cos)
+ FCFuncElement("Cosh", COMDouble::Cosh)
+ FCFuncElement("Exp", COMDouble::Exp)
+ FCFuncElement("Floor", COMDouble::Floor)
FCFuncElement("FMod", COMDouble::FMod)
FCFuncElement("FusedMultiplyAdd", COMDouble::FusedMultiplyAdd)
FCFuncElement("ILogB", COMDouble::ILogB)
FCFuncElement("Log", COMDouble::Log)
FCFuncElement("Log2", COMDouble::Log2)
- FCIntrinsic("Log10", COMDouble::Log10, CORINFO_INTRINSIC_Log10)
+ FCFuncElement("Log10", COMDouble::Log10)
FCFuncElement("ModF", COMDouble::ModF)
- FCIntrinsic("Pow", COMDouble::Pow, CORINFO_INTRINSIC_Pow)
+ FCFuncElement("Pow", COMDouble::Pow)
FCFuncElement("ScaleB", COMDouble::ScaleB)
- FCIntrinsic("Sin", COMDouble::Sin, CORINFO_INTRINSIC_Sin)
- FCIntrinsic("Sinh", COMDouble::Sinh, CORINFO_INTRINSIC_Sinh)
- FCIntrinsic("Sqrt", COMDouble::Sqrt, CORINFO_INTRINSIC_Sqrt)
- FCIntrinsic("Tan", COMDouble::Tan, CORINFO_INTRINSIC_Tan)
- FCIntrinsic("Tanh", COMDouble::Tanh, CORINFO_INTRINSIC_Tanh)
+ FCFuncElement("Sin", COMDouble::Sin)
+ FCFuncElement("Sinh", COMDouble::Sinh)
+ FCFuncElement("Sqrt", COMDouble::Sqrt)
+ FCFuncElement("Tan", COMDouble::Tan)
+ FCFuncElement("Tanh", COMDouble::Tanh)
FCFuncEnd()
FCFuncStart(gMathFFuncs)
- FCIntrinsic("Acos", COMSingle::Acos, CORINFO_INTRINSIC_Acos)
- FCIntrinsic("Acosh", COMSingle::Acosh, CORINFO_INTRINSIC_Acosh)
- FCIntrinsic("Asin", COMSingle::Asin, CORINFO_INTRINSIC_Asin)
- FCIntrinsic("Asinh", COMSingle::Asinh, CORINFO_INTRINSIC_Asinh)
- FCIntrinsic("Atan", COMSingle::Atan, CORINFO_INTRINSIC_Atan)
- FCIntrinsic("Atanh", COMSingle::Atanh, CORINFO_INTRINSIC_Atanh)
- FCIntrinsic("Atan2", COMSingle::Atan2, CORINFO_INTRINSIC_Atan2)
- FCIntrinsic("Cbrt", COMSingle::Cbrt, CORINFO_INTRINSIC_Cbrt)
- FCIntrinsic("Ceiling", COMSingle::Ceil, CORINFO_INTRINSIC_Ceiling)
- FCIntrinsic("Cos", COMSingle::Cos, CORINFO_INTRINSIC_Cos)
- FCIntrinsic("Cosh", COMSingle::Cosh, CORINFO_INTRINSIC_Cosh)
- FCIntrinsic("Exp", COMSingle::Exp, CORINFO_INTRINSIC_Exp)
- FCIntrinsic("Floor", COMSingle::Floor, CORINFO_INTRINSIC_Floor)
+ FCFuncElement("Acos", COMSingle::Acos)
+ FCFuncElement("Acosh", COMSingle::Acosh)
+ FCFuncElement("Asin", COMSingle::Asin)
+ FCFuncElement("Asinh", COMSingle::Asinh)
+ FCFuncElement("Atan", COMSingle::Atan)
+ FCFuncElement("Atanh", COMSingle::Atanh)
+ FCFuncElement("Atan2", COMSingle::Atan2)
+ FCFuncElement("Cbrt", COMSingle::Cbrt)
+ FCFuncElement("Ceiling", COMSingle::Ceil)
+ FCFuncElement("Cos", COMSingle::Cos)
+ FCFuncElement("Cosh", COMSingle::Cosh)
+ FCFuncElement("Exp", COMSingle::Exp)
+ FCFuncElement("Floor", COMSingle::Floor)
FCFuncElement("FMod", COMSingle::FMod)
FCFuncElement("FusedMultiplyAdd", COMSingle::FusedMultiplyAdd)
FCFuncElement("ILogB", COMSingle::ILogB)
FCFuncElement("Log", COMSingle::Log)
FCFuncElement("Log2", COMSingle::Log2)
- FCIntrinsic("Log10", COMSingle::Log10, CORINFO_INTRINSIC_Log10)
+ FCFuncElement("Log10", COMSingle::Log10)
FCFuncElement("ModF", COMSingle::ModF)
- FCIntrinsic("Pow", COMSingle::Pow, CORINFO_INTRINSIC_Pow)
+ FCFuncElement("Pow", COMSingle::Pow)
FCFuncElement("ScaleB", COMSingle::ScaleB)
- FCIntrinsic("Sin", COMSingle::Sin, CORINFO_INTRINSIC_Sin)
- FCIntrinsic("Sinh", COMSingle::Sinh, CORINFO_INTRINSIC_Sinh)
- FCIntrinsic("Sqrt", COMSingle::Sqrt, CORINFO_INTRINSIC_Sqrt)
- FCIntrinsic("Tan", COMSingle::Tan, CORINFO_INTRINSIC_Tan)
- FCIntrinsic("Tanh", COMSingle::Tanh, CORINFO_INTRINSIC_Tanh)
+ FCFuncElement("Sin", COMSingle::Sin)
+ FCFuncElement("Sinh", COMSingle::Sinh)
+ FCFuncElement("Sqrt", COMSingle::Sqrt)
+ FCFuncElement("Tan", COMSingle::Tan)
+ FCFuncElement("Tanh", COMSingle::Tanh)
FCFuncEnd()
FCFuncStart(gThreadFuncs)
#if defined(TARGET_X86) || defined(TARGET_AMD64)
else if (strcmp(namespaceName, "System") == 0)
{
- if ((strcmp(className, "Math") == 0) || (strcmp(className, "MathF") == 0))
+ if (strcmp(className, "Math") == 0 || strcmp(className, "MathF") == 0)
{
// These are normally handled via the SSE4.1 instructions ROUNDSS/ROUNDSD.
// However, we don't know the ISAs the target machine supports so we should
// fallback to the method call implementation instead.
- fTreatAsRegularMethodCall = strcmp(methodName, "Round") == 0;
+ fTreatAsRegularMethodCall = strcmp(methodName, "Round") == 0 || strcmp(methodName, "Ceiling") == 0 ||
+ strcmp(methodName, "Floor") == 0;
}
}
else if (strcmp(namespaceName, "System.Numerics") == 0)
CorInfoIntrinsics ZapInfo::getIntrinsicID(CORINFO_METHOD_HANDLE method,
bool * pMustExpand)
{
- CorInfoIntrinsics intrinsicID = m_pEEJitInfo->getIntrinsicID(method, pMustExpand);
-
-#if defined(TARGET_X86) || defined(TARGET_AMD64)
- if ((intrinsicID == CORINFO_INTRINSIC_Ceiling) || (intrinsicID == CORINFO_INTRINSIC_Floor))
- {
- // These are normally handled via the SSE4.1 instructions ROUNDSS/ROUNDSD.
- // However, we don't know the ISAs the target machine supports so we should
- // fallback to the method call implementation instead.
- intrinsicID = CORINFO_INTRINSIC_Illegal;
- }
-#endif // defined(TARGET_X86) || defined(TARGET_AMD64)
-
- return intrinsicID;
+ return m_pEEJitInfo->getIntrinsicID(method, pMustExpand);
}
bool ZapInfo::isIntrinsicType(CORINFO_CLASS_HANDLE classHnd)