@@ -4962,140 +4962,63 @@ GenTree* Compiler::optAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* tr
49624962// Arguments:
49634963// op - tree to check
49644964// assertions - set of live assertions
4965- // pVnBased - [out] set to true if value numbers were used
4966- // pIndex - [out] the assertion used in the proof
49674965//
49684966// Return Value:
49694967// true if the tree's value will be non-null
49704968//
4971- // Notes:
4972- // Sets "pVnBased" if the assertion is value number based. If no matching
4973- // assertions are found from the table, then returns "NO_ASSERTION_INDEX."
4974- //
4975- // If both VN and assertion table yield a matching assertion, "pVnBased"
4976- // is only set and the return value is "NO_ASSERTION_INDEX."
4977- //
4978- bool Compiler::optAssertionIsNonNull (GenTree* op,
4979- ASSERT_VALARG_TP assertions DEBUGARG (bool * pVnBased)
4980- DEBUGARG(AssertionIndex* pIndex))
4969+ bool Compiler::optAssertionIsNonNull (GenTree* op, ASSERT_VALARG_TP assertions)
49814970{
49824971 if (op->OperIs (GT_ADD) && op->AsOp ()->gtGetOp2 ()->IsCnsIntOrI () &&
49834972 !fgIsBigOffset (op->AsOp ()->gtGetOp2 ()->AsIntCon ()->IconValue ()))
49844973 {
49854974 op = op->AsOp ()->gtGetOp1 ();
49864975 }
49874976
4988- bool vnBased = (!optLocalAssertionProp && vnStore->IsKnownNonNull (op->gtVNPair .GetConservative ()));
4989- #ifdef DEBUG
4990- *pIndex = NO_ASSERTION_INDEX;
4991- *pVnBased = vnBased;
4992- #endif
4993-
4994- if (vnBased)
4977+ // Fast path when we have a VN
4978+ if (!optLocalAssertionProp && vnStore->IsKnownNonNull (op->gtVNPair .GetConservative ()))
49954979 {
49964980 return true ;
49974981 }
49984982
4999- op = op->gtEffectiveVal ();
5000-
5001- if (!op->OperIs (GT_LCL_VAR))
4983+ if (!optCanPropNonNull || BitVecOps::MayBeUninit (assertions))
50024984 {
50034985 return false ;
50044986 }
50054987
5006- AssertionIndex index = optAssertionIsNonNullInternal (op, assertions DEBUGARG (pVnBased));
5007- #ifdef DEBUG
5008- *pIndex = index;
5009- #endif
5010- return index != NO_ASSERTION_INDEX;
5011- }
5012-
5013- // ------------------------------------------------------------------------
5014- // optAssertionIsNonNullInternal: see if we can prove a tree's value will
5015- // be non-null based on assertions
5016- //
5017- // Arguments:
5018- // op - tree to check
5019- // assertions - set of live assertions
5020- // pVnBased - [out] set to true if value numbers were used
5021- //
5022- // Return Value:
5023- // index of assertion, or NO_ASSERTION_INDEX
5024- //
5025- AssertionIndex Compiler::optAssertionIsNonNullInternal (GenTree* op,
5026- ASSERT_VALARG_TP assertions DEBUGARG (bool * pVnBased))
5027- {
5028-
5029- #ifdef DEBUG
5030- // Initialize the out param
5031- //
5032- *pVnBased = false ;
5033- #endif
5034-
5035- if (!optCanPropNonNull)
4988+ op = op->gtEffectiveVal ();
4989+ if (!op->OperIs (GT_LCL_VAR))
50364990 {
5037- return NO_ASSERTION_INDEX ;
4991+ return false ;
50384992 }
50394993
50404994 // If local assertion prop use lcl comparison, else use VN comparison.
50414995 if (!optLocalAssertionProp)
50424996 {
5043- if (BitVecOps::MayBeUninit (assertions) || BitVecOps::IsEmpty (apTraits, assertions))
5044- {
5045- return NO_ASSERTION_INDEX;
5046- }
5047-
50484997 // Look at both the top-level vn, and
50494998 // the vn we get by stripping off any constant adds.
50504999 //
5051- ValueNum vn = vnStore->VNConservativeNormalValue (op->gtVNPair );
5052- ValueNum vnBase = vn;
5053- VNFuncApp funcAttr;
5054-
5055- while (vnStore->GetVNFunc (vnBase, &funcAttr) && (funcAttr.m_func == (VNFunc)GT_ADD))
5000+ ValueNum vn = vnStore->VNConservativeNormalValue (op->gtVNPair );
5001+ if (vn == ValueNumStore::NoVN)
50565002 {
5057- if (vnStore->IsVNConstant (funcAttr.m_args [1 ]) && varTypeIsIntegral (vnStore->TypeOfVN (funcAttr.m_args [1 ])))
5058- {
5059- vnBase = funcAttr.m_args [0 ];
5060- }
5061- else if (vnStore->IsVNConstant (funcAttr.m_args [0 ]) &&
5062- varTypeIsIntegral (vnStore->TypeOfVN (funcAttr.m_args [0 ])))
5063- {
5064- vnBase = funcAttr.m_args [1 ];
5065- }
5066- else
5067- {
5068- break ;
5069- }
5003+ return false ;
50705004 }
50715005
5006+ ValueNum vnBase = vn;
5007+ target_ssize_t offset = 0 ;
5008+ vnStore->PeelOffsets (&vnBase, &offset);
5009+
50725010 // Check each assertion to find if we have a vn != null assertion.
50735011 //
50745012 BitVecOps::Iter iter (apTraits, assertions);
50755013 unsigned index = 0 ;
50765014 while (iter.NextElem (&index))
50775015 {
50785016 AssertionIndex assertionIndex = GetAssertionIndex (index);
5079- if (assertionIndex > optAssertionCount)
5080- {
5081- break ;
5082- }
5083- AssertionDsc* curAssertion = optGetAssertion (assertionIndex);
5084- if (!curAssertion->CanPropNonNull ())
5085- {
5086- continue ;
5087- }
5088-
5089- if ((curAssertion->op1 .vn != vn) && (curAssertion->op1 .vn != vnBase))
5017+ AssertionDsc* curAssertion = optGetAssertion (assertionIndex);
5018+ if (curAssertion->CanPropNonNull () && ((curAssertion->op1 .vn == vn) || (curAssertion->op1 .vn == vnBase)))
50905019 {
5091- continue ;
5020+ return true ;
50925021 }
5093-
5094- #ifdef DEBUG
5095- *pVnBased = true ;
5096- #endif
5097-
5098- return assertionIndex;
50995022 }
51005023 }
51015024 else
@@ -5119,11 +5042,11 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree*
51195042 (curAssertion->op2 .kind == O2K_CONST_INT) && // op2
51205043 (curAssertion->op1 .lcl .lclNum == lclNum) && (curAssertion->op2 .u1 .iconVal == 0 ))
51215044 {
5122- return assertionIndex ;
5045+ return true ;
51235046 }
51245047 }
51255048 }
5126- return NO_ASSERTION_INDEX ;
5049+ return false ;
51275050}
51285051
51295052// ------------------------------------------------------------------------
@@ -5177,20 +5100,10 @@ GenTree* Compiler::optNonNullAssertionProp_Call(ASSERT_VALARG_TP assertions, Gen
51775100 GenTree* op1 = call->gtArgs .GetThisArg ()->GetNode ();
51785101 noway_assert (op1 != nullptr );
51795102
5180- #ifdef DEBUG
5181- bool vnBased = false ;
5182- AssertionIndex index = NO_ASSERTION_INDEX;
5183- #endif
5184- if (optAssertionIsNonNull (op1, assertions DEBUGARG (&vnBased) DEBUGARG (&index)))
5103+ if (optAssertionIsNonNull (op1, assertions))
51855104 {
5186- #ifdef DEBUG
5187- if (verbose)
5188- {
5189- (vnBased) ? printf (" \n VN based non-null prop in " FMT_BB " :\n " , compCurBB->bbNum )
5190- : printf (" \n Non-null prop for index #%02u in " FMT_BB " :\n " , index, compCurBB->bbNum );
5191- gtDispTree (call, nullptr , nullptr , true );
5192- }
5193- #endif
5105+ JITDUMP (" Non-null assertion prop for tree [%06d] in " FMT_BB " :\n " , dspTreeID (op1), compCurBB->bbNum );
5106+
51945107 call->gtFlags &= ~GTF_CALL_NULLCHECK;
51955108 call->gtFlags &= ~GTF_EXCEPT;
51965109 noway_assert (call->gtFlags & GTF_SIDE_EFFECT);
@@ -5219,20 +5132,10 @@ bool Compiler::optNonNullAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree*
52195132 return false ;
52205133 }
52215134
5222- #ifdef DEBUG
5223- bool vnBased = false ;
5224- AssertionIndex index = NO_ASSERTION_INDEX;
5225- #endif
5226- if (optAssertionIsNonNull (indir->AsIndir ()->Addr (), assertions DEBUGARG (&vnBased) DEBUGARG (&index)))
5135+ if (optAssertionIsNonNull (indir->AsIndir ()->Addr (), assertions))
52275136 {
5228- #ifdef DEBUG
5229- if (verbose)
5230- {
5231- (vnBased) ? printf (" \n VN based non-null prop in " FMT_BB " :\n " , compCurBB->bbNum )
5232- : printf (" \n Non-null prop for index #%02u in " FMT_BB " :\n " , index, compCurBB->bbNum );
5233- gtDispTree (indir, nullptr , nullptr , true );
5234- }
5235- #endif
5137+ JITDUMP (" Non-null assertion prop for indirection [%06d] in " FMT_BB " :\n " , dspTreeID (indir), compCurBB->bbNum );
5138+
52365139 indir->gtFlags &= ~GTF_EXCEPT;
52375140 indir->gtFlags |= GTF_IND_NONFAULTING;
52385141
@@ -5429,11 +5332,9 @@ GenTree* Compiler::optAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCal
54295332 }
54305333
54315334 // Leave a hint for fgLateCastExpansion that obj is never null.
5432- INDEBUG (AssertionIndex nonNullIdx = NO_ASSERTION_INDEX);
5433- INDEBUG (bool vnBased = false );
54345335 // GTF_CALL_M_CAST_CAN_BE_EXPANDED check is to improve TP
54355336 if (((call->gtCallMoreFlags & GTF_CALL_M_CAST_CAN_BE_EXPANDED) != 0 ) &&
5436- optAssertionIsNonNull (objArg, assertions DEBUGARG (&vnBased) DEBUGARG (&nonNullIdx) ))
5337+ optAssertionIsNonNull (objArg, assertions))
54375338 {
54385339 call->gtCallMoreFlags |= GTF_CALL_M_CAST_OBJ_NONNULL;
54395340 return optAssertionProp_Update (call, call, stmt);
0 commit comments