Skip to content

Commit 0841003

Browse files
Added support for eliminating top-level standalone range checks
1 parent adc7dde commit 0841003

File tree

4 files changed

+27
-15
lines changed

4 files changed

+27
-15
lines changed

src/coreclr/jit/assertionprop.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3679,7 +3679,7 @@ GenTree* Compiler::optAssertionProp_Comma(ASSERT_VALARG_TP assertions, GenTree*
36793679
if ((tree->gtGetOp1()->OperGet() == GT_ARR_BOUNDS_CHECK) &&
36803680
((tree->gtGetOp1()->gtFlags & GTF_ARR_BOUND_INBND) != 0))
36813681
{
3682-
optRemoveRangeCheck(tree, stmt);
3682+
optRemoveCommaBasedRangeCheck(tree, stmt);
36833683
return optAssertionProp_Update(tree, tree, stmt);
36843684
}
36853685
return nullptr;
@@ -3941,10 +3941,9 @@ GenTree* Compiler::optAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCal
39413941

39423942
/*****************************************************************************
39433943
*
3944-
* Given a tree consisting of a comma node with a bounds check, remove any
3945-
* redundant bounds check that has already been checked in the program flow.
3944+
* Given a tree with a bounds check, remove it if it has already been checked in the program flow.
39463945
*/
3947-
GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree* tree)
3946+
GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt)
39483947
{
39493948
if (optLocalAssertionProp)
39503949
{
@@ -4062,12 +4061,23 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree
40624061
gtDispTree(tree, nullptr, nullptr, true);
40634062
}
40644063
#endif
4064+
if (arrBndsChk == stmt->GetRootNode())
4065+
{
4066+
// We have a top-level bounds check node.
4067+
// This can happen when trees are broken up due to inlining.
4068+
// optRemoveStandaloneRangeCheck will return the modified tree (side effects or a no-op).
4069+
GenTree* newTree = optRemoveStandaloneRangeCheck(arrBndsChk, stmt);
4070+
4071+
return optAssertionProp_Update(newTree, arrBndsChk, stmt);
4072+
}
40654073

40664074
// Defer actually removing the tree until processing reaches its parent comma, since
4067-
// optRemoveRangeCheck needs to rewrite the whole comma tree.
4075+
// optRemoveCommaBasedRangeCheck needs to rewrite the whole comma tree.
40684076
arrBndsChk->gtFlags |= GTF_ARR_BOUND_INBND;
4077+
40694078
return nullptr;
40704079
}
4080+
40714081
return nullptr;
40724082
}
40734083

@@ -4160,7 +4170,7 @@ GenTree* Compiler::optAssertionProp(ASSERT_VALARG_TP assertions, GenTree* tree,
41604170
return optAssertionProp_Ind(assertions, tree, stmt);
41614171

41624172
case GT_ARR_BOUNDS_CHECK:
4163-
return optAssertionProp_BndsChk(assertions, tree);
4173+
return optAssertionProp_BndsChk(assertions, tree, stmt);
41644174

41654175
case GT_COMMA:
41664176
return optAssertionProp_Comma(assertions, tree, stmt);

src/coreclr/jit/earlyprop.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -388,12 +388,13 @@ GenTree* Compiler::optEarlyPropRewriteTree(GenTree* tree, LocalNumberToNullCheck
388388
if ((checkConstVal >= 0) && (checkConstVal < actualConstVal))
389389
{
390390
GenTree* comma = check->gtGetParent(nullptr);
391-
if ((comma != nullptr) && comma->OperIs(GT_COMMA) && (comma->gtGetOp1() == check))
391+
if (((comma != nullptr) && comma->OperIs(GT_COMMA) && (comma->gtGetOp1() == check)) ||
392+
(check == compCurStmt->GetRootNode()))
392393
{
393-
optRemoveRangeCheck(comma, compCurStmt);
394394
// Both `tree` and `check` have been removed from the statement.
395395
// 'tree' was replaced with 'nop' or side effect list under 'comma'.
396-
return comma->gtGetOp1();
396+
// optRemoveRangeCheck returns this modified tree.
397+
return optRemoveRangeCheck(check, comma, compCurStmt);
397398
}
398399
}
399400
}

src/coreclr/jit/optimizer.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8224,7 +8224,7 @@ void Compiler::AddModifiedElemTypeAllContainingLoops(unsigned lnum, CORINFO_CLAS
82248224
// Assumptions:
82258225
// This method is capable of removing checks of two kinds: COMMA-based and standalone top-level ones.
82268226
// In case of a COMMA-based check, "check" must be a non-null first operand of a non-null COMMA.
8227-
// If case of a standalone check, "comma" must be null and "check" - "stmt"'s root.
8227+
// In case of a standalone check, "comma" must be null and "check" - "stmt"'s root.
82288228
//
82298229
GenTree* Compiler::optRemoveRangeCheck(GenTreeBoundsChk* check, GenTree* comma, Statement* stmt)
82308230
{
@@ -8238,7 +8238,7 @@ GenTree* Compiler::optRemoveRangeCheck(GenTreeBoundsChk* check, GenTree* comma,
82388238
noway_assert(check->OperIsBoundsCheck());
82398239

82408240
GenTree* tree = comma != nullptr ? comma : check;
8241-
8241+
82428242
#ifdef DEBUG
82438243
if (verbose)
82448244
{

src/coreclr/jit/rangecheck.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,18 +187,19 @@ bool RangeCheck::BetweenBounds(Range& range, GenTree* upper, int arrSize)
187187
void RangeCheck::OptimizeRangeCheck(BasicBlock* block, Statement* stmt, GenTree* treeParent)
188188
{
189189
// Check if we are dealing with a bounds check node.
190-
if (treeParent->OperGet() != GT_COMMA)
190+
if (!(treeParent->OperIs(GT_COMMA) || (treeParent->OperIsBoundsCheck() && treeParent == stmt->GetRootNode())))
191191
{
192192
return;
193193
}
194194

195195
// If we are not looking at array bounds check, bail.
196-
GenTree* tree = treeParent->AsOp()->gtOp1;
196+
GenTree* tree = treeParent->OperIs(GT_COMMA) ? treeParent->AsOp()->gtOp1 : treeParent;
197197
if (!tree->OperIsBoundsCheck())
198198
{
199199
return;
200200
}
201201

202+
GenTree* comma = treeParent->OperIs(GT_COMMA) ? treeParent : nullptr;
202203
GenTreeBoundsChk* bndsChk = tree->AsBoundsChk();
203204
m_pCurBndsChk = bndsChk;
204205
GenTree* treeIndex = bndsChk->gtIndex;
@@ -258,7 +259,7 @@ void RangeCheck::OptimizeRangeCheck(BasicBlock* block, Statement* stmt, GenTree*
258259
if ((idxVal < arrSize) && (idxVal >= 0))
259260
{
260261
JITDUMP("Removing range check\n");
261-
m_pCompiler->optRemoveRangeCheck(treeParent, stmt);
262+
m_pCompiler->optRemoveRangeCheck(bndsChk, comma, stmt);
262263
return;
263264
}
264265
}
@@ -299,7 +300,7 @@ void RangeCheck::OptimizeRangeCheck(BasicBlock* block, Statement* stmt, GenTree*
299300
if (BetweenBounds(range, bndsChk->gtArrLen, arrSize))
300301
{
301302
JITDUMP("[RangeCheck::OptimizeRangeCheck] Between bounds\n");
302-
m_pCompiler->optRemoveRangeCheck(treeParent, stmt);
303+
m_pCompiler->optRemoveRangeCheck(bndsChk, comma, stmt);
303304
}
304305
return;
305306
}

0 commit comments

Comments
 (0)