From 6589e221cb6677f4cbf8e94eebddfd390d7f29c4 Mon Sep 17 00:00:00 2001 From: dotnet-bot Date: Wed, 17 Feb 2016 11:03:58 -0800 Subject: [PATCH] Option for Enforcing Intrinsic Expansion Currently intrinsic is disabled under MIN_OPT while being enabled under OPT. There is no way to enforce intrinsic expansion where non-intrinsic (call) path is not yet implemented. This adds an optional output boolean argument to getIntrinsicID that tells JIT whether to enforce intrinsic expansion. If JIT cannot expand intrinsic for such case, fatal error occurs. There is no functional change the argument is default to false. [tfs-changeset: 1575973] --- src/inc/corinfo.h | 18 +++++++--- src/jit/importer.cpp | 74 +++++++++++++++++++++++++++-------------- src/vm/jitinterface.cpp | 8 ++++- src/vm/jitinterface.h | 3 +- src/zap/zapinfo.cpp | 5 +-- src/zap/zapinfo.h | 3 +- 6 files changed, 76 insertions(+), 35 deletions(-) diff --git a/src/inc/corinfo.h b/src/inc/corinfo.h index 86f46a6092..0cbbf7a11e 100644 --- a/src/inc/corinfo.h +++ b/src/inc/corinfo.h @@ -231,11 +231,11 @@ TODO: Talk about initializing strutures before use #if COR_JIT_EE_VERSION > 460 // Update this one -SELECTANY const GUID JITEEVersionIdentifier = { /* b26841f8-74d6-4fc9-9d81-6500cd662549 */ - 0xb26841f8, - 0x74d6, - 0x4fc9, - { 0x9d, 0x81, 0x65, 0x00, 0xcd, 0x66, 0x25, 0x49 } +SELECTANY const GUID JITEEVersionIdentifier = { /* 13accf3d-12d7-4fd4-bc65-d73578b1a474 */ + 0x13accf3d, + 0x12d7, + 0x4fd4, + { 0xbc, 0x65, 0xd7, 0x35, 0x78, 0xb1, 0xa4, 0x74 } }; #else @@ -2426,9 +2426,17 @@ public: // If a method's attributes have (getMethodAttribs) CORINFO_FLG_INTRINSIC set, // getIntrinsicID() returns the intrinsic ID. + // *pMustExpand tells whether or not JIT must expand the intrinsic. +#if COR_JIT_EE_VERSION > 460 + virtual CorInfoIntrinsics getIntrinsicID( + CORINFO_METHOD_HANDLE method, + bool* pMustExpand = NULL /* OUT */ + ) = 0; +#else virtual CorInfoIntrinsics getIntrinsicID( CORINFO_METHOD_HANDLE method ) = 0; +#endif // Is the given module the System.Numerics.Vectors module? // This defaults to false. diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp index c211c35336..f69ce97e26 100644 --- a/src/jit/importer.cpp +++ b/src/jit/importer.cpp @@ -2880,7 +2880,14 @@ GenTreePtr Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, bool readonlyCall, CorInfoIntrinsics * pIntrinsicID) { + bool mustExpand = false; +#if COR_JIT_EE_VERSION > 460 + CorInfoIntrinsics intrinsicID = info.compCompHnd->getIntrinsicID(method, &mustExpand); +#else CorInfoIntrinsics intrinsicID = info.compCompHnd->getIntrinsicID(method); +#endif + *pIntrinsicID = intrinsicID; + #ifndef _TARGET_ARM_ genTreeOps interlockedOperator; #endif @@ -2888,32 +2895,27 @@ GenTreePtr Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, if (intrinsicID == CORINFO_INTRINSIC_StubHelpers_GetStubContext) { // must be done regardless of DbgCode and MinOpts - *pIntrinsicID = intrinsicID; return gtNewLclvNode(lvaStubArgumentVar, TYP_I_IMPL); } #ifdef _TARGET_64BIT_ if (intrinsicID == CORINFO_INTRINSIC_StubHelpers_GetStubContextAddr) { // must be done regardless of DbgCode and MinOpts - *pIntrinsicID = intrinsicID; return gtNewOperNode(GT_ADDR, TYP_I_IMPL, gtNewLclvNode(lvaStubArgumentVar, TYP_I_IMPL)); } #endif + GenTreePtr retNode = nullptr; + // // We disable the inlining of instrinsics for MinOpts. // - if (opts.compDbgCode || opts.MinOpts()) + if (!mustExpand && (opts.compDbgCode || opts.MinOpts())) { *pIntrinsicID = CORINFO_INTRINSIC_Illegal; - return nullptr; + return retNode; } - *pIntrinsicID = intrinsicID; - - if (intrinsicID < 0 || CORINFO_INTRINSIC_Count <= intrinsicID) - return nullptr; - // Currently we don't have CORINFO_INTRINSIC_Exp because it does not // seem to work properly for Infinity values, we don't do // CORINFO_INTRINSIC_Pow because it needs a Helper which we currently don't have @@ -3012,8 +3014,7 @@ GenTreePtr Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, break; default: - assert(!"Unsupport number of args for Math Instrinsic"); - return nullptr; + NO_WAY("Unsupported number of args for Math Instrinsic"); } } @@ -3023,7 +3024,8 @@ GenTreePtr Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, op1->gtFlags |= GTF_CALL; } #endif - return op1; + retNode = op1; + break; #ifdef _TARGET_XARCH_ @@ -3063,7 +3065,8 @@ InterlockedBinOpCommon: op1 = gtNewOperNode(interlockedOperator, genActualType(callType), op1, op2); op1->gtFlags |= GTF_GLOB_EFFECT; - return op1; + retNode = op1; + break; #endif // _TARGET_XARCH_ case CORINFO_INTRINSIC_MemoryBarrier: @@ -3072,7 +3075,8 @@ InterlockedBinOpCommon: op1 = new (this, GT_MEMORYBARRIER) GenTree(GT_MEMORYBARRIER, TYP_VOID); op1->gtFlags |= GTF_GLOB_EFFECT; - return op1; + retNode = op1; + break; #ifdef _TARGET_XARCH_ // TODO-ARM-CQ: reenable treating InterlockedCmpXchg32 operation as intrinsic @@ -3093,7 +3097,8 @@ InterlockedBinOpCommon: GenTreeCmpXchg(genActualType(callType), op1, op2, op3); node->gtCmpXchg.gtOpLocation->gtFlags |= GTF_DONT_CSE; - return node; + retNode = node; + break; } #endif @@ -3111,22 +3116,26 @@ InterlockedBinOpCommon: op1 = gtNewOperNode(GT_ADD, TYP_BYREF, op1, gtNewIconNode(offsetof(CORINFO_String, stringLen), TYP_I_IMPL)); op1 = gtNewOperNode(GT_IND, TYP_INT, op1); } - return op1; + retNode = op1; + break; case CORINFO_INTRINSIC_StringGetChar: op2 = impPopStack().val; op1 = impPopStack().val; op1 = gtNewIndexRef(TYP_CHAR, op1, op2); op1->gtFlags |= GTF_INX_STRING_LAYOUT; - return op1; + retNode = op1; + break; case CORINFO_INTRINSIC_InitializeArray: - return impInitializeArrayIntrinsic(sig); + retNode = impInitializeArrayIntrinsic(sig); + break; case CORINFO_INTRINSIC_Array_Address: case CORINFO_INTRINSIC_Array_Get: case CORINFO_INTRINSIC_Array_Set: - return impArrayAccessIntrinsic(clsHnd, sig, memberRef, readonlyCall, intrinsicID); + retNode = impArrayAccessIntrinsic(clsHnd, sig, memberRef, readonlyCall, intrinsicID); + break; case CORINFO_INTRINSIC_GetTypeFromHandle: op1 = impStackTop(0).val; @@ -3136,10 +3145,10 @@ InterlockedBinOpCommon: op1 = impPopStack().val; // Change call to return RuntimeType directly. op1->gtType = TYP_REF; - return op1; + retNode = op1; } // Call the regular function. - return NULL; + break; case CORINFO_INTRINSIC_RTH_GetValueInternal: op1 = impStackTop(0).val; @@ -3162,10 +3171,10 @@ InterlockedBinOpCommon: assert(op1->IsList()); assert(op1->gtOp.gtOp2 == nullptr); op1 = op1->gtOp.gtOp1; - return op1; + retNode = op1; } // Call the regular function. - return NULL; + break; #ifndef LEGACY_BACKEND case CORINFO_INTRINSIC_Object_GetType: @@ -3177,13 +3186,28 @@ InterlockedBinOpCommon: // Set also the EXCEPTION flag because the native implementation of // CORINFO_INTRINSIC_Object_GetType intrinsic can throw NullReferenceException. op1->gtFlags |= (GTF_CALL | GTF_EXCEPT); - return op1; + retNode = op1; + break; #endif default: /* Unknown intrinsic */ - return nullptr; + break; } + + if (mustExpand) + { + if (retNode == nullptr) + { + NO_WAY("JIT must expand the intrinsic!"); + } + else if (IsIntrinsicImplementedByUserCall(intrinsicID)) + { + NO_WAY("JIT must not implement the intrinsic by a user call!"); + } + } + + return retNode; } /*****************************************************************************/ diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index 451390ad7f..e8d2faec3b 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -8934,7 +8934,8 @@ CORINFO_MODULE_HANDLE CEEInfo::getMethodModule (CORINFO_METHOD_HANDLE methodHnd) } /*********************************************************************/ -CorInfoIntrinsics CEEInfo::getIntrinsicID(CORINFO_METHOD_HANDLE methodHnd) +CorInfoIntrinsics CEEInfo::getIntrinsicID(CORINFO_METHOD_HANDLE methodHnd, + bool * pMustExpand) { CONTRACTL { SO_TOLERANT; @@ -8947,6 +8948,11 @@ CorInfoIntrinsics CEEInfo::getIntrinsicID(CORINFO_METHOD_HANDLE methodHnd) JIT_TO_EE_TRANSITION(); + if (pMustExpand != NULL) + { + *pMustExpand = false; + } + MethodDesc* method = GetMethod(methodHnd); if (method->IsArray()) diff --git a/src/vm/jitinterface.h b/src/vm/jitinterface.h index bb9fc06115..076088d8ee 100644 --- a/src/vm/jitinterface.h +++ b/src/vm/jitinterface.h @@ -764,7 +764,8 @@ public: unsigned * pOffsetAfterIndirection ); - CorInfoIntrinsics getIntrinsicID(CORINFO_METHOD_HANDLE method); + CorInfoIntrinsics getIntrinsicID(CORINFO_METHOD_HANDLE method, + bool * pMustExpand = NULL); bool isInSIMDModule(CORINFO_CLASS_HANDLE classHnd); diff --git a/src/zap/zapinfo.cpp b/src/zap/zapinfo.cpp index e0306cd6fe..d26ecf4cba 100644 --- a/src/zap/zapinfo.cpp +++ b/src/zap/zapinfo.cpp @@ -4597,9 +4597,10 @@ void ZapInfo::getMethodVTableOffset(CORINFO_METHOD_HANDLE method, m_pEEJitInfo->getMethodVTableOffset(method, pOffsetOfIndirection, pOffsetAfterIndirection); } -CorInfoIntrinsics ZapInfo::getIntrinsicID(CORINFO_METHOD_HANDLE method) +CorInfoIntrinsics ZapInfo::getIntrinsicID(CORINFO_METHOD_HANDLE method, + bool * pMustExpand) { - return m_pEEJitInfo->getIntrinsicID(method); + return m_pEEJitInfo->getIntrinsicID(method, pMustExpand); } bool ZapInfo::isInSIMDModule(CORINFO_CLASS_HANDLE classHnd) diff --git a/src/zap/zapinfo.h b/src/zap/zapinfo.h index 3d7d231e1d..b56da9f4bf 100644 --- a/src/zap/zapinfo.h +++ b/src/zap/zapinfo.h @@ -746,7 +746,8 @@ public: unsigned * pOffsetOfIndirection, unsigned * pOffsetAfterIndirection); - CorInfoIntrinsics getIntrinsicID(CORINFO_METHOD_HANDLE method); + CorInfoIntrinsics getIntrinsicID(CORINFO_METHOD_HANDLE method, + bool * pMustExpand = NULL); bool isInSIMDModule(CORINFO_CLASS_HANDLE classHnd); CorInfoUnmanagedCallConv getUnmanagedCallConv(CORINFO_METHOD_HANDLE method); BOOL pInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig); -- 2.34.1