Skip to content

JIT: eliminate redundant bounds checks for span.Slice(span.Length - cns)#127488

Open
EgorBo wants to merge 2 commits intodotnet:mainfrom
EgorBo:fix-127486-redundant-slice-bounds-checks
Open

JIT: eliminate redundant bounds checks for span.Slice(span.Length - cns)#127488
EgorBo wants to merge 2 commits intodotnet:mainfrom
EgorBo:fix-127486-redundant-slice-bounds-checks

Conversation

@EgorBo
Copy link
Copy Markdown
Member

@EgorBo EgorBo commented Apr 28, 2026

Closes #127486

For the snippet from the issue:

int Test(ReadOnlySpan<byte> span)
{
    if (span.Length >= sizeof(int))
    {
        return BinaryPrimitives.ReadInt32BigEndian(span.Slice(span.Length - sizeof(int)));
    }
    return -1;
}
-       sub      rsp, 40
-       mov      rcx, bword ptr [rdx]
-       mov      edx, dword ptr [rdx+0x08]
-       cmp      edx, 4
-       jge      SHORT G_M27777_IG05
+       mov      rax, bword ptr [rcx]
+       mov      ecx, dword ptr [rcx+0x08]
+       cmp      ecx, 4
+       jl       SHORT G_M6173_IG05
+       add      ecx, -4
+       add      rax, rcx
+       movbe    eax, dword ptr [rax]
+       ret
        mov      eax, -1
-       add      rsp, 40
        ret
-       lea      eax, [rdx-0x04]
-       cmp      eax, edx
-       ja       SHORT G_M27777_IG07
-       mov      r8d, eax
-       add      rcx, r8
-       sub      edx, eax
-       cmp      edx, 4
-       jl       SHORT G_M27777_IG08
-       movbe    eax, dword ptr [rcx]
-       add      rsp, 40
-       ret
-       call     [System.ThrowHelper:ThrowArgumentOutOfRangeException()]
-       int3
-       mov      ecx, 40
-       call     [System.ThrowHelper:ThrowArgumentOutOfRangeException(int)]
-       int3

Two changes:

  • VN: add identity x - (x + a) == -a so that length - (length - cns) value-numbers to cns. This eliminates the BinaryPrimitives.ReadInt32BigEndian length check after Slice.
  • RangeCheck: in GetRangeFromAssertionsWorker, recognize the correlated relop ADD(A, K) op A (constant K < 0) and fold it when A's lower bound is >= -K (so the add cannot wrap, signed or unsigned). This eliminates the Slice(start) (uint)start > (uint)_length check.

Copilot AI review requested due to automatic review settings April 28, 2026 01:35
@github-actions github-actions Bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Apr 28, 2026
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

Two complementary changes:

* VN: add identity 'x - (x + a) == -a' so that 'length - (length - cns)' folds to 'cns', eliminating the BinaryPrimitives length check.

* RangeCheck: in GetRangeFromAssertionsWorker, recognize the correlated relop 'ADD(A, K) op A' (K constant < 0) and fold it when A's lower bound proves ADD(A, K) does not wrap, eliminating the Slice 'start > length' check.

Fixes dotnet#127486

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@EgorBo EgorBo force-pushed the fix-127486-redundant-slice-bounds-checks branch from 366d859 to 490ce9b Compare April 28, 2026 01:38
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves CoreCLR JIT optimizations to eliminate redundant bounds checks in the common pattern span.Slice(span.Length - cns) by strengthening value numbering identities and range-check assertion reasoning, enabling subsequent checks (including in BinaryPrimitives.ReadInt32BigEndian) to fold away.

Changes:

  • Extend VN math identities to recognize x - (x + a) / x - (a + x) as -a (non-floating, non-overflowing case).
  • Enhance RangeCheck’s assertion-based relop folding by proving ADD(A, K) < A for negative K when A’s lower bound is high enough to prevent wraparound.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/coreclr/jit/valuenum.cpp Adds a new subtraction identity and cleans up ADD/SUB VNFunc usage to improve VN simplification for length - (length - cns) patterns.
src/coreclr/jit/rangecheck.cpp Adds correlated relop folding logic to eliminate the Slice(start) (uint)start > (uint)_length check when proven false via assertions.

Comment thread src/coreclr/jit/rangecheck.cpp Outdated
Comment thread src/coreclr/jit/rangecheck.cpp
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@EgorBo
Copy link
Copy Markdown
Member Author

EgorBo commented Apr 28, 2026

PTAL @jakobbotsch @dotnet/jit-contrib Diffs

@EgorBo EgorBo requested a review from jakobbotsch April 28, 2026 08:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI reduce-unsafe

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Redundant bound checks around span.Slice(span.Length - CNS)

4 participants