Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code clean up in AP for NonNull* #112027

Merged
merged 9 commits into from
Feb 11, 2025
Merged
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
151 changes: 26 additions & 125 deletions src/coreclr/jit/assertionprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4962,140 +4962,63 @@ GenTree* Compiler::optAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* tr
// Arguments:
// op - tree to check
// assertions - set of live assertions
// pVnBased - [out] set to true if value numbers were used
// pIndex - [out] the assertion used in the proof
//
// Return Value:
// true if the tree's value will be non-null
//
// Notes:
// Sets "pVnBased" if the assertion is value number based. If no matching
// assertions are found from the table, then returns "NO_ASSERTION_INDEX."
//
// If both VN and assertion table yield a matching assertion, "pVnBased"
// is only set and the return value is "NO_ASSERTION_INDEX."
//
bool Compiler::optAssertionIsNonNull(GenTree* op,
ASSERT_VALARG_TP assertions DEBUGARG(bool* pVnBased)
DEBUGARG(AssertionIndex* pIndex))
bool Compiler::optAssertionIsNonNull(GenTree* op, ASSERT_VALARG_TP assertions)
{
if (op->OperIs(GT_ADD) && op->AsOp()->gtGetOp2()->IsCnsIntOrI() &&
!fgIsBigOffset(op->AsOp()->gtGetOp2()->AsIntCon()->IconValue()))
{
op = op->AsOp()->gtGetOp1();
}

bool vnBased = (!optLocalAssertionProp && vnStore->IsKnownNonNull(op->gtVNPair.GetConservative()));
#ifdef DEBUG
*pIndex = NO_ASSERTION_INDEX;
*pVnBased = vnBased;
#endif

if (vnBased)
// Fast path when we have a VN
if (!optLocalAssertionProp && vnStore->IsKnownNonNull(op->gtVNPair.GetConservative()))
{
return true;
}

op = op->gtEffectiveVal();

if (!op->OperIs(GT_LCL_VAR))
if (!optCanPropNonNull || BitVecOps::MayBeUninit(assertions))
{
return false;
}

AssertionIndex index = optAssertionIsNonNullInternal(op, assertions DEBUGARG(pVnBased));
#ifdef DEBUG
*pIndex = index;
#endif
return index != NO_ASSERTION_INDEX;
}

//------------------------------------------------------------------------
// optAssertionIsNonNullInternal: see if we can prove a tree's value will
// be non-null based on assertions
//
// Arguments:
// op - tree to check
// assertions - set of live assertions
// pVnBased - [out] set to true if value numbers were used
//
// Return Value:
// index of assertion, or NO_ASSERTION_INDEX
//
AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op,
ASSERT_VALARG_TP assertions DEBUGARG(bool* pVnBased))
{

#ifdef DEBUG
// Initialize the out param
//
*pVnBased = false;
#endif

if (!optCanPropNonNull)
op = op->gtEffectiveVal();
if (!op->OperIs(GT_LCL_VAR))
{
return NO_ASSERTION_INDEX;
return false;
}

// If local assertion prop use lcl comparison, else use VN comparison.
if (!optLocalAssertionProp)
{
if (BitVecOps::MayBeUninit(assertions) || BitVecOps::IsEmpty(apTraits, assertions))
{
return NO_ASSERTION_INDEX;
}

// Look at both the top-level vn, and
// the vn we get by stripping off any constant adds.
//
ValueNum vn = vnStore->VNConservativeNormalValue(op->gtVNPair);
ValueNum vnBase = vn;
VNFuncApp funcAttr;

while (vnStore->GetVNFunc(vnBase, &funcAttr) && (funcAttr.m_func == (VNFunc)GT_ADD))
ValueNum vn = vnStore->VNConservativeNormalValue(op->gtVNPair);
if (vn == ValueNumStore::NoVN)
{
if (vnStore->IsVNConstant(funcAttr.m_args[1]) && varTypeIsIntegral(vnStore->TypeOfVN(funcAttr.m_args[1])))
{
vnBase = funcAttr.m_args[0];
}
else if (vnStore->IsVNConstant(funcAttr.m_args[0]) &&
varTypeIsIntegral(vnStore->TypeOfVN(funcAttr.m_args[0])))
{
vnBase = funcAttr.m_args[1];
}
else
{
break;
}
return false;
}

ValueNum vnBase = vn;
target_ssize_t offset = 0;
vnStore->PeelOffsets(&vnBase, &offset);

// Check each assertion to find if we have a vn != null assertion.
//
BitVecOps::Iter iter(apTraits, assertions);
unsigned index = 0;
while (iter.NextElem(&index))
{
AssertionIndex assertionIndex = GetAssertionIndex(index);
if (assertionIndex > optAssertionCount)
{
break;
}
AssertionDsc* curAssertion = optGetAssertion(assertionIndex);
if (!curAssertion->CanPropNonNull())
{
continue;
}

if ((curAssertion->op1.vn != vn) && (curAssertion->op1.vn != vnBase))
AssertionDsc* curAssertion = optGetAssertion(assertionIndex);
if (curAssertion->CanPropNonNull() && ((curAssertion->op1.vn == vn) || (curAssertion->op1.vn == vnBase)))
{
continue;
return true;
}

#ifdef DEBUG
*pVnBased = true;
#endif

return assertionIndex;
}
}
else
Expand All @@ -5119,11 +5042,11 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree*
(curAssertion->op2.kind == O2K_CONST_INT) && // op2
(curAssertion->op1.lcl.lclNum == lclNum) && (curAssertion->op2.u1.iconVal == 0))
{
return assertionIndex;
return true;
}
}
}
return NO_ASSERTION_INDEX;
return false;
}

//------------------------------------------------------------------------
Expand Down Expand Up @@ -5177,20 +5100,10 @@ GenTree* Compiler::optNonNullAssertionProp_Call(ASSERT_VALARG_TP assertions, Gen
GenTree* op1 = call->gtArgs.GetThisArg()->GetNode();
noway_assert(op1 != nullptr);

#ifdef DEBUG
bool vnBased = false;
AssertionIndex index = NO_ASSERTION_INDEX;
#endif
if (optAssertionIsNonNull(op1, assertions DEBUGARG(&vnBased) DEBUGARG(&index)))
if (optAssertionIsNonNull(op1, assertions))
{
#ifdef DEBUG
if (verbose)
{
(vnBased) ? printf("\nVN based non-null prop in " FMT_BB ":\n", compCurBB->bbNum)
: printf("\nNon-null prop for index #%02u in " FMT_BB ":\n", index, compCurBB->bbNum);
gtDispTree(call, nullptr, nullptr, true);
}
#endif
JITDUMP("Non-null assertion prop for tree [%06d] in " FMT_BB ":\n", dspTreeID(op1), compCurBB->bbNum);

call->gtFlags &= ~GTF_CALL_NULLCHECK;
call->gtFlags &= ~GTF_EXCEPT;
noway_assert(call->gtFlags & GTF_SIDE_EFFECT);
Expand Down Expand Up @@ -5219,20 +5132,10 @@ bool Compiler::optNonNullAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree*
return false;
}

#ifdef DEBUG
bool vnBased = false;
AssertionIndex index = NO_ASSERTION_INDEX;
#endif
if (optAssertionIsNonNull(indir->AsIndir()->Addr(), assertions DEBUGARG(&vnBased) DEBUGARG(&index)))
if (optAssertionIsNonNull(indir->AsIndir()->Addr(), assertions))
{
#ifdef DEBUG
if (verbose)
{
(vnBased) ? printf("\nVN based non-null prop in " FMT_BB ":\n", compCurBB->bbNum)
: printf("\nNon-null prop for index #%02u in " FMT_BB ":\n", index, compCurBB->bbNum);
gtDispTree(indir, nullptr, nullptr, true);
}
#endif
JITDUMP("Non-null assertion prop for indirection [%06d] in " FMT_BB ":\n", dspTreeID(indir), compCurBB->bbNum);

indir->gtFlags &= ~GTF_EXCEPT;
indir->gtFlags |= GTF_IND_NONFAULTING;

Expand Down Expand Up @@ -5429,11 +5332,9 @@ GenTree* Compiler::optAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCal
}

// Leave a hint for fgLateCastExpansion that obj is never null.
INDEBUG(AssertionIndex nonNullIdx = NO_ASSERTION_INDEX);
INDEBUG(bool vnBased = false);
// GTF_CALL_M_CAST_CAN_BE_EXPANDED check is to improve TP
if (((call->gtCallMoreFlags & GTF_CALL_M_CAST_CAN_BE_EXPANDED) != 0) &&
optAssertionIsNonNull(objArg, assertions DEBUGARG(&vnBased) DEBUGARG(&nonNullIdx)))
optAssertionIsNonNull(objArg, assertions))
{
call->gtCallMoreFlags |= GTF_CALL_M_CAST_OBJ_NONNULL;
return optAssertionProp_Update(call, call, stmt);
Expand Down
4 changes: 1 addition & 3 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -8247,10 +8247,8 @@ class Compiler
// Used for respective assertion propagations.
AssertionIndex optAssertionIsSubrange(GenTree* tree, IntegralRange range, ASSERT_VALARG_TP assertions);
AssertionIndex optAssertionIsSubtype(GenTree* tree, GenTree* methodTableArg, ASSERT_VALARG_TP assertions);
AssertionIndex optAssertionIsNonNullInternal(GenTree* op, ASSERT_VALARG_TP assertions DEBUGARG(bool* pVnBased));
bool optAssertionVNIsNonNull(ValueNum vn, ASSERT_VALARG_TP assertions);
bool optAssertionIsNonNull(GenTree* op,
ASSERT_VALARG_TP assertions DEBUGARG(bool* pVnBased) DEBUGARG(AssertionIndex* pIndex));
bool optAssertionIsNonNull(GenTree* op, ASSERT_VALARG_TP assertions);

AssertionIndex optGlobalAssertionIsEqualOrNotEqual(ASSERT_VALARG_TP assertions, GenTree* op1, GenTree* op2);
AssertionIndex optGlobalAssertionIsEqualOrNotEqualZero(ASSERT_VALARG_TP assertions, GenTree* op1);
Expand Down
Loading
Loading