Skip to content

Commit

Permalink
RyuJIT: Don't emit null checks for constant strings (#37245)
Browse files Browse the repository at this point in the history
* Fold "ldstr ==/!== null" (mikedn's PR)

* Formatting

* check IsUnsigned for GT_GT

* Address feedback
  • Loading branch information
EgorBo authored Oct 21, 2020
1 parent 7eba836 commit c9d3d3e
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 7 deletions.
15 changes: 11 additions & 4 deletions src/coreclr/src/jit/flowgraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7321,6 +7321,10 @@ bool Compiler::fgAddrCouldBeNull(GenTree* addr)
{
return false;
}
else if (addr->OperIs(GT_CNS_STR))
{
return false;
}
else if (addr->gtOper == GT_LCL_VAR)
{
unsigned varNum = addr->AsLclVarCommon()->GetLclNum();
Expand Down Expand Up @@ -23763,10 +23767,13 @@ Statement* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo)
if (call->gtFlags & GTF_CALL_NULLCHECK && !inlineInfo->thisDereferencedFirst)
{
// Call impInlineFetchArg to "reserve" a temp for the "this" pointer.
nullcheck = gtNewNullCheck(impInlineFetchArg(0, inlArgInfo, lclVarInfo), block);

// The NULL-check statement will be inserted to the statement list after those statements
// that assign arguments to temps and before the actual body of the inlinee method.
GenTree* thisOp = impInlineFetchArg(0, inlArgInfo, lclVarInfo);
if (fgAddrCouldBeNull(thisOp))
{
nullcheck = gtNewNullCheck(impInlineFetchArg(0, inlArgInfo, lclVarInfo), block);
// The NULL-check statement will be inserted to the statement list after those statements
// that assign arguments to temps and before the actual body of the inlinee method.
}
}

/* Treat arguments that had to be assigned to temps */
Expand Down
16 changes: 15 additions & 1 deletion src/coreclr/src/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14531,8 +14531,22 @@ GenTree* Compiler::gtFoldExprConst(GenTree* tree)

/* String nodes are an RVA at this point */

if (op1->gtOper == GT_CNS_STR || op2->gtOper == GT_CNS_STR)
if (op1->OperIs(GT_CNS_STR) || op2->OperIs(GT_CNS_STR))
{
// Fold "ldstr" ==/!= null
if (op2->IsIntegralConst(0))
{
if (tree->OperIs(GT_EQ))
{
i1 = 0;
goto FOLD_COND;
}
if (tree->OperIs(GT_NE) || (tree->OperIs(GT_GT) && tree->IsUnsigned()))
{
i1 = 1;
goto FOLD_COND;
}
}
return tree;
}

Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/src/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6110,8 +6110,8 @@ GenTree* Compiler::fgMorphField(GenTree* tree, MorphAddrContext* mac)

bool addExplicitNullCheck = false;

// Implicit byref locals are never null.
if (!((objRef->gtOper == GT_LCL_VAR) && lvaIsImplicitByRefLocal(objRef->AsLclVarCommon()->GetLclNum())))
// Implicit byref locals and string literals are never null.
if (fgAddrCouldBeNull(objRef))
{
// If the objRef is a GT_ADDR node, it, itself, never requires null checking. The expression
// whose address is being taken is either a local or static variable, whose address is necessarily
Expand Down

0 comments on commit c9d3d3e

Please sign in to comment.