Skip to content

[experiment] JIT: Introduce KnownBits#129082

Draft
EgorBo wants to merge 3 commits into
dotnet:mainfrom
EgorBo:knownbits
Draft

[experiment] JIT: Introduce KnownBits#129082
EgorBo wants to merge 3 commits into
dotnet:mainfrom
EgorBo:knownbits

Conversation

@EgorBo
Copy link
Copy Markdown
Member

@EgorBo EgorBo commented Jun 6, 2026

Closes #105333
Closes #111567

Most optimizing compilers use KnownBits to track ranges, e.g. LLVM, MSVC vs tracking Min-Max values.
We have Range wich is 32-bit only and will likely require lots of efforts to make it 64-bit, fix casts between 32-bit and 64-bit, fight with all kinds of overflows and correctness issues and still it's only good fo representing continues ranges.

KnownBits looks like this:

struct KnownBits
{
    uint64_t knownZero;
    uint64_t knownOne;
}

My estimate it can bring 500k-600k diffs for win-x64 if extended (I've seen 450k with +400 LOC), current version should be -320kb on win-x64 with somewhat nices improvements in non-tests collections.

I'm not sure it can fully replace Range just like Range can't replace KnownBits, but some usages definitely can be re-routed to KnownBits.

This PR is basically an attempt to mimic LLVM's impl

Not done:

  • Enable assertions for 64-bit VNs, today we don't spawn them
  • Migrate more opts from MergeEdgeAssertions to MergeKnownBitsAssertions
  • Support more operations, benefit from Compute range for various GT_AND, GT_ORR in assertion prop, etc

Diffs - -662244 bytes on linux-arm64

Copilot AI review requested due to automatic review settings June 6, 2026 21:42
@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 6, 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.

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 adds a new JIT-internal KnownBits analysis (LLVM-style “known zero/known one” bit lattice) and wires it into assertion propagation so the JIT can fold more comparisons (including TYP_LONG) and prove more casts redundant/overflow-safe using bit-level facts.

Changes:

  • Introduces KnownBits / KnownBitsOps (bit lattice + transfer functions) and a KnownBits::Compute VN/assertion-driven analysis.
  • Uses KnownBits in global assertion propagation to fold relops and to remove/relax casts when provably safe.
  • Updates JIT build wiring to compile the new implementation.

Reviewed changes

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

File Description
src/coreclr/jit/knownbits.h New KnownBits lattice + transfer helpers (And/Or/UDiv/Cast/EvalRelop) and analysis entrypoint.
src/coreclr/jit/knownbits.cpp Implements VN/assertion-based KnownBits computation, including PHI merging and assertion refinement.
src/coreclr/jit/CMakeLists.txt Adds KnownBits sources/headers to the JIT build.
src/coreclr/jit/assertionprop.cpp Hooks KnownBits into global relop folding and cast simplification paths; widens some assertion creation gates to include TYP_LONG.

Comment thread src/coreclr/jit/knownbits.h Outdated
Copilot AI review requested due to automatic review settings June 7, 2026 02:20
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 6 out of 6 changed files in this pull request and generated 1 comment.

Comment thread src/coreclr/jit/knownbits.h Outdated
Copilot AI review requested due to automatic review settings June 7, 2026 04:43
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 6 out of 6 changed files in this pull request and generated 3 comments.

Comment thread src/coreclr/jit/knownbits.h Outdated
Comment thread src/coreclr/jit/assertionprop.cpp Outdated
Comment thread src/coreclr/jit/assertionprop.cpp Outdated
Adds a 32/64-bit fixed-width KnownBits lattice for integral VNs, plus an
assertion-aware analysis (KnownBits::Compute) that derives the known bits of
a value number from its VN structure and the incoming assertions. The struct
and transfer functions are ports of llvm::KnownBits from
llvm/Support/KnownBits.{h,cpp}; only the subset of operations needed by the
current consumers (And/Or/UDiv/Cast/EvalRelop) is included.

Three consumers wired in assertionprop.cpp:
* optAssertionProp_RangeProperties - sign-bit/non-zero from KnownBits
* optAssertionPropGlobal_RelOp     - relop folding
* optAssertionProp_BndsChk         - (uint)index < (uint)length

Plus a one-shot KnownBits refinement at the end of
RangeCheck::GetRangeFromAssertionsWorker that tightens the signed [lo, hi]
when an interval side is at the type extreme.

libraries.pmi: -14,515 / +6 bytes (489 contexts, 409 size improvements,
2 regressions).
libraries_tests.run: -246k / +0.4k bytes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
EgorBo and others added 2 commits June 7, 2026 18:08
The bounds-check consumer hardcoded width=32 in EvalRelop, which is unsound on
64-bit targets where fgMorphIndexAddr (morph.cpp:2995-3015) widens the bounds
check to TYP_I_IMPL when the index is native int. With a TYP_LONG index whose
low 32 bits are provably small but whose high 32 bits are unknown, the fold
could prove (uint)idx < (uint)len using only the low half and incorrectly drop
a required bounds check (memory corruption).

Derive the width from the operand type, matching the other two consumers.
Caught by Opus 4.7 (xhigh), Opus 4.8, and GPT-5.5 in parallel review.

Also drop the now-dead #include "knownbits.h" from rangecheck.cpp left over
from the previous cleanup commit.

libraries.pmi: -13,920 bytes (was -14,515; ~600 byte loss is the correctness
recovery -- those wins were unsound TYP_LONG bounds-check drops).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 7, 2026 16:30
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 on lines +4534 to +4539
// See if we can fold the relop based on known bits. This complements the range-based folding
// above (which is limited to TYP_INT) by reasoning about individual bits and TYP_LONG values.
if (varTypeIsIntegral(op1) && (op1VN != ValueNumStore::NoVN) && (op2VN != ValueNumStore::NoVN))
{
const unsigned width = genTypeSize(genActualType(op1)) * BITS_PER_BYTE;
const KnownBits kb1 = KnownBits::Compute(this, op1VN, assertions);
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.

Unnecessary overflow check with checked on 64-bit ryujit Unnecessary overflow check for checked BigMul on x64

2 participants