Skip to content

Commit ebbfec3

Browse files
authored
[Bounds checks] Tighten pRange in MergeEdgeAssertions via X != CNS assertions (#121273)
Closes #121259 When we already have, say, `[1..10]` range for `X` and we encounter `X != 1` assertion, we can tighten the range to `[2..10]` Removes bounds checks for the following snippet: ```cs void Test(ReadOnlySpan<char> name) { if (name is [] or [':'] or [':', not ':', ..]) { Console.WriteLine("test"); } } ``` [Diffs](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1191071&view=ms.vss-build-web.run-extensions-tab)
1 parent 5f84cb0 commit ebbfec3

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

src/coreclr/jit/rangecheck.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -863,8 +863,28 @@ void RangeCheck::MergeEdgeAssertions(Compiler* comp,
863863
}
864864
else
865865
{
866-
// We have a != assertion, but it doesn't tell us much about the interval. So just skip it.
867-
continue;
866+
assert(curAssertion->assertionKind == Compiler::OAK_NOT_EQUAL);
867+
868+
// We have an assertion of the form "X != constLimit".
869+
// For example, if the assertion is "X != 100" and the current range for X is [100, X],
870+
// we can tighten the range to [101, X].
871+
// Similarly, if the range is [Y, 100], we can tighten it to [Y, 99].
872+
873+
if (pRange->LowerLimit().IsConstant() && pRange->LowerLimit().GetConstant() == cnstLimit)
874+
{
875+
limit = Limit(Limit::keConstant, cnstLimit);
876+
cmpOper = GT_GT;
877+
}
878+
else if (pRange->UpperLimit().IsConstant() && pRange->UpperLimit().GetConstant() == cnstLimit)
879+
{
880+
limit = Limit(Limit::keConstant, cnstLimit);
881+
cmpOper = GT_LT;
882+
}
883+
else
884+
{
885+
// We can't make any useful deduction from this assertion.
886+
continue;
887+
}
868888
}
869889

870890
isConstantAssertion = true;

0 commit comments

Comments
 (0)