') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); [experiment] JIT: Introduce KnownBits by EgorBo · Pull Request #129082 · dotnet/runtime · GitHub
Skip to content

[experiment] JIT: Introduce KnownBits - #129082

Closed
EgorBo wants to merge 4 commits into
dotnet:mainfrom
EgorBo:knownbits
Closed

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

Conversation

@EgorBo

@EgorBoEgorBo commented Jun 6, 2026

Copy link
Copy Markdown
Member

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:

structKnownBits
{
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

CopilotAI review requested due to automatic review settings June 6, 2026 21:42
@github-actionsgithub-actionsBot 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.

CopilotAI 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 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.

FileDescription
src/coreclr/jit/knownbits.hNew KnownBits lattice + transfer helpers (And/Or/UDiv/Cast/EvalRelop) and analysis entrypoint.
src/coreclr/jit/knownbits.cppImplements VN/assertion-based KnownBits computation, including PHI merging and assertion refinement.
src/coreclr/jit/CMakeLists.txtAdds KnownBits sources/headers to the JIT build.
src/coreclr/jit/assertionprop.cppHooks KnownBits into global relop folding and cast simplification paths; widens some assertion creation gates to include TYP_LONG.

Comment threadsrc/coreclr/jit/knownbits.h Outdated
CopilotAI review requested due to automatic review settings June 7, 2026 02:20

CopilotAI 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 6 out of 6 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/jit/knownbits.h Outdated
CopilotAI review requested due to automatic review settings June 7, 2026 04:43

CopilotAI 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 6 out of 6 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/jit/knownbits.h Outdated
Comment threadsrc/coreclr/jit/assertionprop.cpp Outdated
Comment threadsrc/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>
EgorBoand 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>
CopilotAI review requested due to automatic review settings June 7, 2026 16:30

CopilotAI 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 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);
@EgorBo

Copy link
Copy Markdown
MemberAuthor

Will try to re-implement from scratch later

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 13, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR 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

@EgorBo