Skip to content

Commit f1b8d5a

Browse files
Fold null checks against known non-null values (dotnet#109164)
1 parent 54e55db commit f1b8d5a

File tree

2 files changed

+41
-35
lines changed

2 files changed

+41
-35
lines changed

src/coreclr/jit/flowgraph.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,9 @@ bool Compiler::fgAddrCouldBeNull(GenTree* addr)
863863
case GT_ARR_ADDR:
864864
return (addr->gtFlags & GTF_ARR_ADDR_NONNULL) == 0;
865865

866+
case GT_BOX:
867+
return !addr->IsBoxedValue();
868+
866869
case GT_LCL_VAR:
867870
return !lvaIsImplicitByRefLocal(addr->AsLclVar()->GetLclNum());
868871

src/coreclr/jit/gentree.cpp

+38-35
Original file line numberDiff line numberDiff line change
@@ -14518,9 +14518,10 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
1451814518
// Optimize boxed value classes; these are always false. This IL is
1451914519
// generated when a generic value is tested against null:
1452014520
// <T> ... foo(T x) { ... if ((object)x == null) ...
14521-
if ((val == 0) && op->IsBoxedValue())
14521+
// Also fold checks against known non-null data like static readonlys
14522+
if ((val == 0) && !fgAddrCouldBeNull(op))
1452214523
{
14523-
JITDUMP("\nAttempting to optimize BOX(valueType) %s null [%06u]\n", GenTree::OpName(oper),
14524+
JITDUMP("\nAttempting to optimize BOX(valueType)/non-null %s null [%06u]\n", GenTree::OpName(oper),
1452414525
dspTreeID(tree));
1452514526

1452614527
// We don't expect GT_GT with signed compares, and we
@@ -14532,44 +14533,46 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
1453214533
}
1453314534
else
1453414535
{
14535-
// The tree under the box must be side effect free
14536-
// since we will drop it if we optimize.
14537-
assert(!gtTreeHasSideEffects(op->AsBox()->BoxOp(), GTF_SIDE_EFFECT));
14536+
bool wrapEffects = true;
14537+
if (op->IsBoxedValue())
14538+
{
14539+
// The tree under the box must be side effect free
14540+
// since we will drop it if we optimize.
14541+
assert(!gtTreeHasSideEffects(op->AsBox()->BoxOp(), GTF_SIDE_EFFECT));
1453814542

14539-
// See if we can optimize away the box and related statements.
14540-
GenTree* boxSourceTree = gtTryRemoveBoxUpstreamEffects(op);
14541-
bool didOptimize = (boxSourceTree != nullptr);
14543+
// See if we can optimize away the box and related statements.
14544+
wrapEffects = (gtTryRemoveBoxUpstreamEffects(op) == nullptr);
14545+
}
1454214546

14543-
// If optimization succeeded, remove the box.
14544-
if (didOptimize)
14547+
// Set up the result of the compare.
14548+
int compareResult;
14549+
if (oper == GT_GT)
1454514550
{
14546-
// Set up the result of the compare.
14547-
int compareResult = 0;
14548-
if (oper == GT_GT)
14549-
{
14550-
// GT_GT(null, box) == false
14551-
// GT_GT(box, null) == true
14552-
compareResult = (op1 == op);
14553-
}
14554-
else if (oper == GT_EQ)
14555-
{
14556-
// GT_EQ(box, null) == false
14557-
// GT_EQ(null, box) == false
14558-
compareResult = 0;
14559-
}
14560-
else
14561-
{
14562-
assert(oper == GT_NE);
14563-
// GT_NE(box, null) == true
14564-
// GT_NE(null, box) == true
14565-
compareResult = 1;
14566-
}
14567-
14568-
JITDUMP("\nSuccess: replacing BOX(valueType) %s null with %d\n", GenTree::OpName(oper),
14569-
compareResult);
14551+
// GT_GT(null, op) == false
14552+
// GT_GT(op, null) == true
14553+
compareResult = (op1 == op);
14554+
}
14555+
else if (oper == GT_EQ)
14556+
{
14557+
// GT_EQ(op, null) == false
14558+
// GT_EQ(null, op) == false
14559+
compareResult = 0;
14560+
}
14561+
else
14562+
{
14563+
assert(oper == GT_NE);
14564+
// GT_NE(op, null) == true
14565+
// GT_NE(null, op) == true
14566+
compareResult = 1;
14567+
}
1457014568

14571-
return NewMorphedIntConNode(compareResult);
14569+
GenTree* newTree = gtNewIconNode(compareResult);
14570+
if (wrapEffects)
14571+
{
14572+
newTree = gtWrapWithSideEffects(newTree, op, GTF_ALL_EFFECT);
1457214573
}
14574+
op = newTree;
14575+
goto DONE_FOLD;
1457314576
}
1457414577
}
1457514578
else

0 commit comments

Comments
 (0)