Skip to content

Commit

Permalink
Code clean up in AP for NonNull* (#112027)
Browse files Browse the repository at this point in the history
  • Loading branch information
EgorBo authored Feb 11, 2025
1 parent 109c946 commit ed8df42
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 229 deletions.
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

0 comments on commit ed8df42

Please sign in to comment.