@@ -4998,23 +4998,6 @@ GenTree* Compiler::optAssertionProp_Cast(ASSERT_VALARG_TP assertions,
49984998 return nullptr ;
49994999}
50005000
5001- /* ****************************************************************************
5002- *
5003- * Given a tree with an array bounds check node, eliminate it because it was
5004- * checked already in the program.
5005- */
5006- GenTree* Compiler::optAssertionProp_Comma (ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt)
5007- {
5008- // Remove the bounds check as part of the GT_COMMA node since we need parent pointer to remove nodes.
5009- // When processing visits the bounds check, it sets the throw kind to None if the check is redundant.
5010- if (tree->gtGetOp1 ()->OperIs (GT_BOUNDS_CHECK ) && ((tree->gtGetOp1 ()->gtFlags & GTF_CHK_INDEX_INBND ) != 0 ))
5011- {
5012- optRemoveCommaBasedRangeCheck (tree, stmt);
5013- return optAssertionProp_Update (tree, tree, stmt);
5014- }
5015- return nullptr ;
5016- }
5017-
50185001// ------------------------------------------------------------------------
50195002// optAssertionProp_Ind: see if we can prove the indirection can't cause
50205003// and exception.
@@ -5501,59 +5484,40 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions,
55015484 Statement* stmt,
55025485 BasicBlock* block)
55035486{
5504- if (optLocalAssertionProp)
5505- {
5506- return nullptr ;
5507- }
5508-
55095487 assert (tree->OperIs (GT_BOUNDS_CHECK ));
5510-
5511- #ifdef FEATURE_ENABLE_NO_RANGE_CHECKS
5512- if (JitConfig.JitNoRngChks ())
5488+ if (optLocalAssertionProp)
55135489 {
5514- #ifdef DEBUG
5515- if (verbose)
5516- {
5517- printf (" \n Flagging check redundant due to JitNoRngChks in " FMT_BB " :\n " , compCurBB->bbNum );
5518- gtDispTree (tree, nullptr , nullptr , true );
5519- }
5520- #endif // DEBUG
5521- tree->gtFlags |= GTF_CHK_INDEX_INBND ;
5490+ // We don't have the right kind of assertions to optimize bounds checks in local assertion prop.
55225491 return nullptr ;
55235492 }
5524- #endif // FEATURE_ENABLE_NO_RANGE_CHECKS
55255493
55265494 GenTreeBoundsChk* arrBndsChk = tree->AsBoundsChk ();
55275495 GenTree* arrBndsChkIdx = arrBndsChk->GetIndex ();
55285496 GenTree* arrBndsChkLen = arrBndsChk->GetArrayLength ();
5529- ValueNum vnCurIdx = vnStore-> VNConservativeNormalValue (arrBndsChkIdx-> gtVNPair );
5530- ValueNum vnCurLen = vnStore-> VNConservativeNormalValue (arrBndsChkLen-> gtVNPair );
5497+ ValueNum vnCurIdx = optConservativeNormalVN (arrBndsChkIdx);
5498+ ValueNum vnCurLen = optConservativeNormalVN (arrBndsChkLen);
55315499
55325500 auto dropBoundsCheck = [&](INDEBUG (const char * reason)) -> GenTree* {
5533- JITDUMP (" \n VN based redundant (%s) bounds check assertion prop in " FMT_BB " :\n " , reason, compCurBB->bbNum );
5501+ JITDUMP (" \n Removing redundant (%s) bounds check in " FMT_BB " :\n " , reason, compCurBB->bbNum );
55345502 DISPTREE (tree);
5535- if (arrBndsChk != stmt->GetRootNode ())
5536- {
5537- // Defer the removal.
5538- arrBndsChk->gtFlags |= GTF_CHK_INDEX_INBND ;
5539- return nullptr ;
5540- }
55415503
5542- GenTree* newTree = optRemoveStandaloneRangeCheck (arrBndsChk, stmt);
5543- return optAssertionProp_Update (newTree, arrBndsChk, stmt);
5504+ // Extract the side effects of idx and len. We deliberately ignore the potential null-check
5505+ // exception of the length (e.g. GT_ARR_LENGTH): having proven the bounds check redundant, we
5506+ // have also proven the length load is non-faulting. This mirrors the hack in optRemoveRangeCheck.
5507+ GenTree* sideEffList = nullptr ;
5508+ gtExtractSideEffList (arrBndsChkLen, &sideEffList, GTF_ASG );
5509+ gtExtractSideEffList (arrBndsChkIdx, &sideEffList);
5510+
5511+ GenTree* nothing = (sideEffList != nullptr ) ? sideEffList : gtNewNothingNode ();
5512+ return optAssertionProp_Update (nothing, arrBndsChk, stmt);
55445513 };
55455514
55465515 BitVecOps::Iter iter (apTraits, assertions);
55475516 unsigned index = 0 ;
55485517 while (iter.NextElem (&index))
55495518 {
5550- AssertionIndex assertionIndex = GetAssertionIndex (index);
5551- if (assertionIndex > optAssertionCount)
5552- {
5553- break ;
5554- }
55555519 // If it is not a nothrow assertion, skip.
5556- const AssertionDsc& curAssertion = optGetAssertion (assertionIndex );
5520+ const AssertionDsc& curAssertion = optGetAssertion (GetAssertionIndex (index) );
55575521 if (!curAssertion.IsBoundsCheckNoThrow ())
55585522 {
55595523 continue ;
@@ -5695,6 +5659,7 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions,
56955659 return dropBoundsCheck (INDEBUG (" upper bound of index is less than lower bound of length" ));
56965660 }
56975661 }
5662+
56985663 return nullptr ;
56995664}
57005665
@@ -5843,9 +5808,6 @@ GenTree* Compiler::optAssertionProp(ASSERT_VALARG_TP assertions, GenTree* tree,
58435808 case GT_BOUNDS_CHECK :
58445809 return optAssertionProp_BndsChk (assertions, tree, stmt, block);
58455810
5846- case GT_COMMA :
5847- return optAssertionProp_Comma (assertions, tree, stmt);
5848-
58495811 case GT_CAST :
58505812 return optAssertionProp_Cast (assertions, tree->AsCast (), stmt, block);
58515813
0 commit comments