diff options
Diffstat (limited to 'src/jit/morph.cpp')
-rw-r--r-- | src/jit/morph.cpp | 115 |
1 files changed, 92 insertions, 23 deletions
diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp index 6928c3c393..9404469c7f 100644 --- a/src/jit/morph.cpp +++ b/src/jit/morph.cpp @@ -7529,6 +7529,39 @@ void Compiler::fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCa fgInsertStmtBefore(block, paramAssignmentInsertionPoint, arg0AssignmentStmt); } + // If compInitMem is set, we may need to zero-initialize some locals. Normally it's done in the prolog + // but this loop can't include the prolog. Since we don't have liveness information, we insert zero-initialization + // for all non-parameter non-temp locals. Liveness phase will remove unnecessary initializations. + if (info.compInitMem) + { + unsigned varNum; + LclVarDsc* varDsc; + for (varNum = 0, varDsc = lvaTable; varNum < info.compLocalsCount; varNum++, varDsc++) + { + if (!varDsc->lvIsParam) + { + assert(!varDsc->lvIsTemp); + var_types lclType = varDsc->TypeGet(); + GenTreePtr lcl = gtNewLclvNode(varNum, lclType); + GenTreePtr init = nullptr; + if (lclType == TYP_STRUCT) + { + const bool isVolatile = false; + const bool isCopyBlock = false; + init = gtNewBlkOpNode(lcl, gtNewIconNode(0), varDsc->lvSize(), isVolatile, isCopyBlock); + init = fgMorphInitBlock(init); + } + else + { + GenTreePtr zero = gtNewZeroConNode(genActualType(lclType)); + init = gtNewAssignNode(lcl, zero); + } + GenTreePtr initStmt = gtNewStmt(init, callILOffset); + fgInsertStmtBefore(block, last, initStmt); + } + } + } + // Remove the call fgRemoveStmt(block, last); @@ -10514,6 +10547,43 @@ GenTree* Compiler::fgMorphForRegisterFP(GenTree* tree) return tree; } +//-------------------------------------------------------------------------------------------------------------- +// fgMorphRecognizeBoxNullable: +// Recognize this pattern: +// +// stmtExpr void (IL 0x000... ???) +// return int +// CNS_INT ref null +// EQ/NE/GT int +// CALL help ref HELPER.CORINFO_HELP_BOX_NULLABLE +// CNS_INT(h) long 0x7fed96836c8 class +// ADDR byref +// FIELD struct value +// LCL_VAR ref V00 this +// +// which comes from this code: +// +// return this.value==null; +// +// and transform it into +// +// stmtExpr void (IL 0x000... ???) +// return int +// CNS_INT ref null +// EQ/NE/GT int +// IND bool +// ADDR byref +// FIELD struct value +// LCL_VAR ref V00 this +// +// Arguments: +// compare - Compare tree to optimize. +// +// return value: +// A tree that has a call to CORINFO_HELP_BOX_NULLABLE optimized away if the pattern is found; +// the original tree otherwise. +// + GenTree* Compiler::fgMorphRecognizeBoxNullable(GenTree* compare) { GenTree* op1 = compare->gtOp.gtOp1; @@ -10521,26 +10591,6 @@ GenTree* Compiler::fgMorphRecognizeBoxNullable(GenTree* compare) GenTree* opCns; GenTreeCall* opCall; - // recognize this pattern: - // - // stmtExpr void (IL 0x000... ???) - // return int - // const ref null - // == int - // call help ref HELPER.CORINFO_HELP_BOX_NULLABLE - // const(h) long 0x7fed96836c8 class - // addr byref - // ld.lclVar struct V00 arg0 - // - // - // which comes from this code (reported by customer as being slow) : - // - // private static bool IsNull<T>(T arg) - // { - // return arg==null; - // } - // - if (op1->IsCnsIntOrI() && op2->IsHelperCall()) { opCns = op1; @@ -10566,8 +10616,17 @@ GenTree* Compiler::fgMorphRecognizeBoxNullable(GenTree* compare) return compare; } - // replace the box with an access of the nullable 'hasValue' field which is at the zero offset - GenTree* newOp = gtNewOperNode(GT_IND, TYP_BOOL, opCall->gtCall.gtCallArgs->gtOp.gtOp2->gtOp.gtOp1); + // Get the nullable struct argument + GenTree* arg = opCall->gtCall.gtCallArgs->gtOp.gtOp2->gtOp.gtOp1; + + // Check for cases that are unsafe to optimize and return the unchanged tree + if (arg->IsArgPlaceHolderNode() || arg->IsNothingNode() || ((arg->gtFlags & GTF_LATE_ARG) != 0)) + { + return compare; + } + + // Replace the box with an access of the nullable 'hasValue' field which is at the zero offset + GenTree* newOp = gtNewOperNode(GT_IND, TYP_BOOL, arg); if (opCall == op1) { @@ -11426,7 +11485,17 @@ GenTreePtr Compiler::fgMorphSmpOp(GenTreePtr tree, MorphAddrContext* mac) } } } - fgMorphRecognizeBoxNullable(tree); + + __fallthrough; + + case GT_GT: + + // Try to optimize away calls to CORINFO_HELP_BOX_NULLABLE for GT_EQ, GT_NE, and unsigned GT_GT. + if ((oper != GT_GT) || tree->IsUnsigned()) + { + fgMorphRecognizeBoxNullable(tree); + } + op1 = tree->gtOp.gtOp1; op2 = tree->gtGetOp2IfPresent(); |