diff options
Diffstat (limited to 'src/jit/compiler.h')
-rw-r--r-- | src/jit/compiler.h | 190 |
1 files changed, 143 insertions, 47 deletions
diff --git a/src/jit/compiler.h b/src/jit/compiler.h index a8aad0cc89..b4077cf6f5 100644 --- a/src/jit/compiler.h +++ b/src/jit/compiler.h @@ -45,6 +45,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #include "valuenum.h" #include "reglist.h" #include "jittelemetry.h" +#include "namedintrinsiclist.h" #ifdef LATE_DISASM #include "disasm.h" #endif @@ -722,6 +723,8 @@ public: return (unsigned)(roundUp(lvExactSize, TARGET_POINTER_SIZE)); } + const size_t lvArgStackSize() const; + unsigned lvSlotNum; // original slot # (if remapped) typeInfo lvVerTypeInfo; // type info needed for verification @@ -2028,7 +2031,7 @@ public: GenTree* gtNewBlkOpNode(GenTreePtr dst, GenTreePtr srcOrFillVal, unsigned size, bool isVolatile, bool isCopyBlock); - GenTree* gtNewPutArgReg(var_types type, GenTreePtr arg); + GenTree* gtNewPutArgReg(var_types type, GenTreePtr arg, regNumber argReg); protected: void gtBlockOpInit(GenTreePtr result, GenTreePtr dst, GenTreePtr srcOrFillVal, bool isVolatile); @@ -2054,10 +2057,7 @@ public: GenTreeArgList* args, IL_OFFSETX ilOffset = BAD_IL_OFFSET); - GenTreeCall* gtNewHelperCallNode(unsigned helper, - var_types type, - unsigned flags = 0, - GenTreeArgList* args = nullptr); + GenTreeCall* gtNewHelperCallNode(unsigned helper, var_types type, GenTreeArgList* args = nullptr); GenTreePtr gtNewLclvNode(unsigned lnum, var_types type, IL_OFFSETX ILoffs = BAD_IL_OFFSET); @@ -2084,6 +2084,10 @@ public: GenTreePtr gtNewIndexRef(var_types typ, GenTreePtr arrayOp, GenTreePtr indexOp); + GenTreeArrLen* gtNewArrLen(var_types typ, GenTree* arrayOp, int lenOffset); + + GenTree* gtNewIndir(var_types typ, GenTree* addr); + GenTreeArgList* gtNewArgList(GenTreePtr op); GenTreeArgList* gtNewArgList(GenTreePtr op1, GenTreePtr op2); GenTreeArgList* gtNewArgList(GenTreePtr op1, GenTreePtr op2, GenTreePtr op3); @@ -2137,7 +2141,13 @@ public: GenTreePtr gtReplaceTree(GenTreePtr stmt, GenTreePtr tree, GenTreePtr replacementTree); - void gtUpdateSideEffects(GenTreePtr tree, unsigned oldGtFlags, unsigned newGtFlags); + void gtUpdateSideEffects(GenTree* stmt, GenTree* tree); + + void gtUpdateTreeAncestorsSideEffects(GenTree* tree); + + void gtUpdateStmtSideEffects(GenTree* stmt); + + void gtResetNodeSideEffects(GenTree* tree); // Returns "true" iff the complexity (not formally defined, but first interpretation // is #of nodes in subtree) of "tree" is greater than "limit". @@ -2229,6 +2239,18 @@ public: GenTreePtr gtFoldExprSpecial(GenTreePtr tree); GenTreePtr gtFoldExprCompare(GenTreePtr tree); + // Options to control behavior of gtTryRemoveBoxUpstreamEffects + enum BoxRemovalOptions + { + BR_REMOVE_AND_NARROW, // remove effects, minimize remaining work, return possibly narrowed source tree + BR_REMOVE_AND_NARROW_WANT_TYPE_HANDLE, // remove effects and minimize remaining work, return type handle tree + BR_REMOVE_BUT_NOT_NARROW, // remove effects, return original source tree + BR_DONT_REMOVE // just check if removal is possible + }; + + GenTree* gtTryRemoveBoxUpstreamEffects(GenTree* tree, BoxRemovalOptions options = BR_REMOVE_AND_NARROW); + GenTree* gtOptimizeEnumHasFlag(GenTree* thisOp, GenTree* flagOp); + //------------------------------------------------------------------------- // Get the handle, if any. CORINFO_CLASS_HANDLE gtGetStructHandleIfPresent(GenTreePtr tree); @@ -2443,6 +2465,9 @@ public: DNER_DepField, // It is a field of a dependently promoted struct DNER_NoRegVars, // opts.compFlags & CLFLG_REGVAR is not set DNER_MinOptsGC, // It is a GC Ref and we are compiling MinOpts +#if !defined(LEGACY_BACKEND) && !defined(_TARGET_64BIT_) + DNER_LongParamField, // It is a decomposed field of a long parameter. +#endif #ifdef JIT32_GCENCODER DNER_PinningRef, #endif @@ -2761,12 +2786,11 @@ public: #if defined(_TARGET_64BIT_) assert(varDsc->lvSize() == 16); - return true; -#else // !defined(_TARGET_64BIT_) +#endif // defined(_TARGET_64BIT_) - // For 32-bit architectures, we make local variable SIMD12 types 16 bytes instead of just 12. lvSize() + // We make local variable SIMD12 types 16 bytes instead of just 12. lvSize() // already does this calculation. However, we also need to prevent mapping types if the var is a - // depenendently promoted struct field, which must remain its exact size within its parent struct. + // dependently promoted struct field, which must remain its exact size within its parent struct. // However, we don't know this until late, so we may have already pretended the field is bigger // before that. if ((varDsc->lvSize() == 16) && !lvaIsFieldOfDependentlyPromotedStruct(varDsc)) @@ -2777,8 +2801,6 @@ public: { return false; } - -#endif // !defined(_TARGET_64BIT_) } #endif // defined(FEATURE_SIMD) @@ -2970,7 +2992,10 @@ protected: int memberRef, bool readonlyCall, bool tailCall, - CorInfoIntrinsics* pIntrinsicID); + bool isJitIntrinsic, + CorInfoIntrinsics* pIntrinsicID, + bool* isSpecialIntrinsic = nullptr); + NamedIntrinsic lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method); GenTreePtr impArrayAccessIntrinsic(CORINFO_CLASS_HANDLE clsHnd, CORINFO_SIG_INFO* sig, int memberRef, @@ -3135,15 +3160,9 @@ private: ((opcode >= CEE_STLOC_0) && (opcode <= CEE_STLOC_3))); } - GenTreeArgList* impPopList(unsigned count, - unsigned* flagsPtr, - CORINFO_SIG_INFO* sig, - GenTreeArgList* prefixTree = nullptr); + GenTreeArgList* impPopList(unsigned count, CORINFO_SIG_INFO* sig, GenTreeArgList* prefixTree = nullptr); - GenTreeArgList* impPopRevList(unsigned count, - unsigned* flagsPtr, - CORINFO_SIG_INFO* sig, - unsigned skipReverseCount = 0); + GenTreeArgList* impPopRevList(unsigned count, CORINFO_SIG_INFO* sig, unsigned skipReverseCount = 0); /* * Get current IL offset with stack-empty info incoporated @@ -3617,9 +3636,8 @@ public: bool fgFuncletsCreated; // true if the funclet creation phase has been run #endif // FEATURE_EH_FUNCLETS - bool fgGlobalMorph; // indicates if we are during the global morphing phase - // since fgMorphTree can be called from several places - bool fgExpandInline; // indicates that we are creating tree for the inliner + bool fgGlobalMorph; // indicates if we are during the global morphing phase + // since fgMorphTree can be called from several places bool impBoxTempInUse; // the temp below is valid and available unsigned impBoxTemp; // a temporary that is used for boxing @@ -3655,6 +3673,16 @@ public: void fgUpdateFinallyTargetFlags(); + void fgClearAllFinallyTargetBits(); + + void fgAddFinallyTargetFlags(); + +#if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_) + // Sometimes we need to defer updating the BBF_FINALLY_TARGET bit. fgNeedToAddFinallyTargetBits signals + // when this is necessary. + bool fgNeedToAddFinallyTargetBits; +#endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_) + bool fgRetargetBranchesToCanonicalCallFinally(BasicBlock* block, BasicBlock* handler, BlockToBlockMap& continuationMap); @@ -3770,6 +3798,16 @@ public: void fgComputeLifeCall(VARSET_TP& life, GenTreeCall* call); + void fgComputeLifeTrackedLocalUse(VARSET_TP& life, LclVarDsc& varDsc, GenTreeLclVarCommon* node); + bool fgComputeLifeTrackedLocalDef(VARSET_TP& life, + VARSET_VALARG_TP keepAliveVars, + LclVarDsc& varDsc, + GenTreeLclVarCommon* node); + void fgComputeLifeUntrackedLocal(VARSET_TP& life, + VARSET_VALARG_TP keepAliveVars, + LclVarDsc& varDsc, + GenTreeLclVarCommon* lclVarNode, + GenTree* node); bool fgComputeLifeLocal(VARSET_TP& life, VARSET_VALARG_TP keepAliveVars, GenTree* lclVarNode, GenTree* node); void fgComputeLife(VARSET_TP& life, @@ -3786,8 +3824,6 @@ public: bool* doAgain, bool* pStmtInfoDirty DEBUGARG(bool* treeModf)); - bool fgTryRemoveDeadLIRStore(LIR::Range& blockRange, GenTree* node, GenTree** next); - // For updating liveset during traversal AFTER fgComputeLife has completed VARSET_VALRET_TP fgGetVarBits(GenTreePtr tree); VARSET_VALRET_TP fgUpdateLiveSet(VARSET_VALARG_TP liveSet, GenTreePtr tree); @@ -3902,6 +3938,9 @@ public: // Returns "true" iff lcl "lclNum" should be excluded from SSA. inline bool fgExcludeFromSsa(unsigned lclNum); + // Returns "true" if a struct temp of the given type requires needs zero init in this block + inline bool fgStructTempNeedsExplicitZeroInit(LclVarDsc* varDsc, BasicBlock* block); + // The value numbers for this compilation. ValueNumStore* vnStore; @@ -4105,11 +4144,11 @@ public: void vnPrint(ValueNum vn, unsigned level); #endif + bool fgDominate(BasicBlock* b1, BasicBlock* b2); // Return true if b1 dominates b2 + // Dominator computation member functions // Not exposed outside Compiler protected: - bool fgDominate(BasicBlock* b1, BasicBlock* b2); // Return true if b1 dominates b2 - bool fgReachable(BasicBlock* b1, BasicBlock* b2); // Returns true if block b1 can reach block b2 void fgComputeDoms(); // Computes the immediate dominators for each basic block in the @@ -4472,12 +4511,6 @@ public: static GenTreePtr fgGetFirstNode(GenTreePtr tree); static bool fgTreeIsInStmt(GenTree* tree, GenTreeStmt* stmt); - - inline bool fgIsInlining() - { - return fgExpandInline; - } - void fgTraverseRPO(); //--------------------- Walking the trees in the IR ----------------------- @@ -4662,6 +4695,8 @@ private: void fgSetRngChkTarget(GenTreePtr tree, bool delay = true); + BasicBlock* fgSetRngChkTargetInner(SpecialCodeKind kind, bool delay, unsigned* stkDepth); + #if REARRANGE_ADDS void fgMoveOpsLeft(GenTreePtr tree); #endif @@ -4738,7 +4773,11 @@ private: void fgFixupStructReturn(GenTreePtr call); GenTreePtr fgMorphLocalVar(GenTreePtr tree, bool forceRemorph); + +public: bool fgAddrCouldBeNull(GenTreePtr addr); + +private: GenTreePtr fgMorphField(GenTreePtr tree, MorphAddrContext* mac); bool fgCanFastTailCall(GenTreeCall* call); void fgMorphTailCall(GenTreeCall* call); @@ -4903,6 +4942,9 @@ private: void fgMarkAddressExposedLocals(); bool fgNodesMayInterfere(GenTree* store, GenTree* load); + static fgWalkPreFn fgUpdateSideEffectsPre; + static fgWalkPostFn fgUpdateSideEffectsPost; + // Returns true if the type of tree is of size at least "width", or if "tree" is not a // local variable. bool fgFitsInOrNotLoc(GenTreePtr tree, unsigned width); @@ -4946,8 +4988,7 @@ protected: LclVarDsc* optIsTrackedLocal(GenTreePtr tree); public: - void optRemoveRangeCheck( - GenTreePtr tree, GenTreePtr stmt, bool updateCSEcounts, unsigned sideEffFlags = 0, bool forceRemove = false); + void optRemoveRangeCheck(GenTreePtr tree, GenTreePtr stmt); bool optIsRangeCheckRemovable(GenTreePtr tree); protected: @@ -5313,6 +5354,14 @@ public: LoopDsc optLoopTable[MAX_LOOP_NUM]; // loop descriptor table unsigned char optLoopCount; // number of tracked loops + bool optRecordLoop(BasicBlock* head, + BasicBlock* first, + BasicBlock* top, + BasicBlock* entry, + BasicBlock* bottom, + BasicBlock* exit, + unsigned char exitCnt); + protected: unsigned optCallCount; // number of calls made in the method unsigned optIndirectCallCount; // number of virtual, interface and indirect calls made in the method @@ -5356,14 +5405,6 @@ protected: GenTreePtr* ppTest, GenTreePtr* ppIncr); - void optRecordLoop(BasicBlock* head, - BasicBlock* first, - BasicBlock* top, - BasicBlock* entry, - BasicBlock* bottom, - BasicBlock* exit, - unsigned char exitCnt); - void optFindNaturalLoops(); // Ensures that all the loops in the loop nest rooted at "loopInd" (an index into the loop table) are 'canonical' -- @@ -6666,8 +6707,16 @@ public: regMask = RBM_R11; } #elif defined(_TARGET_ARM_) - reg = REG_R4; - regMask = RBM_R4; + if (isCoreRTABI) + { + reg = REG_R12; + regMask = RBM_R12; + } + else + { + reg = REG_R4; + regMask = RBM_R4; + } #elif defined(_TARGET_ARM64_) reg = REG_R11; regMask = RBM_R11; @@ -8273,7 +8322,14 @@ public: var_types compRetNativeType; // Normalized return type as per target arch ABI unsigned compILargsCount; // Number of arguments (incl. implicit but not hidden) unsigned compArgsCount; // Number of arguments (incl. implicit and hidden) - unsigned compRetBuffArg; // position of hidden return param var (0, 1) (BAD_VAR_NUM means not present); + +#if FEATURE_FASTTAILCALL + unsigned compArgRegCount; // Number of incoming integer argument registers used for incoming arguments + unsigned compFloatArgRegCount; // Number of incoming floating argument registers used for incoming arguments + size_t compArgStackSize; // Incoming argument stack size in bytes +#endif // FEATURE_FASTTAILCALL + + unsigned compRetBuffArg; // position of hidden return param var (0, 1) (BAD_VAR_NUM means not present); int compTypeCtxtArg; // position of hidden param for type context for generic code (CORINFO_CALLCONV_PARAMTYPE) unsigned compThisArg; // position of implicit this pointer param (not to be confused with lvaArg0Var) unsigned compILlocalsCount; // Number of vars : args + locals (incl. implicit but not hidden) @@ -8404,6 +8460,7 @@ public: #ifdef DEBUG static unsigned s_compMethodsCount; // to produce unique label names unsigned compGenTreeID; + unsigned compBasicBlockID; #endif BasicBlock* compCurBB; // the current basic block in process @@ -9305,6 +9362,37 @@ public: return compRoot->m_arrayInfoMap; } + //----------------------------------------------------------------------------------------------------------------- + // Compiler::TryGetArrayInfo: + // Given an indirection node, checks to see whether or not that indirection represents an array access, and + // if so returns information about the array. + // + // Arguments: + // indir - The `GT_IND` node. + // arrayInfo (out) - Information about the accessed array if this function returns true. Undefined otherwise. + // + // Returns: + // True if the `GT_IND` node represents an array access; false otherwise. + inline bool TryGetArrayInfo(GenTreeIndir* indir, ArrayInfo* arrayInfo) + { + if ((indir->gtFlags & GTF_IND_ARR_INDEX) == 0) + { + return false; + } + + if (indir->gtOp1->OperIs(GT_INDEX_ADDR)) + { + GenTreeIndexAddr* const indexAddr = indir->gtOp1->AsIndexAddr(); + *arrayInfo = ArrayInfo(indexAddr->gtElemType, indexAddr->gtElemSize, indexAddr->gtElemOffset, + indexAddr->gtStructElemClass); + return true; + } + + bool found = GetArrayInfoMap()->Lookup(indir, arrayInfo); + assert(found); + return true; + } + NodeToUnsignedMap* m_memorySsaMap[MemoryKindCount]; // In some cases, we want to assign intermediate SSA #'s to memory states, and know what nodes create those memory @@ -9361,11 +9449,19 @@ public: static var_types GetTypeFromClassificationAndSizes(SystemVClassificationType classType, int size); static var_types GetEightByteType(const SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR& structDesc, unsigned slotNum); + static void GetStructTypeOffset(const SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR& structDesc, var_types* type0, var_types* type1, unsigned __int8* offset0, unsigned __int8* offset1); + + void GetStructTypeOffset(CORINFO_CLASS_HANDLE typeHnd, + var_types* type0, + var_types* type1, + unsigned __int8* offset0, + unsigned __int8* offset1); + void fgMorphSystemVStructArgs(GenTreeCall* call, bool hasStructArgument); #endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) |