JIT: Elide transitive array bounds checks#130588
Open
EgorBo wants to merge 4 commits into
Open
Conversation
Contributor
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR extends JIT assertion propagation + range analysis so it can chain certain unsigned relations involving checked-bound VNs (e.g., size u<= items.Length) to prove a subsequent index relation (e.g., index u< size) and thereby elide the transitive array bounds check for items[index].
Changes:
- Teach
optCreateJTrueBoundsAssertionto create/selectively admit unsigned VN-to-VN and checked-bound assertions that can participate in chaining. - Update
RangeCheck::MergeEdgeAssertionsWorkerto (a) acceptLE_UNchecked-bound assertions and (b) derive bounds through transitive unsigned VN relations while preserving checked-bound-shaped limits. - Add a JIT opt test covering the “
index < size <= length” pattern and asserting noCORINFO_HELP_RNGCHKFAILappears in the generated code.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/tests/JIT/opt/RangeChecks/ElidedBoundsChecks.cs | Adds a new regression/opt-pattern method and invocation to validate transitive unsigned bounds-check elimination. |
| src/coreclr/jit/rangecheck.cpp | Enables transitive reasoning across unsigned relations (with guardrails) and preserves checked-bound limits when following VN chains. |
| src/coreclr/jit/assertionprop.cpp | Broadens assertion creation to support the unsigned checked-bound chaining needed by the rangecheck optimization, with heuristics to limit table pressure. |
Comment on lines
+273
to
+276
| // Bounds-check coalescing: 4 constant indices, same length VN. | ||
| int[] arr4 = new int[] { 10, 20, 30, 40 }; | ||
| if (IndexLessThanSizeLessThanOrEqualToLength(arr4, 3, 2) != 30) | ||
| return 0; |
Comment on lines
+1794
to
+1796
| // Restrict optional unsigned relation assertions to small methods, where they cannot crowd out | ||
| // later bounds-check assertions in an already pressured assertion table. | ||
| const bool canCreateUnsignedRelation = optMaxAssertionCount == 64; |
8e84a81 to
d67fb6b
Compare
Comment on lines
+1572
to
+1582
| budget--; | ||
| Range otherRange = GetRangeFromAssertionsWorker(comp, otherVN, assertions, budget, visited); | ||
| if (!otherRange.IsConstantRange()) | ||
| int nextBudget = budget; | ||
| Range otherRange = GetRangeFromAssertionsWorker(comp, otherVN, assertions, nextBudget, visited); | ||
|
|
||
| // Preserve checked-bound-shaped limits while following a chain such as | ||
| // "index u< size" and "size u<= array.Length". | ||
| if (canUseCheckedBounds) | ||
| { | ||
| MergeEdgeAssertionsWorker(comp, otherVN, preferredBoundVN, assertions, &otherRange, canUseCheckedBounds, | ||
| nextBudget, visited); | ||
| } |
Track bounds-check index VNs and let range analysis propagate symbolic bounds through unsigned VN comparisons. Preserve the distinction between index operands and non-negative length bounds. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b997c5bf-c48e-4c43-af7f-3062fc691e31
Restrict symbolic unsigned bound propagation to unresolved ranges and non-strict intermediate array-length bounds. Keep legacy length-only assertion consumers from treating marked index VNs as lengths. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b997c5bf-c48e-4c43-af7f-3062fc691e31
Keep length and index VN markers separate, and recognize the exact short-circuit predecessor pattern at bounds-check assertion propagation. Do not infer non-negativity from checked-bound membership. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b997c5bf-c48e-4c43-af7f-3062fc691e31
d67fb6b to
19159f8
Compare
When an index has an unsigned upper-bound assertion against an intermediate VN, resolve that VN through assertions using the current preferred array-length bound. Keep existing unsigned-bound recognition precedence and require explicit non-negativity facts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b997c5bf-c48e-4c43-af7f-3062fc691e31
Comment on lines
+1531
to
+1532
| if (boundRange.LowerLimit().IsConstant() && (boundRange.LowerLimit().GetConstant() >= 0) && | ||
| boundRange.UpperLimit().IsBinOpArray() && (boundRange.UpperLimit().vn == preferredBoundVN)) |
Comment on lines
+1519
to
+1525
| // Current assertion is "normalLclVN u< boundVN". Get boundVN's range using our preferred bound. | ||
| else if (canUseCheckedBounds && pRange->LowerLimit().IsUnknown() && pRange->UpperLimit().IsUnknown() && | ||
| curAssertion.KindIs(Compiler::OAK_LT_UN) && | ||
| (curAssertion.GetOp1().GetVN() == normalLclVN) && | ||
| curAssertion.GetOp2().KindIs(Compiler::O2K_VN_ADD_CNS) && | ||
| (curAssertion.GetOp2().GetVN() != preferredBoundVN) && (curAssertion.GetOp2().GetCns() == 0) && | ||
| (budget > 0)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #121795
Diffs