Skip to content

Use SSA-based TryGetRange to fold conditions#129354

Open
EgorBo wants to merge 3 commits into
dotnet:mainfrom
EgorBo:ssa-based-relop
Open

Use SSA-based TryGetRange to fold conditions#129354
EgorBo wants to merge 3 commits into
dotnet:mainfrom
EgorBo:ssa-based-relop

Conversation

@EgorBo

@EgorBo EgorBo commented Jun 12, 2026

Copy link
Copy Markdown
Member

Diffs (~ -1.2Mb on linux-x64)

We have two ways of computing a Range {int lo;int hi} for a tree:

  • GetRangeFromAssertions (purely on top of VN and assertions, handles PHIs as well)
  • TryGetRange - SSA-based approach + assertions + GetRangeFromAssertions, used for GT_BOUNDS_CHECK only today.

This PR enables TryGetRange for folding relops in global assertion prop. The TP Impact is 0.3-0.4% on average, I have some ideas how to improve it inside RangeCheck, but I think it's worth it.

Mainly, it helps folding various Span.Slice checks we don't use GT_BOUNDS_CHECK for.

NOTE: we don't set preferred bound yet when we call it, I'll experiment with that separately.

Copilot AI review requested due to automatic review settings June 12, 2026 22:52
@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 Jun 12, 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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 extends JIT assertion propagation to opportunistically fold ordered integer relational operators (<, <=, >, >=) to constant true/false using the SSA-based RangeCheck::TryGetRange analysis, and adds a small constant fast-path in TryGetRange itself to make such queries cheaper.

Changes:

  • Add a constant fast-path to RangeCheck::TryGetRange for int/nint constants that fit in int32.
  • In optAssertionPropGlobal_RelOp, when assertion-based range evaluation can’t prove a relop constant, attempt SSA-based operand range discovery via TryGetRange and fold when the relop becomes provably constant.

Reviewed changes

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

File Description
src/coreclr/jit/rangecheck.cpp Adds a fast-path for constant expressions in RangeCheck::TryGetRange.
src/coreclr/jit/assertionprop.cpp Adds SSA-based range evaluation to fold certain ordered relops during global assertion propagation.

@EgorBo EgorBo marked this pull request as ready for review June 13, 2026 02:26
Copilot AI review requested due to automatic review settings June 13, 2026 02:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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/assertionprop.cpp Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 2 comments.

Comment thread src/coreclr/jit/assertionprop.cpp Outdated
Comment thread src/coreclr/jit/assertionprop.cpp Outdated
@EgorBo EgorBo force-pushed the ssa-based-relop branch from d1283a6 to 5144397 Compare June 13, 2026 14:25
@EgorBo

EgorBo commented Jun 14, 2026

Copy link
Copy Markdown
Member Author

/azp list

@azure-pipelines

This comment was marked as resolved.

@EgorBo

EgorBo commented Jun 14, 2026

Copy link
Copy Markdown
Member Author

/azp run runtime-coreclr outerloop, runtime-coreclr jitstress, runtime-coreclr libraries-pgo, Fuzzlyn

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 4 pipeline(s).

…ed type

The VNF_Cast handling in RangeCheck::GetRangeFromAssertionsWorker reused the
source-type range for any widening cast, assuming the value is preserved. That
is wrong when widening a signed source into a smaller-than-int unsigned type
(e.g. (ushort)(sbyte)): negative source values are zero-extended into large
positive values ((ushort)(-1) == 65535), so the source range no longer bounds
the result. The new SSA-based relop folding then folded conditions such as
30997 > (ushort)s_F3 to a wrong constant.

Use the destination-type range in that case. Found by Fuzzlyn.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 15, 2026 12:24
@EgorBo

EgorBo commented Jun 15, 2026

Copy link
Copy Markdown
Member Author

/azp run Fuzzlyn

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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/assertionprop.cpp
@EgorBo

EgorBo commented Jun 15, 2026

Copy link
Copy Markdown
Member Author

PTAL @AndyAyersMS @dotnet/jit-contrib see description

@EgorBo EgorBo requested a review from AndyAyersMS June 15, 2026 17:23
// RangeCheck does not understand reads through LCL_FLD nodes: a LCL_FLD use reads a
// sub-range of the local (a different offset and/or a narrower type), so the value
// produced by the (full-width) definition does not describe the value being read.
if (lclUse->OperIs(GT_LCL_FLD))

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.

a correctness issue I found as part of this PR.

// signed source into a smaller-than-int unsigned type (e.g. (ushort)(sbyte)). There, negative
// source values are zero-extended into large positive values (e.g. (ushort)(-1) == 65535), so
// the source range no longer bounds the result.
bool widensToSmallUnsigned = varTypeIsUnsigned(castToType) &&

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.

another pre-existing correctness issue we had

@AndyAyersMS AndyAyersMS left a comment

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.

Nice improvements!

assert(block != nullptr);
assert(tree != nullptr);

int budget = 64;

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.

How do we arrive at these budget values?

@EgorBo

EgorBo commented Jun 16, 2026

Copy link
Copy Markdown
Member Author

/azp run Fuzzlyn

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants