JIT: Decouple "DoNotEnregister" from liveness - #127932

Merged
jakobbotsch merged 9 commits into
dotnet:mainfrom
jakobbotsch:decouple-liveness-dner
May 18, 2026
Merged

JIT: Decouple "DoNotEnregister" from liveness#127932
jakobbotsch merged 9 commits into
dotnet:mainfrom
jakobbotsch:decouple-liveness-dner

Conversation

@jakobbotsch

Copy link
Copy Markdown
Member

Liveness was marking locals as DNER in various places, including when it found locals to be live into EH handlers.
DNER is sticky and cannot be unset, and we call liveness multiple times, so that made things hard to reason about and led to unnecessary DNER.

This showed up for runtime async functions. Even when we were able to optimize out the try-fault clauses inserted around the body we would often still end up with lvaAsyncContinuationArg unnecessarily DNER'd because we had already marked it as DNER during a previous liveness pass, when it was live into the fault handler.

This PR:

  • Resets lvLiveInOutOfHandler on all locals every time we run liveness
  • Moves all the DNER setting from liveness to LSRA and to lowering
  • Encapsulates lvLiveInOutOfHandler into LclVarDsc::IsLiveInOutOfHandler() and adds an assert(lvTracked) to this function, so it cannot be misused
  • Introduces a few updates to heuristics to use IsLiveInOutOfHandler() in addition to DNER

Diffs aren't all that great, but I think this is a good clean up on its own.

CopilotAI review requested due to automatic review settings May 7, 2026 19:15
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 7, 2026
Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/regalloc.cpp

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 refactors CoreCLR JIT local liveness/EH handling so that EH “live-in/out-of-handler” state is recomputed each liveness run and lvDoNotEnregister (DNER) is no longer set by liveness, instead being set by regalloc / lowering.

Changes:

  • Recompute and encapsulate EH live-in/out state via LclVarDsc::IsLiveInOutOfHandler() and reset EH/must-init flags each liveness run.
  • Move DNER-setting decisions out of liveness into regalloc (checkForDNER) and lowering (lvSetEHVarsDoNotEnreg), and update heuristics to consult EH-liveness in addition to DNER.
  • Add Compiler::IsEHVarARegCandidate to centralize “EH write-thru candidate” logic and use it in multiple optimizations.

Reviewed changes

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

Show a summary per file
FileDescription
src/coreclr/jit/sideeffects.hUse IsLiveInOutOfHandler() for EH-related aliasing decisions.
src/coreclr/jit/regallocwasm.hDeclare checkForDNER for Wasm regalloc.
src/coreclr/jit/regallocwasm.cppCall checkForDNER and use encapsulated EH-live query.
src/coreclr/jit/regalloc.cppAdd checkForDNER and remove DNER-setting from isRegCandidate.
src/coreclr/jit/optimizer.cppSwitch EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/morph.cppStop copying EH-live flag during implicit-byref arg retyping.
src/coreclr/jit/lsra.hDeclare checkForDNER for LSRA.
src/coreclr/jit/lsra.cppCall checkForDNER and use IsLiveInOutOfHandler() in LSRA logic.
src/coreclr/jit/lower.cppAdd lvSetEHVarsDoNotEnreg() call to support containment heuristics in lowering.
src/coreclr/jit/liveness.cppReset lvMustInit and EH-live state each liveness run; set EH-live without setting DNER.
src/coreclr/jit/lclvars.cppAdd lvSetEHVarsDoNotEnreg; remove lvaSetVarLiveInOutOfHandler; adjust DNER behavior.
src/coreclr/jit/jiteh.cppTrack when EH clauses are removed post-liveness.
src/coreclr/jit/inductionvariableopts.cppUpdate IV widening heuristics to consider EH-liveness independently of DNER.
src/coreclr/jit/gschecks.cppRemove direct clearing of EH-live flag on shadowing locals.
src/coreclr/jit/gentree.cppAdd Compiler::IsEHVarARegCandidate helper; update EH-live checks.
src/coreclr/jit/earlyprop.cppUpdate EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/copyprop.cppAdjust “profitability” gating to compare expected enregistration status incl. EH-liveness.
src/coreclr/jit/compiler.hEncapsulate EH-live flag, add helper APIs, and add optRemovedEHClausesAfterLiveness.
src/coreclr/jit/compiler.cppUpdate enregister stats accounting to include PinningRef unconditionally.
src/coreclr/jit/codegenwasm.cppUpdate EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/codegencommon.cppUpdate EH-live checks to IsLiveInOutOfHandler().
Comments suppressed due to low confidence (1)

src/coreclr/jit/compiler.h:5734

  • optRemovedEHClausesAfterLiveness is currently only set/reset (in fgRemoveEHTableEntry and liveness) but not consumed anywhere else. If it’s meant to guard heuristics that rely on IsLiveInOutOfHandler() (e.g., avoid setting DNER based on stale EH liveness after EH removal), consider wiring it into the relevant decision points; otherwise it should be removed to avoid accumulating dead state.
 bool fgBBVarSetsInited = false;
// Track how many artificial ref counts we've added to fgEntryBB (for OSR)

Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/liveness.cpp Outdated
CopilotAI review requested due to automatic review settings May 7, 2026 19:42

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

Comment threadsrc/coreclr/jit/lower.cpp
Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/liveness.cpp Outdated
CopilotAI review requested due to automatic review settings May 8, 2026 08:19

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

Comment threadsrc/coreclr/jit/gschecks.cpp

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.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@dotnet-policy-servicedotnet-policy-serviceBot added the linkable-framework Issues associated with delivering a linker friendly framework label May 12, 2026
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Sorry for the requests, accidentally rebased across a merge here...

@jakobbotsch
jakobbotschforce-pushed the decouple-liveness-dner branch from d3d7400 to 15f6d4eCompareMay 12, 2026 13:38
@jakobbotschjakobbotsch removed the linkable-framework Issues associated with delivering a linker friendly framework label May 12, 2026
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr jitstress, runtime-coreclr libraries-jitstress

@azure-pipelines

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

@jakobbotsch
jakobbotsch marked this pull request as ready for review May 13, 2026 12:28
CopilotAI review requested due to automatic review settings May 13, 2026 12:28
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

cc @dotnet/jit-contrib PTAL @AndyAyersMS

Diffs.

This will be more important for future work once we start optimizing out IR that allows us to remove the EH we inserted for async.

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

Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/lower.cpp
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.

3 participants

@jakobbotsch@AndyAyersMS
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

JIT: Decouple "DoNotEnregister" from liveness - #127932

Merged
jakobbotsch merged 9 commits into
dotnet:mainfrom
jakobbotsch:decouple-liveness-dner
May 18, 2026
Merged

JIT: Decouple "DoNotEnregister" from liveness#127932
jakobbotsch merged 9 commits into
dotnet:mainfrom
jakobbotsch:decouple-liveness-dner

Conversation

@jakobbotsch

Copy link
Copy Markdown
Member

Liveness was marking locals as DNER in various places, including when it found locals to be live into EH handlers.
DNER is sticky and cannot be unset, and we call liveness multiple times, so that made things hard to reason about and led to unnecessary DNER.

This showed up for runtime async functions. Even when we were able to optimize out the try-fault clauses inserted around the body we would often still end up with lvaAsyncContinuationArg unnecessarily DNER'd because we had already marked it as DNER during a previous liveness pass, when it was live into the fault handler.

This PR:

  • Resets lvLiveInOutOfHandler on all locals every time we run liveness
  • Moves all the DNER setting from liveness to LSRA and to lowering
  • Encapsulates lvLiveInOutOfHandler into LclVarDsc::IsLiveInOutOfHandler() and adds an assert(lvTracked) to this function, so it cannot be misused
  • Introduces a few updates to heuristics to use IsLiveInOutOfHandler() in addition to DNER

Diffs aren't all that great, but I think this is a good clean up on its own.

CopilotAI review requested due to automatic review settings May 7, 2026 19:15
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 7, 2026
Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/regalloc.cpp

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 refactors CoreCLR JIT local liveness/EH handling so that EH “live-in/out-of-handler” state is recomputed each liveness run and lvDoNotEnregister (DNER) is no longer set by liveness, instead being set by regalloc / lowering.

Changes:

  • Recompute and encapsulate EH live-in/out state via LclVarDsc::IsLiveInOutOfHandler() and reset EH/must-init flags each liveness run.
  • Move DNER-setting decisions out of liveness into regalloc (checkForDNER) and lowering (lvSetEHVarsDoNotEnreg), and update heuristics to consult EH-liveness in addition to DNER.
  • Add Compiler::IsEHVarARegCandidate to centralize “EH write-thru candidate” logic and use it in multiple optimizations.

Reviewed changes

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

Show a summary per file
FileDescription
src/coreclr/jit/sideeffects.hUse IsLiveInOutOfHandler() for EH-related aliasing decisions.
src/coreclr/jit/regallocwasm.hDeclare checkForDNER for Wasm regalloc.
src/coreclr/jit/regallocwasm.cppCall checkForDNER and use encapsulated EH-live query.
src/coreclr/jit/regalloc.cppAdd checkForDNER and remove DNER-setting from isRegCandidate.
src/coreclr/jit/optimizer.cppSwitch EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/morph.cppStop copying EH-live flag during implicit-byref arg retyping.
src/coreclr/jit/lsra.hDeclare checkForDNER for LSRA.
src/coreclr/jit/lsra.cppCall checkForDNER and use IsLiveInOutOfHandler() in LSRA logic.
src/coreclr/jit/lower.cppAdd lvSetEHVarsDoNotEnreg() call to support containment heuristics in lowering.
src/coreclr/jit/liveness.cppReset lvMustInit and EH-live state each liveness run; set EH-live without setting DNER.
src/coreclr/jit/lclvars.cppAdd lvSetEHVarsDoNotEnreg; remove lvaSetVarLiveInOutOfHandler; adjust DNER behavior.
src/coreclr/jit/jiteh.cppTrack when EH clauses are removed post-liveness.
src/coreclr/jit/inductionvariableopts.cppUpdate IV widening heuristics to consider EH-liveness independently of DNER.
src/coreclr/jit/gschecks.cppRemove direct clearing of EH-live flag on shadowing locals.
src/coreclr/jit/gentree.cppAdd Compiler::IsEHVarARegCandidate helper; update EH-live checks.
src/coreclr/jit/earlyprop.cppUpdate EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/copyprop.cppAdjust “profitability” gating to compare expected enregistration status incl. EH-liveness.
src/coreclr/jit/compiler.hEncapsulate EH-live flag, add helper APIs, and add optRemovedEHClausesAfterLiveness.
src/coreclr/jit/compiler.cppUpdate enregister stats accounting to include PinningRef unconditionally.
src/coreclr/jit/codegenwasm.cppUpdate EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/codegencommon.cppUpdate EH-live checks to IsLiveInOutOfHandler().
Comments suppressed due to low confidence (1)

src/coreclr/jit/compiler.h:5734

  • optRemovedEHClausesAfterLiveness is currently only set/reset (in fgRemoveEHTableEntry and liveness) but not consumed anywhere else. If it’s meant to guard heuristics that rely on IsLiveInOutOfHandler() (e.g., avoid setting DNER based on stale EH liveness after EH removal), consider wiring it into the relevant decision points; otherwise it should be removed to avoid accumulating dead state.
 bool fgBBVarSetsInited = false;
// Track how many artificial ref counts we've added to fgEntryBB (for OSR)

Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/liveness.cpp Outdated
CopilotAI review requested due to automatic review settings May 7, 2026 19:42

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

Comment threadsrc/coreclr/jit/lower.cpp
Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/liveness.cpp Outdated
CopilotAI review requested due to automatic review settings May 8, 2026 08:19

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

Comment threadsrc/coreclr/jit/gschecks.cpp

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.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@dotnet-policy-servicedotnet-policy-serviceBot added the linkable-framework Issues associated with delivering a linker friendly framework label May 12, 2026
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Sorry for the requests, accidentally rebased across a merge here...

@jakobbotsch
jakobbotschforce-pushed the decouple-liveness-dner branch from d3d7400 to 15f6d4eCompareMay 12, 2026 13:38
@jakobbotschjakobbotsch removed the linkable-framework Issues associated with delivering a linker friendly framework label May 12, 2026
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr jitstress, runtime-coreclr libraries-jitstress

@azure-pipelines

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

@jakobbotsch
jakobbotsch marked this pull request as ready for review May 13, 2026 12:28
CopilotAI review requested due to automatic review settings May 13, 2026 12:28
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

cc @dotnet/jit-contrib PTAL @AndyAyersMS

Diffs.

This will be more important for future work once we start optimizing out IR that allows us to remove the EH we inserted for async.

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

Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/lower.cpp
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.

3 participants

@jakobbotsch@AndyAyersMS
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

JIT: Decouple "DoNotEnregister" from liveness - #127932

Merged
jakobbotsch merged 9 commits into
dotnet:mainfrom
jakobbotsch:decouple-liveness-dner
May 18, 2026
Merged

JIT: Decouple "DoNotEnregister" from liveness#127932
jakobbotsch merged 9 commits into
dotnet:mainfrom
jakobbotsch:decouple-liveness-dner

Conversation

@jakobbotsch

Copy link
Copy Markdown
Member

Liveness was marking locals as DNER in various places, including when it found locals to be live into EH handlers.
DNER is sticky and cannot be unset, and we call liveness multiple times, so that made things hard to reason about and led to unnecessary DNER.

This showed up for runtime async functions. Even when we were able to optimize out the try-fault clauses inserted around the body we would often still end up with lvaAsyncContinuationArg unnecessarily DNER'd because we had already marked it as DNER during a previous liveness pass, when it was live into the fault handler.

This PR:

  • Resets lvLiveInOutOfHandler on all locals every time we run liveness
  • Moves all the DNER setting from liveness to LSRA and to lowering
  • Encapsulates lvLiveInOutOfHandler into LclVarDsc::IsLiveInOutOfHandler() and adds an assert(lvTracked) to this function, so it cannot be misused
  • Introduces a few updates to heuristics to use IsLiveInOutOfHandler() in addition to DNER

Diffs aren't all that great, but I think this is a good clean up on its own.

CopilotAI review requested due to automatic review settings May 7, 2026 19:15
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 7, 2026
Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/regalloc.cpp

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 refactors CoreCLR JIT local liveness/EH handling so that EH “live-in/out-of-handler” state is recomputed each liveness run and lvDoNotEnregister (DNER) is no longer set by liveness, instead being set by regalloc / lowering.

Changes:

  • Recompute and encapsulate EH live-in/out state via LclVarDsc::IsLiveInOutOfHandler() and reset EH/must-init flags each liveness run.
  • Move DNER-setting decisions out of liveness into regalloc (checkForDNER) and lowering (lvSetEHVarsDoNotEnreg), and update heuristics to consult EH-liveness in addition to DNER.
  • Add Compiler::IsEHVarARegCandidate to centralize “EH write-thru candidate” logic and use it in multiple optimizations.

Reviewed changes

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

Show a summary per file
FileDescription
src/coreclr/jit/sideeffects.hUse IsLiveInOutOfHandler() for EH-related aliasing decisions.
src/coreclr/jit/regallocwasm.hDeclare checkForDNER for Wasm regalloc.
src/coreclr/jit/regallocwasm.cppCall checkForDNER and use encapsulated EH-live query.
src/coreclr/jit/regalloc.cppAdd checkForDNER and remove DNER-setting from isRegCandidate.
src/coreclr/jit/optimizer.cppSwitch EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/morph.cppStop copying EH-live flag during implicit-byref arg retyping.
src/coreclr/jit/lsra.hDeclare checkForDNER for LSRA.
src/coreclr/jit/lsra.cppCall checkForDNER and use IsLiveInOutOfHandler() in LSRA logic.
src/coreclr/jit/lower.cppAdd lvSetEHVarsDoNotEnreg() call to support containment heuristics in lowering.
src/coreclr/jit/liveness.cppReset lvMustInit and EH-live state each liveness run; set EH-live without setting DNER.
src/coreclr/jit/lclvars.cppAdd lvSetEHVarsDoNotEnreg; remove lvaSetVarLiveInOutOfHandler; adjust DNER behavior.
src/coreclr/jit/jiteh.cppTrack when EH clauses are removed post-liveness.
src/coreclr/jit/inductionvariableopts.cppUpdate IV widening heuristics to consider EH-liveness independently of DNER.
src/coreclr/jit/gschecks.cppRemove direct clearing of EH-live flag on shadowing locals.
src/coreclr/jit/gentree.cppAdd Compiler::IsEHVarARegCandidate helper; update EH-live checks.
src/coreclr/jit/earlyprop.cppUpdate EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/copyprop.cppAdjust “profitability” gating to compare expected enregistration status incl. EH-liveness.
src/coreclr/jit/compiler.hEncapsulate EH-live flag, add helper APIs, and add optRemovedEHClausesAfterLiveness.
src/coreclr/jit/compiler.cppUpdate enregister stats accounting to include PinningRef unconditionally.
src/coreclr/jit/codegenwasm.cppUpdate EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/codegencommon.cppUpdate EH-live checks to IsLiveInOutOfHandler().
Comments suppressed due to low confidence (1)

src/coreclr/jit/compiler.h:5734

  • optRemovedEHClausesAfterLiveness is currently only set/reset (in fgRemoveEHTableEntry and liveness) but not consumed anywhere else. If it’s meant to guard heuristics that rely on IsLiveInOutOfHandler() (e.g., avoid setting DNER based on stale EH liveness after EH removal), consider wiring it into the relevant decision points; otherwise it should be removed to avoid accumulating dead state.
 bool fgBBVarSetsInited = false;
// Track how many artificial ref counts we've added to fgEntryBB (for OSR)

Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/liveness.cpp Outdated
CopilotAI review requested due to automatic review settings May 7, 2026 19:42

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

Comment threadsrc/coreclr/jit/lower.cpp
Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/liveness.cpp Outdated
CopilotAI review requested due to automatic review settings May 8, 2026 08:19

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

Comment threadsrc/coreclr/jit/gschecks.cpp

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.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@dotnet-policy-servicedotnet-policy-serviceBot added the linkable-framework Issues associated with delivering a linker friendly framework label May 12, 2026
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Sorry for the requests, accidentally rebased across a merge here...

@jakobbotsch
jakobbotschforce-pushed the decouple-liveness-dner branch from d3d7400 to 15f6d4eCompareMay 12, 2026 13:38
@jakobbotschjakobbotsch removed the linkable-framework Issues associated with delivering a linker friendly framework label May 12, 2026
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr jitstress, runtime-coreclr libraries-jitstress

@azure-pipelines

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

@jakobbotsch
jakobbotsch marked this pull request as ready for review May 13, 2026 12:28
CopilotAI review requested due to automatic review settings May 13, 2026 12:28
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

cc @dotnet/jit-contrib PTAL @AndyAyersMS

Diffs.

This will be more important for future work once we start optimizing out IR that allows us to remove the EH we inserted for async.

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

Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/lower.cpp
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.

3 participants

@jakobbotsch@AndyAyersMS
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

JIT: Decouple "DoNotEnregister" from liveness - #127932

Merged
jakobbotsch merged 9 commits into
dotnet:mainfrom
jakobbotsch:decouple-liveness-dner
May 18, 2026
Merged

JIT: Decouple "DoNotEnregister" from liveness#127932
jakobbotsch merged 9 commits into
dotnet:mainfrom
jakobbotsch:decouple-liveness-dner

Conversation

@jakobbotsch

Copy link
Copy Markdown
Member

Liveness was marking locals as DNER in various places, including when it found locals to be live into EH handlers.
DNER is sticky and cannot be unset, and we call liveness multiple times, so that made things hard to reason about and led to unnecessary DNER.

This showed up for runtime async functions. Even when we were able to optimize out the try-fault clauses inserted around the body we would often still end up with lvaAsyncContinuationArg unnecessarily DNER'd because we had already marked it as DNER during a previous liveness pass, when it was live into the fault handler.

This PR:

  • Resets lvLiveInOutOfHandler on all locals every time we run liveness
  • Moves all the DNER setting from liveness to LSRA and to lowering
  • Encapsulates lvLiveInOutOfHandler into LclVarDsc::IsLiveInOutOfHandler() and adds an assert(lvTracked) to this function, so it cannot be misused
  • Introduces a few updates to heuristics to use IsLiveInOutOfHandler() in addition to DNER

Diffs aren't all that great, but I think this is a good clean up on its own.

CopilotAI review requested due to automatic review settings May 7, 2026 19:15
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 7, 2026
Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/regalloc.cpp

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 refactors CoreCLR JIT local liveness/EH handling so that EH “live-in/out-of-handler” state is recomputed each liveness run and lvDoNotEnregister (DNER) is no longer set by liveness, instead being set by regalloc / lowering.

Changes:

  • Recompute and encapsulate EH live-in/out state via LclVarDsc::IsLiveInOutOfHandler() and reset EH/must-init flags each liveness run.
  • Move DNER-setting decisions out of liveness into regalloc (checkForDNER) and lowering (lvSetEHVarsDoNotEnreg), and update heuristics to consult EH-liveness in addition to DNER.
  • Add Compiler::IsEHVarARegCandidate to centralize “EH write-thru candidate” logic and use it in multiple optimizations.

Reviewed changes

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

Show a summary per file
FileDescription
src/coreclr/jit/sideeffects.hUse IsLiveInOutOfHandler() for EH-related aliasing decisions.
src/coreclr/jit/regallocwasm.hDeclare checkForDNER for Wasm regalloc.
src/coreclr/jit/regallocwasm.cppCall checkForDNER and use encapsulated EH-live query.
src/coreclr/jit/regalloc.cppAdd checkForDNER and remove DNER-setting from isRegCandidate.
src/coreclr/jit/optimizer.cppSwitch EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/morph.cppStop copying EH-live flag during implicit-byref arg retyping.
src/coreclr/jit/lsra.hDeclare checkForDNER for LSRA.
src/coreclr/jit/lsra.cppCall checkForDNER and use IsLiveInOutOfHandler() in LSRA logic.
src/coreclr/jit/lower.cppAdd lvSetEHVarsDoNotEnreg() call to support containment heuristics in lowering.
src/coreclr/jit/liveness.cppReset lvMustInit and EH-live state each liveness run; set EH-live without setting DNER.
src/coreclr/jit/lclvars.cppAdd lvSetEHVarsDoNotEnreg; remove lvaSetVarLiveInOutOfHandler; adjust DNER behavior.
src/coreclr/jit/jiteh.cppTrack when EH clauses are removed post-liveness.
src/coreclr/jit/inductionvariableopts.cppUpdate IV widening heuristics to consider EH-liveness independently of DNER.
src/coreclr/jit/gschecks.cppRemove direct clearing of EH-live flag on shadowing locals.
src/coreclr/jit/gentree.cppAdd Compiler::IsEHVarARegCandidate helper; update EH-live checks.
src/coreclr/jit/earlyprop.cppUpdate EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/copyprop.cppAdjust “profitability” gating to compare expected enregistration status incl. EH-liveness.
src/coreclr/jit/compiler.hEncapsulate EH-live flag, add helper APIs, and add optRemovedEHClausesAfterLiveness.
src/coreclr/jit/compiler.cppUpdate enregister stats accounting to include PinningRef unconditionally.
src/coreclr/jit/codegenwasm.cppUpdate EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/codegencommon.cppUpdate EH-live checks to IsLiveInOutOfHandler().
Comments suppressed due to low confidence (1)

src/coreclr/jit/compiler.h:5734

  • optRemovedEHClausesAfterLiveness is currently only set/reset (in fgRemoveEHTableEntry and liveness) but not consumed anywhere else. If it’s meant to guard heuristics that rely on IsLiveInOutOfHandler() (e.g., avoid setting DNER based on stale EH liveness after EH removal), consider wiring it into the relevant decision points; otherwise it should be removed to avoid accumulating dead state.
 bool fgBBVarSetsInited = false;
// Track how many artificial ref counts we've added to fgEntryBB (for OSR)

Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/liveness.cpp Outdated
CopilotAI review requested due to automatic review settings May 7, 2026 19:42

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

Comment threadsrc/coreclr/jit/lower.cpp
Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/liveness.cpp Outdated
CopilotAI review requested due to automatic review settings May 8, 2026 08:19

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

Comment threadsrc/coreclr/jit/gschecks.cpp

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.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@dotnet-policy-servicedotnet-policy-serviceBot added the linkable-framework Issues associated with delivering a linker friendly framework label May 12, 2026
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Sorry for the requests, accidentally rebased across a merge here...

@jakobbotsch
jakobbotschforce-pushed the decouple-liveness-dner branch from d3d7400 to 15f6d4eCompareMay 12, 2026 13:38
@jakobbotschjakobbotsch removed the linkable-framework Issues associated with delivering a linker friendly framework label May 12, 2026
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr jitstress, runtime-coreclr libraries-jitstress

@azure-pipelines

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

@jakobbotsch
jakobbotsch marked this pull request as ready for review May 13, 2026 12:28
CopilotAI review requested due to automatic review settings May 13, 2026 12:28
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

cc @dotnet/jit-contrib PTAL @AndyAyersMS

Diffs.

This will be more important for future work once we start optimizing out IR that allows us to remove the EH we inserted for async.

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

Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/lower.cpp
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.

3 participants

@jakobbotsch@AndyAyersMS
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

JIT: Decouple "DoNotEnregister" from liveness - #127932

Merged
jakobbotsch merged 9 commits into
dotnet:mainfrom
jakobbotsch:decouple-liveness-dner
May 18, 2026
Merged

JIT: Decouple "DoNotEnregister" from liveness#127932
jakobbotsch merged 9 commits into
dotnet:mainfrom
jakobbotsch:decouple-liveness-dner

Conversation

@jakobbotsch

Copy link
Copy Markdown
Member

Liveness was marking locals as DNER in various places, including when it found locals to be live into EH handlers.
DNER is sticky and cannot be unset, and we call liveness multiple times, so that made things hard to reason about and led to unnecessary DNER.

This showed up for runtime async functions. Even when we were able to optimize out the try-fault clauses inserted around the body we would often still end up with lvaAsyncContinuationArg unnecessarily DNER'd because we had already marked it as DNER during a previous liveness pass, when it was live into the fault handler.

This PR:

  • Resets lvLiveInOutOfHandler on all locals every time we run liveness
  • Moves all the DNER setting from liveness to LSRA and to lowering
  • Encapsulates lvLiveInOutOfHandler into LclVarDsc::IsLiveInOutOfHandler() and adds an assert(lvTracked) to this function, so it cannot be misused
  • Introduces a few updates to heuristics to use IsLiveInOutOfHandler() in addition to DNER

Diffs aren't all that great, but I think this is a good clean up on its own.

CopilotAI review requested due to automatic review settings May 7, 2026 19:15
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 7, 2026
Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/regalloc.cpp

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 refactors CoreCLR JIT local liveness/EH handling so that EH “live-in/out-of-handler” state is recomputed each liveness run and lvDoNotEnregister (DNER) is no longer set by liveness, instead being set by regalloc / lowering.

Changes:

  • Recompute and encapsulate EH live-in/out state via LclVarDsc::IsLiveInOutOfHandler() and reset EH/must-init flags each liveness run.
  • Move DNER-setting decisions out of liveness into regalloc (checkForDNER) and lowering (lvSetEHVarsDoNotEnreg), and update heuristics to consult EH-liveness in addition to DNER.
  • Add Compiler::IsEHVarARegCandidate to centralize “EH write-thru candidate” logic and use it in multiple optimizations.

Reviewed changes

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

Show a summary per file
FileDescription
src/coreclr/jit/sideeffects.hUse IsLiveInOutOfHandler() for EH-related aliasing decisions.
src/coreclr/jit/regallocwasm.hDeclare checkForDNER for Wasm regalloc.
src/coreclr/jit/regallocwasm.cppCall checkForDNER and use encapsulated EH-live query.
src/coreclr/jit/regalloc.cppAdd checkForDNER and remove DNER-setting from isRegCandidate.
src/coreclr/jit/optimizer.cppSwitch EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/morph.cppStop copying EH-live flag during implicit-byref arg retyping.
src/coreclr/jit/lsra.hDeclare checkForDNER for LSRA.
src/coreclr/jit/lsra.cppCall checkForDNER and use IsLiveInOutOfHandler() in LSRA logic.
src/coreclr/jit/lower.cppAdd lvSetEHVarsDoNotEnreg() call to support containment heuristics in lowering.
src/coreclr/jit/liveness.cppReset lvMustInit and EH-live state each liveness run; set EH-live without setting DNER.
src/coreclr/jit/lclvars.cppAdd lvSetEHVarsDoNotEnreg; remove lvaSetVarLiveInOutOfHandler; adjust DNER behavior.
src/coreclr/jit/jiteh.cppTrack when EH clauses are removed post-liveness.
src/coreclr/jit/inductionvariableopts.cppUpdate IV widening heuristics to consider EH-liveness independently of DNER.
src/coreclr/jit/gschecks.cppRemove direct clearing of EH-live flag on shadowing locals.
src/coreclr/jit/gentree.cppAdd Compiler::IsEHVarARegCandidate helper; update EH-live checks.
src/coreclr/jit/earlyprop.cppUpdate EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/copyprop.cppAdjust “profitability” gating to compare expected enregistration status incl. EH-liveness.
src/coreclr/jit/compiler.hEncapsulate EH-live flag, add helper APIs, and add optRemovedEHClausesAfterLiveness.
src/coreclr/jit/compiler.cppUpdate enregister stats accounting to include PinningRef unconditionally.
src/coreclr/jit/codegenwasm.cppUpdate EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/codegencommon.cppUpdate EH-live checks to IsLiveInOutOfHandler().
Comments suppressed due to low confidence (1)

src/coreclr/jit/compiler.h:5734

  • optRemovedEHClausesAfterLiveness is currently only set/reset (in fgRemoveEHTableEntry and liveness) but not consumed anywhere else. If it’s meant to guard heuristics that rely on IsLiveInOutOfHandler() (e.g., avoid setting DNER based on stale EH liveness after EH removal), consider wiring it into the relevant decision points; otherwise it should be removed to avoid accumulating dead state.
 bool fgBBVarSetsInited = false;
// Track how many artificial ref counts we've added to fgEntryBB (for OSR)

Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/liveness.cpp Outdated
CopilotAI review requested due to automatic review settings May 7, 2026 19:42

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

Comment threadsrc/coreclr/jit/lower.cpp
Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/liveness.cpp Outdated
CopilotAI review requested due to automatic review settings May 8, 2026 08:19

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

Comment threadsrc/coreclr/jit/gschecks.cpp

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.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@dotnet-policy-servicedotnet-policy-serviceBot added the linkable-framework Issues associated with delivering a linker friendly framework label May 12, 2026
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Sorry for the requests, accidentally rebased across a merge here...

@jakobbotsch
jakobbotschforce-pushed the decouple-liveness-dner branch from d3d7400 to 15f6d4eCompareMay 12, 2026 13:38
@jakobbotschjakobbotsch removed the linkable-framework Issues associated with delivering a linker friendly framework label May 12, 2026
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr jitstress, runtime-coreclr libraries-jitstress

@azure-pipelines

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

@jakobbotsch
jakobbotsch marked this pull request as ready for review May 13, 2026 12:28
CopilotAI review requested due to automatic review settings May 13, 2026 12:28
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

cc @dotnet/jit-contrib PTAL @AndyAyersMS

Diffs.

This will be more important for future work once we start optimizing out IR that allows us to remove the EH we inserted for async.

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

Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/lower.cpp
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.

3 participants

@jakobbotsch@AndyAyersMS
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

JIT: Decouple "DoNotEnregister" from liveness - #127932

Merged
jakobbotsch merged 9 commits into
dotnet:mainfrom
jakobbotsch:decouple-liveness-dner
May 18, 2026
Merged

JIT: Decouple "DoNotEnregister" from liveness#127932
jakobbotsch merged 9 commits into
dotnet:mainfrom
jakobbotsch:decouple-liveness-dner

Conversation

@jakobbotsch

Copy link
Copy Markdown
Member

Liveness was marking locals as DNER in various places, including when it found locals to be live into EH handlers.
DNER is sticky and cannot be unset, and we call liveness multiple times, so that made things hard to reason about and led to unnecessary DNER.

This showed up for runtime async functions. Even when we were able to optimize out the try-fault clauses inserted around the body we would often still end up with lvaAsyncContinuationArg unnecessarily DNER'd because we had already marked it as DNER during a previous liveness pass, when it was live into the fault handler.

This PR:

  • Resets lvLiveInOutOfHandler on all locals every time we run liveness
  • Moves all the DNER setting from liveness to LSRA and to lowering
  • Encapsulates lvLiveInOutOfHandler into LclVarDsc::IsLiveInOutOfHandler() and adds an assert(lvTracked) to this function, so it cannot be misused
  • Introduces a few updates to heuristics to use IsLiveInOutOfHandler() in addition to DNER

Diffs aren't all that great, but I think this is a good clean up on its own.

CopilotAI review requested due to automatic review settings May 7, 2026 19:15
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 7, 2026
Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/regalloc.cpp

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 refactors CoreCLR JIT local liveness/EH handling so that EH “live-in/out-of-handler” state is recomputed each liveness run and lvDoNotEnregister (DNER) is no longer set by liveness, instead being set by regalloc / lowering.

Changes:

  • Recompute and encapsulate EH live-in/out state via LclVarDsc::IsLiveInOutOfHandler() and reset EH/must-init flags each liveness run.
  • Move DNER-setting decisions out of liveness into regalloc (checkForDNER) and lowering (lvSetEHVarsDoNotEnreg), and update heuristics to consult EH-liveness in addition to DNER.
  • Add Compiler::IsEHVarARegCandidate to centralize “EH write-thru candidate” logic and use it in multiple optimizations.

Reviewed changes

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

Show a summary per file
FileDescription
src/coreclr/jit/sideeffects.hUse IsLiveInOutOfHandler() for EH-related aliasing decisions.
src/coreclr/jit/regallocwasm.hDeclare checkForDNER for Wasm regalloc.
src/coreclr/jit/regallocwasm.cppCall checkForDNER and use encapsulated EH-live query.
src/coreclr/jit/regalloc.cppAdd checkForDNER and remove DNER-setting from isRegCandidate.
src/coreclr/jit/optimizer.cppSwitch EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/morph.cppStop copying EH-live flag during implicit-byref arg retyping.
src/coreclr/jit/lsra.hDeclare checkForDNER for LSRA.
src/coreclr/jit/lsra.cppCall checkForDNER and use IsLiveInOutOfHandler() in LSRA logic.
src/coreclr/jit/lower.cppAdd lvSetEHVarsDoNotEnreg() call to support containment heuristics in lowering.
src/coreclr/jit/liveness.cppReset lvMustInit and EH-live state each liveness run; set EH-live without setting DNER.
src/coreclr/jit/lclvars.cppAdd lvSetEHVarsDoNotEnreg; remove lvaSetVarLiveInOutOfHandler; adjust DNER behavior.
src/coreclr/jit/jiteh.cppTrack when EH clauses are removed post-liveness.
src/coreclr/jit/inductionvariableopts.cppUpdate IV widening heuristics to consider EH-liveness independently of DNER.
src/coreclr/jit/gschecks.cppRemove direct clearing of EH-live flag on shadowing locals.
src/coreclr/jit/gentree.cppAdd Compiler::IsEHVarARegCandidate helper; update EH-live checks.
src/coreclr/jit/earlyprop.cppUpdate EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/copyprop.cppAdjust “profitability” gating to compare expected enregistration status incl. EH-liveness.
src/coreclr/jit/compiler.hEncapsulate EH-live flag, add helper APIs, and add optRemovedEHClausesAfterLiveness.
src/coreclr/jit/compiler.cppUpdate enregister stats accounting to include PinningRef unconditionally.
src/coreclr/jit/codegenwasm.cppUpdate EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/codegencommon.cppUpdate EH-live checks to IsLiveInOutOfHandler().
Comments suppressed due to low confidence (1)

src/coreclr/jit/compiler.h:5734

  • optRemovedEHClausesAfterLiveness is currently only set/reset (in fgRemoveEHTableEntry and liveness) but not consumed anywhere else. If it’s meant to guard heuristics that rely on IsLiveInOutOfHandler() (e.g., avoid setting DNER based on stale EH liveness after EH removal), consider wiring it into the relevant decision points; otherwise it should be removed to avoid accumulating dead state.
 bool fgBBVarSetsInited = false;
// Track how many artificial ref counts we've added to fgEntryBB (for OSR)

Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/liveness.cpp Outdated
CopilotAI review requested due to automatic review settings May 7, 2026 19:42

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

Comment threadsrc/coreclr/jit/lower.cpp
Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/liveness.cpp Outdated
CopilotAI review requested due to automatic review settings May 8, 2026 08:19

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

Comment threadsrc/coreclr/jit/gschecks.cpp

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.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@dotnet-policy-servicedotnet-policy-serviceBot added the linkable-framework Issues associated with delivering a linker friendly framework label May 12, 2026
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Sorry for the requests, accidentally rebased across a merge here...

@jakobbotsch
jakobbotschforce-pushed the decouple-liveness-dner branch from d3d7400 to 15f6d4eCompareMay 12, 2026 13:38
@jakobbotschjakobbotsch removed the linkable-framework Issues associated with delivering a linker friendly framework label May 12, 2026
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr jitstress, runtime-coreclr libraries-jitstress

@azure-pipelines

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

@jakobbotsch
jakobbotsch marked this pull request as ready for review May 13, 2026 12:28
CopilotAI review requested due to automatic review settings May 13, 2026 12:28
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

cc @dotnet/jit-contrib PTAL @AndyAyersMS

Diffs.

This will be more important for future work once we start optimizing out IR that allows us to remove the EH we inserted for async.

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

Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/lower.cpp
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.

3 participants

@jakobbotsch@AndyAyersMS
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

JIT: Decouple "DoNotEnregister" from liveness - #127932

Merged
jakobbotsch merged 9 commits into
dotnet:mainfrom
jakobbotsch:decouple-liveness-dner
May 18, 2026
Merged

JIT: Decouple "DoNotEnregister" from liveness#127932
jakobbotsch merged 9 commits into
dotnet:mainfrom
jakobbotsch:decouple-liveness-dner

Conversation

@jakobbotsch

Copy link
Copy Markdown
Member

Liveness was marking locals as DNER in various places, including when it found locals to be live into EH handlers.
DNER is sticky and cannot be unset, and we call liveness multiple times, so that made things hard to reason about and led to unnecessary DNER.

This showed up for runtime async functions. Even when we were able to optimize out the try-fault clauses inserted around the body we would often still end up with lvaAsyncContinuationArg unnecessarily DNER'd because we had already marked it as DNER during a previous liveness pass, when it was live into the fault handler.

This PR:

  • Resets lvLiveInOutOfHandler on all locals every time we run liveness
  • Moves all the DNER setting from liveness to LSRA and to lowering
  • Encapsulates lvLiveInOutOfHandler into LclVarDsc::IsLiveInOutOfHandler() and adds an assert(lvTracked) to this function, so it cannot be misused
  • Introduces a few updates to heuristics to use IsLiveInOutOfHandler() in addition to DNER

Diffs aren't all that great, but I think this is a good clean up on its own.

CopilotAI review requested due to automatic review settings May 7, 2026 19:15
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 7, 2026
Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/regalloc.cpp

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 refactors CoreCLR JIT local liveness/EH handling so that EH “live-in/out-of-handler” state is recomputed each liveness run and lvDoNotEnregister (DNER) is no longer set by liveness, instead being set by regalloc / lowering.

Changes:

  • Recompute and encapsulate EH live-in/out state via LclVarDsc::IsLiveInOutOfHandler() and reset EH/must-init flags each liveness run.
  • Move DNER-setting decisions out of liveness into regalloc (checkForDNER) and lowering (lvSetEHVarsDoNotEnreg), and update heuristics to consult EH-liveness in addition to DNER.
  • Add Compiler::IsEHVarARegCandidate to centralize “EH write-thru candidate” logic and use it in multiple optimizations.

Reviewed changes

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

Show a summary per file
FileDescription
src/coreclr/jit/sideeffects.hUse IsLiveInOutOfHandler() for EH-related aliasing decisions.
src/coreclr/jit/regallocwasm.hDeclare checkForDNER for Wasm regalloc.
src/coreclr/jit/regallocwasm.cppCall checkForDNER and use encapsulated EH-live query.
src/coreclr/jit/regalloc.cppAdd checkForDNER and remove DNER-setting from isRegCandidate.
src/coreclr/jit/optimizer.cppSwitch EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/morph.cppStop copying EH-live flag during implicit-byref arg retyping.
src/coreclr/jit/lsra.hDeclare checkForDNER for LSRA.
src/coreclr/jit/lsra.cppCall checkForDNER and use IsLiveInOutOfHandler() in LSRA logic.
src/coreclr/jit/lower.cppAdd lvSetEHVarsDoNotEnreg() call to support containment heuristics in lowering.
src/coreclr/jit/liveness.cppReset lvMustInit and EH-live state each liveness run; set EH-live without setting DNER.
src/coreclr/jit/lclvars.cppAdd lvSetEHVarsDoNotEnreg; remove lvaSetVarLiveInOutOfHandler; adjust DNER behavior.
src/coreclr/jit/jiteh.cppTrack when EH clauses are removed post-liveness.
src/coreclr/jit/inductionvariableopts.cppUpdate IV widening heuristics to consider EH-liveness independently of DNER.
src/coreclr/jit/gschecks.cppRemove direct clearing of EH-live flag on shadowing locals.
src/coreclr/jit/gentree.cppAdd Compiler::IsEHVarARegCandidate helper; update EH-live checks.
src/coreclr/jit/earlyprop.cppUpdate EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/copyprop.cppAdjust “profitability” gating to compare expected enregistration status incl. EH-liveness.
src/coreclr/jit/compiler.hEncapsulate EH-live flag, add helper APIs, and add optRemovedEHClausesAfterLiveness.
src/coreclr/jit/compiler.cppUpdate enregister stats accounting to include PinningRef unconditionally.
src/coreclr/jit/codegenwasm.cppUpdate EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/codegencommon.cppUpdate EH-live checks to IsLiveInOutOfHandler().
Comments suppressed due to low confidence (1)

src/coreclr/jit/compiler.h:5734

  • optRemovedEHClausesAfterLiveness is currently only set/reset (in fgRemoveEHTableEntry and liveness) but not consumed anywhere else. If it’s meant to guard heuristics that rely on IsLiveInOutOfHandler() (e.g., avoid setting DNER based on stale EH liveness after EH removal), consider wiring it into the relevant decision points; otherwise it should be removed to avoid accumulating dead state.
 bool fgBBVarSetsInited = false;
// Track how many artificial ref counts we've added to fgEntryBB (for OSR)

Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/liveness.cpp Outdated
CopilotAI review requested due to automatic review settings May 7, 2026 19:42

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

Comment threadsrc/coreclr/jit/lower.cpp
Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/liveness.cpp Outdated
CopilotAI review requested due to automatic review settings May 8, 2026 08:19

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

Comment threadsrc/coreclr/jit/gschecks.cpp

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.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@dotnet-policy-servicedotnet-policy-serviceBot added the linkable-framework Issues associated with delivering a linker friendly framework label May 12, 2026
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Sorry for the requests, accidentally rebased across a merge here...

@jakobbotsch
jakobbotschforce-pushed the decouple-liveness-dner branch from d3d7400 to 15f6d4eCompareMay 12, 2026 13:38
@jakobbotschjakobbotsch removed the linkable-framework Issues associated with delivering a linker friendly framework label May 12, 2026
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr jitstress, runtime-coreclr libraries-jitstress

@azure-pipelines

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

@jakobbotsch
jakobbotsch marked this pull request as ready for review May 13, 2026 12:28
CopilotAI review requested due to automatic review settings May 13, 2026 12:28
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

cc @dotnet/jit-contrib PTAL @AndyAyersMS

Diffs.

This will be more important for future work once we start optimizing out IR that allows us to remove the EH we inserted for async.

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

Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/lower.cpp
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.

3 participants

@jakobbotsch@AndyAyersMS
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

JIT: Decouple "DoNotEnregister" from liveness - #127932

Merged
jakobbotsch merged 9 commits into
dotnet:mainfrom
jakobbotsch:decouple-liveness-dner
May 18, 2026
Merged

JIT: Decouple "DoNotEnregister" from liveness#127932
jakobbotsch merged 9 commits into
dotnet:mainfrom
jakobbotsch:decouple-liveness-dner

Conversation

@jakobbotsch

Copy link
Copy Markdown
Member

Liveness was marking locals as DNER in various places, including when it found locals to be live into EH handlers.
DNER is sticky and cannot be unset, and we call liveness multiple times, so that made things hard to reason about and led to unnecessary DNER.

This showed up for runtime async functions. Even when we were able to optimize out the try-fault clauses inserted around the body we would often still end up with lvaAsyncContinuationArg unnecessarily DNER'd because we had already marked it as DNER during a previous liveness pass, when it was live into the fault handler.

This PR:

  • Resets lvLiveInOutOfHandler on all locals every time we run liveness
  • Moves all the DNER setting from liveness to LSRA and to lowering
  • Encapsulates lvLiveInOutOfHandler into LclVarDsc::IsLiveInOutOfHandler() and adds an assert(lvTracked) to this function, so it cannot be misused
  • Introduces a few updates to heuristics to use IsLiveInOutOfHandler() in addition to DNER

Diffs aren't all that great, but I think this is a good clean up on its own.

CopilotAI review requested due to automatic review settings May 7, 2026 19:15
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 7, 2026
Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/regalloc.cpp

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 refactors CoreCLR JIT local liveness/EH handling so that EH “live-in/out-of-handler” state is recomputed each liveness run and lvDoNotEnregister (DNER) is no longer set by liveness, instead being set by regalloc / lowering.

Changes:

  • Recompute and encapsulate EH live-in/out state via LclVarDsc::IsLiveInOutOfHandler() and reset EH/must-init flags each liveness run.
  • Move DNER-setting decisions out of liveness into regalloc (checkForDNER) and lowering (lvSetEHVarsDoNotEnreg), and update heuristics to consult EH-liveness in addition to DNER.
  • Add Compiler::IsEHVarARegCandidate to centralize “EH write-thru candidate” logic and use it in multiple optimizations.

Reviewed changes

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

Show a summary per file
FileDescription
src/coreclr/jit/sideeffects.hUse IsLiveInOutOfHandler() for EH-related aliasing decisions.
src/coreclr/jit/regallocwasm.hDeclare checkForDNER for Wasm regalloc.
src/coreclr/jit/regallocwasm.cppCall checkForDNER and use encapsulated EH-live query.
src/coreclr/jit/regalloc.cppAdd checkForDNER and remove DNER-setting from isRegCandidate.
src/coreclr/jit/optimizer.cppSwitch EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/morph.cppStop copying EH-live flag during implicit-byref arg retyping.
src/coreclr/jit/lsra.hDeclare checkForDNER for LSRA.
src/coreclr/jit/lsra.cppCall checkForDNER and use IsLiveInOutOfHandler() in LSRA logic.
src/coreclr/jit/lower.cppAdd lvSetEHVarsDoNotEnreg() call to support containment heuristics in lowering.
src/coreclr/jit/liveness.cppReset lvMustInit and EH-live state each liveness run; set EH-live without setting DNER.
src/coreclr/jit/lclvars.cppAdd lvSetEHVarsDoNotEnreg; remove lvaSetVarLiveInOutOfHandler; adjust DNER behavior.
src/coreclr/jit/jiteh.cppTrack when EH clauses are removed post-liveness.
src/coreclr/jit/inductionvariableopts.cppUpdate IV widening heuristics to consider EH-liveness independently of DNER.
src/coreclr/jit/gschecks.cppRemove direct clearing of EH-live flag on shadowing locals.
src/coreclr/jit/gentree.cppAdd Compiler::IsEHVarARegCandidate helper; update EH-live checks.
src/coreclr/jit/earlyprop.cppUpdate EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/copyprop.cppAdjust “profitability” gating to compare expected enregistration status incl. EH-liveness.
src/coreclr/jit/compiler.hEncapsulate EH-live flag, add helper APIs, and add optRemovedEHClausesAfterLiveness.
src/coreclr/jit/compiler.cppUpdate enregister stats accounting to include PinningRef unconditionally.
src/coreclr/jit/codegenwasm.cppUpdate EH-live checks to IsLiveInOutOfHandler().
src/coreclr/jit/codegencommon.cppUpdate EH-live checks to IsLiveInOutOfHandler().
Comments suppressed due to low confidence (1)

src/coreclr/jit/compiler.h:5734

  • optRemovedEHClausesAfterLiveness is currently only set/reset (in fgRemoveEHTableEntry and liveness) but not consumed anywhere else. If it’s meant to guard heuristics that rely on IsLiveInOutOfHandler() (e.g., avoid setting DNER based on stale EH liveness after EH removal), consider wiring it into the relevant decision points; otherwise it should be removed to avoid accumulating dead state.
 bool fgBBVarSetsInited = false;
// Track how many artificial ref counts we've added to fgEntryBB (for OSR)

Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/liveness.cpp Outdated
CopilotAI review requested due to automatic review settings May 7, 2026 19:42

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

Comment threadsrc/coreclr/jit/lower.cpp
Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/liveness.cpp Outdated
CopilotAI review requested due to automatic review settings May 8, 2026 08:19

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

Comment threadsrc/coreclr/jit/gschecks.cpp

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.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@dotnet-policy-servicedotnet-policy-serviceBot added the linkable-framework Issues associated with delivering a linker friendly framework label May 12, 2026
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Sorry for the requests, accidentally rebased across a merge here...

@jakobbotsch
jakobbotschforce-pushed the decouple-liveness-dner branch from d3d7400 to 15f6d4eCompareMay 12, 2026 13:38
@jakobbotschjakobbotsch removed the linkable-framework Issues associated with delivering a linker friendly framework label May 12, 2026
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr jitstress, runtime-coreclr libraries-jitstress

@azure-pipelines

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

@jakobbotsch
jakobbotsch marked this pull request as ready for review May 13, 2026 12:28
CopilotAI review requested due to automatic review settings May 13, 2026 12:28
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

cc @dotnet/jit-contrib PTAL @AndyAyersMS

Diffs.

This will be more important for future work once we start optimizing out IR that allows us to remove the EH we inserted for async.

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

Comment threadsrc/coreclr/jit/lclvars.cpp
Comment threadsrc/coreclr/jit/lower.cpp
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.

3 participants

@jakobbotsch@AndyAyersMS