Skip to content

JIT: eliminate redundant span checks across loop back-edge phis#127117

Open
EgorBo wants to merge 6 commits intomainfrom
jit-rangecheck-phi-add-cns
Open

JIT: eliminate redundant span checks across loop back-edge phis#127117
EgorBo wants to merge 6 commits intomainfrom
jit-rangecheck-phi-add-cns

Conversation

@EgorBo
Copy link
Copy Markdown
Member

@EgorBo EgorBo commented Apr 19, 2026

Contributes to #111309

Optimize redundant range/argument checks for spans inside loops.

int Sum(ReadOnlySpan<int> data)
{
    Vector128<int> sum = default;
    while (data.Length >= Vector128<int>.Count)
    {
        sum += Vector128.Create(data);
        data = data.Slice(Vector128<int>.Count);
    }
    int result = Vector128.Sum(sum);
    foreach (var t in data)
        result += t;
    return result;
}

Codegen diff

 G_M38854_IG02:
        mov      rax, bword ptr [rcx]
        mov      ecx, dword ptr [rcx+0x08]
        vxorps   xmm0, xmm0, xmm0
        cmp      ecx, 4
        jl       SHORT G_M38854_IG04
 G_M38854_IG03:
-       cmp      ecx, 4
-       jl       SHORT G_M38854_IG09
        vpaddd   xmm0, xmm0, xmmword ptr [rax]
        add      rax, 16
        add      ecx, -4
        cmp      ecx, 4
        jge      SHORT G_M38854_IG03
 G_M38854_IG04:
        vpsrldq  xmm1, xmm0, 8
        vpaddd   xmm0, xmm1, xmm0
        vpsrldq  xmm1, xmm0, 4
        vpaddd   xmm0, xmm1, xmm0
        vmovd    edx, xmm0
        test     ecx, ecx
        je       SHORT G_M38854_IG07
 G_M38854_IG05:
        xor      r8d, r8d
 G_M38854_IG06:
        add      edx, dword ptr [rax+r8]
        add      r8, 4
        dec      ecx
        jne      SHORT G_M38854_IG06
 G_M38854_IG07:
        mov      eax, edx
 G_M38854_IG08:
-       add      rsp, 40
        ret
-G_M38854_IG09:
-       mov      ecx, 6
-       call     [System.ThrowHelper:ThrowArgumentOutOfRangeException(int)]
-       int3
-; Total bytes of code 113
+; Total bytes of code 79

Diffs

Recognize that a back-edge phi-arg's VN equals the (checkedBound + cns) form referenced by an O2K_CHECKED_BOUND_ADD_CNS assertion in RangeCheck::MergeEdgeAssertions.

Read phi-arg VNs from the SSA def's m_vnPair in optVisitReachingAssertions; this is always at least as precise as phiArg->gtVNPair (which fgValueNumberPhiDef may leave as NoVN or stale when it refuses to back-patch a loop-varying VN).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 19, 2026 11:29
@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 19, 2026
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

Optimize CoreCLR JIT range/argument check elimination for spans in loops by improving how edge assertions are interpreted across loop back-edge phi arguments.

Changes:

  • Extend RangeCheck::MergeEdgeAssertions to recognize when the tracked VN matches a checked-bound expression via ADD(boundVN, cns), enabling assertion application to loop back-edge phi-args.
  • Update Compiler::optVisitReachingAssertions to read the VN for a phi-arg from its SSA def’s m_vnPair (instead of the potentially stale gtVNPair), improving precision for assertion propagation.

Reviewed changes

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

File Description
src/coreclr/jit/rangecheck.cpp Enhances checked-bound assertion matching so loop back-edge phi args can inherit assertions and eliminate redundant checks.
src/coreclr/jit/compiler.hpp Uses SSA-def VN for phi args during reaching-assertion visitation to avoid gtVNPair staleness/NoVN cases.

Comment thread src/coreclr/jit/rangecheck.cpp Outdated
- optVisitReachingAssertions: only fall back to the SSA def's m_vnPair when phiArg->gtVNPair is NoVN, restoring the cheap fast-path for the common case.

- MergeEdgeAssertions: skip the IsVNBinFuncWithConst lookup when boundCns == 0, since VN normalizes ADD(x, 0) to x, so any positive match would already be caught by the trivial check.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 19, 2026 13: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

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment thread src/coreclr/jit/rangecheck.cpp Outdated
@EgorBo EgorBo force-pushed the jit-rangecheck-phi-add-cns branch from e5170d0 to ff00e93 Compare April 19, 2026 14:44
Copilot AI review requested due to automatic review settings April 19, 2026 15:08
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

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

Comment thread src/coreclr/jit/rangecheck.cpp
Comment thread src/coreclr/jit/compiler.hpp Outdated
Comment thread src/coreclr/jit/rangecheck.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 19, 2026 15:21
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

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

Comment thread src/coreclr/jit/rangecheck.cpp
@EgorBo
Copy link
Copy Markdown
Member Author

EgorBo commented Apr 20, 2026

PTAL @jakobbotsch @dotnet/jit-contrib

@EgorBo EgorBo requested a review from jakobbotsch April 20, 2026 13:55
auto visitor = [comp, &phiRange, &budget](ValueNum reachingVN, ASSERT_TP reachingAssertions) {
// call GetRangeFromAssertions for each reaching VN using reachingAssertions
Range edgeRange = GetRangeFromAssertions(comp, reachingVN, reachingAssertions, --budget);
Range edgeRange = GetRangeFromAssertions(comp, reachingVN, reachingAssertions, min(3, --budget));
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

After I switched optVisitReachingAssertion to SSA defs instead of VNs it significantly regressed TP, this helped to reduce it 3x times

Comment on lines +5629 to +5635
// fgValueNumberPhiDef may leave gtVNPair as NoVN when it refuses to back-patch
// a loop-varying SSA-def VN into the phi-arg slot (a hygiene constraint for general
// gtVNPair consumers that does not apply here, since we hand the VN to the visitor
// together with this edge's assertion set and never write it back into any tree).
// Use the SSA def's VN directly; by SSA construction it names the same value.
LclSsaVarDsc* phiArgSsaDef = lvaGetDesc(phiArg)->GetPerSsaData(phiArg->GetSsaNum());
const ValueNum phiArgVN = vnStore->VNConservativeNormalValue(phiArgSsaDef->m_vnPair);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not clear to me if this is legal... See #106229 and the issue it links to. The VNs from the phi def can be from a different loop iteration and it can take on a different runtime value.

Copy link
Copy Markdown
Member Author

@EgorBo EgorBo Apr 20, 2026

Choose a reason for hiding this comment

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

@jakobbotsch but isn't similar how rangecheck works? where we iterate phi via SSA and call MergeEdgeAssertions on them?
{E35C1120-7A35-40AC-A098-DEB1EC7703BF}

(we obtain VN out of the tree inside)

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.

3 participants