Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 20 additions & 11 deletions src/coreclr/jit/assertionprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1149,16 +1149,14 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1,
}
}

if (fgIsBigOffset(offset) || op1->gtOper != GT_LCL_VAR)
if (fgIsBigOffset(offset) || !op1->IsLocal())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change ok? LCL_FLD will create an assertion about the parent local without encoding any information about the offset, which seems odd.

{
goto DONE_ASSERTION; // Don't make an assertion
}

unsigned lclNum = op1->AsLclVarCommon()->GetLclNum();
LclVarDsc* lclVar = lvaGetDesc(lclNum);

ValueNum vn;

// We only perform null-checks on byrefs and GC refs
if (!varTypeIsGC(lclVar->TypeGet()))
{
Expand All @@ -1174,9 +1172,7 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1,
assertion.op1.kind = O1K_LCLVAR;
assertion.op1.lcl.lclNum = lclNum;
assertion.op1.lcl.ssaNum = op1->AsLclVarCommon()->GetSsaNum();
vn = optConservativeNormalVN(op1);

assertion.op1.vn = vn;
assertion.op1.vn = optConservativeNormalVN(op1->OperIsLocalStore() ? op1->gtGetOp1() : op1);
assertion.assertionKind = assertionKind;
assertion.op2.kind = O2K_CONST_INT;
assertion.op2.vn = ValueNumStore::VNForNull();
Expand Down Expand Up @@ -2329,10 +2325,10 @@ AssertionIndex Compiler::optAssertionGenPhiDefn(GenTree* tree)
}
}

// All phi arguments are non-null implies phi rhs is non-null.
// All phi arguments are non-null implies the phi itself is non-null.
if (isNonNull)
{
return optCreateAssertion(tree->AsOp()->gtOp1, nullptr, OAK_NOT_EQUAL);
return optCreateAssertion(tree, nullptr, OAK_NOT_EQUAL);
}
return NO_ASSERTION_INDEX;
}
Expand Down Expand Up @@ -6686,7 +6682,7 @@ PhaseStatus Compiler::optAssertionPropMain()
fgRemoveRestOfBlock = false;

// Walk the statement trees in this basic block
Statement* stmt = block->FirstNonPhiDef();
Statement* stmt = block->firstStmt();
while (stmt != nullptr)
{
// Propagation tells us to remove the rest of the block. Remove it.
Expand All @@ -6704,8 +6700,8 @@ PhaseStatus Compiler::optAssertionPropMain()

optAssertionPropagatedCurrentStmt = false; // set to true if a assertion propagation took place
// and thus we must morph, set order, re-link
for (GenTree* tree = stmt->GetTreeList(); tree != nullptr; tree = tree->gtNext)
{

auto runAssertPropForTree = [&](GenTree* tree) {
optDumpAssertionIndices("Propagating ", assertions, " ");
JITDUMP("for " FMT_BB ", stmt " FMT_STMT ", tree [%06d]", block->bbNum, stmt->GetID(), dspTreeID(tree));
JITDUMP(", tree -> ");
Expand All @@ -6726,6 +6722,19 @@ PhaseStatus Compiler::optAssertionPropMain()
optImpliedAssertions(info.GetAssertionIndex(), assertions);
BitVecOps::AddElemD(apTraits, assertions, info.GetAssertionIndex() - 1);
}
};

if (stmt->IsPhiDefnStmt())
{
// For PHI statements, we're only interested in the root node (to save TP).
runAssertPropForTree(stmt->GetRootNode());
}
else
{
for (GenTree* tree = stmt->GetTreeList(); tree != nullptr; tree = tree->gtNext)
{
runAssertPropForTree(tree);
}
}

if (optAssertionPropagatedCurrentStmt)
Expand Down
34 changes: 27 additions & 7 deletions src/coreclr/jit/valuenum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1635,7 +1635,33 @@ bool ValueNumStore::IsKnownNonNull(ValueNum vn)
}

VNFuncApp funcAttr;
return GetVNFunc(vn, &funcAttr) && (s_vnfOpAttribs[funcAttr.m_func] & VNFOA_KnownNonNull) != 0;
if (!GetVNFunc(vn, &funcAttr))
{
return false;
}

if ((s_vnfOpAttribs[funcAttr.m_func] & VNFOA_KnownNonNull) != 0)
{
return true;
}

// TODO-VN: we can add more cases, e.g. "VNF_ADD(KnownNotNull, smallCns)"

if (funcAttr.m_func == VNF_Cast)
{
var_types castFromType = TypeOfVN(vn);
var_types castToType;
bool srcIsUnsigned;
GetCastOperFromVN(funcAttr.m_args[1], &castToType, &srcIsUnsigned);

// Any integral cast from a known non-null value is always non-null.
if (varTypeIsIntegralOrI(castFromType) && varTypeIsIntegralOrI(castToType))
{
return IsKnownNonNull(funcAttr.m_args[0]);
}
}

return false;
}

bool ValueNumStore::IsSharedStatic(ValueNum vn)
Expand Down Expand Up @@ -11136,12 +11162,6 @@ void Compiler::fgValueNumberStore(GenTree* store)

valueVNPair.SetBoth(initObjVN);
}
else if (value->TypeGet() == TYP_REF)
{
// If we have an unsafe IL store of a TYP_REF to a non-ref (typically a TYP_BYREF)
// then don't propagate this ValueNumber to the lhs, instead create a new unique VN.
valueVNPair.SetBoth(vnStore->VNForExpr(compCurBB, store->TypeGet()));
}
Comment on lines -11139 to -11144
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be a good idea to see if you can dig up why this was added to verify it won't cause any problems to remove it.

else
{
// This means that there is an implicit cast on the value.
Expand Down