Skip to content

Commit 651c190

Browse files
EgorBoCopilot
andauthored
More cleanups in rangecheck/assertionprop (#129325)
* Remove `GTF_CHK_INDEX_INBND` and unconditionally always remove `GT_BOUNDS_CHECK` in assertprop when we can * Remove `FEATURE_ENABLE_NO_RANGE_CHECKS` and `DOTNET_JitNoRngChks`, these were never enabled by default and I don't think they have any value. * Correctness improvement: we no longer use this [potential bug](https://github.com/dotnet/runtime/blob/d71e0a994980fc47a1efb4ce2c207947e7efedca/src/coreclr/jit/optimizer.cpp#L5545-L5553) and extract all side-effects. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 2c05d04 commit 651c190

6 files changed

Lines changed: 16 additions & 86 deletions

File tree

src/coreclr/inc/switches.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,6 @@
119119

120120
#endif // _DEBUG
121121

122-
// MUST NEVER CHECK IN WITH THIS ENABLED.
123-
// This is just for convenience in doing performance investigations in a checked-out enlistment.
124-
// #define FEATURE_ENABLE_NO_RANGE_CHECKS
125-
126122
// This controls whether a compilation-timing feature that relies on Windows APIs, if available, else direct
127123
// hardware instructions (rdtsc), for accessing high-resolution hardware timers is enabled. This is disabled
128124
// in Silverlight (just to avoid thinking about whether the extra code space is worthwhile).

src/coreclr/jit/assertionprop.cpp

Lines changed: 16 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -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("\nFlagging 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("\nVN based redundant (%s) bounds check assertion prop in " FMT_BB ":\n", reason, compCurBB->bbNum);
5501+
JITDUMP("\nRemoving 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

src/coreclr/jit/compiler.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7523,7 +7523,6 @@ class Compiler
75237523
public:
75247524
PhaseStatus rangeCheckPhase();
75257525
GenTree* optRemoveRangeCheck(GenTreeBoundsChk* check, GenTree* comma, Statement* stmt);
7526-
GenTree* optRemoveStandaloneRangeCheck(GenTreeBoundsChk* check, Statement* stmt);
75277526
void optRemoveCommaBasedRangeCheck(GenTree* comma, Statement* stmt);
75287527

75297528
protected:
@@ -9233,7 +9232,6 @@ class Compiler
92339232
GenTree* optAssertionProp_Cast(ASSERT_VALARG_TP assertions, GenTreeCast* cast, Statement* stmt, BasicBlock* block);
92349233
GenTree* optAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call, Statement* stmt);
92359234
GenTree* optAssertionProp_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt, BasicBlock* block);
9236-
GenTree* optAssertionProp_Comma(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt);
92379235
GenTree* optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt, BasicBlock* block);
92389236
GenTree* optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions,
92399237
GenTree* tree,

src/coreclr/jit/gentree.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,8 +528,6 @@ enum GenTreeFlags : unsigned
528528

529529
GTF_DIV_MOD_NO_OVERFLOW = 0x40000000, // GT_DIV, GT_MOD -- Div or mod definitely does not overflow.
530530

531-
GTF_CHK_INDEX_INBND = 0x80000000, // GT_BOUNDS_CHECK -- have proven this check is always in-bounds
532-
533531
GTF_ARRLEN_NONFAULTING = 0x20000000, // GT_ARR_LENGTH -- An array length operation that cannot fault. Same as GT_IND_NONFAULTING.
534532

535533
GTF_MDARRLEN_NONFAULTING = 0x20000000, // GT_MDARR_LENGTH -- An MD array length operation that cannot fault. Same as GT_IND_NONFAULTING.

src/coreclr/jit/jitconfigvalues.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -576,10 +576,6 @@ RELEASE_CONFIG_INTEGER(JitInlineSIMDMultiplier, "JitInlineSIMDMultiplier", 3)
576576
// Ex lclMAX_TRACKED constant.
577577
RELEASE_CONFIG_INTEGER(JitMaxLocalsToTrack, "JitMaxLocalsToTrack", 0x400)
578578

579-
#if defined(FEATURE_ENABLE_NO_RANGE_CHECKS)
580-
RELEASE_CONFIG_INTEGER(JitNoRngChks, "JitNoRngChks", 0) // If 1, don't generate range checks
581-
#endif
582-
583579
OPT_CONFIG_INTEGER(JitDoAssertionProp, "JitDoAssertionProp", 1) // Perform assertion propagation optimization
584580
OPT_CONFIG_INTEGER(JitDoCopyProp, "JitDoCopyProp", 1) // Perform copy propagation on variables that appear redundant
585581
OPT_CONFIG_INTEGER(JitDoOptimizeIVs, "JitDoOptimizeIVs", 1) // Perform optimization of induction variables

src/coreclr/jit/optimizer.cpp

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5674,26 +5674,6 @@ GenTree* Compiler::optRemoveRangeCheck(GenTreeBoundsChk* check, GenTree* comma,
56745674
return check;
56755675
}
56765676

5677-
//------------------------------------------------------------------------------
5678-
// optRemoveStandaloneRangeCheck : A thin wrapper over optRemoveRangeCheck that removes standalone checks.
5679-
//
5680-
// Arguments:
5681-
// check - The standalone top-level CHECK node.
5682-
// stmt - The statement "check" is a root node of.
5683-
//
5684-
// Return Value:
5685-
// If "check" has no side effects, it is retuned, bashed to a no-op.
5686-
// If it has side effects, the tree that executes them is returned.
5687-
//
5688-
GenTree* Compiler::optRemoveStandaloneRangeCheck(GenTreeBoundsChk* check, Statement* stmt)
5689-
{
5690-
assert(check != nullptr);
5691-
assert(stmt != nullptr);
5692-
assert(check == stmt->GetRootNode());
5693-
5694-
return optRemoveRangeCheck(check, nullptr, stmt);
5695-
}
5696-
56975677
//------------------------------------------------------------------------------
56985678
// optRemoveCommaBasedRangeCheck : A thin wrapper over optRemoveRangeCheck that removes COMMA-based checks.
56995679
//

0 commit comments

Comments
 (0)