Skip to content

JIT: Stop treating GT_LCLHEAP as inherently exceptional#125362

Open
Copilot wants to merge 7 commits intomainfrom
copilot/remove-gt-lclheap-node-unused
Open

JIT: Stop treating GT_LCLHEAP as inherently exceptional#125362
Copilot wants to merge 7 commits intomainfrom
copilot/remove-gt-lclheap-node-unused

Conversation

Copy link
Contributor

Copilot AI commented Mar 10, 2026

Description

GT_LCLHEAP was previously marked as inherently exception-producing via GTF_EXCEPT in the importer, and OperExceptions also reported StackOverflowException for it. Based on review feedback, this change removes that special exception treatment instead of trying to delete GT_LCLHEAP nodes in liveness.

Changes

  • importer.cpp — Stopped marking imported GT_LCLHEAP nodes with GTF_EXCEPT. The node still gets GTF_DONT_CSE.

  • gentree.cpp — Removed the GT_LCLHEAP case from GenTree::OperExceptions, so it no longer reports StackOverflowException as an inherent exception side effect.

  • liveness.cpp — Reverted the earlier liveness-specific dead-code-elimination handling for GT_LCLHEAP.

  • morph.cpp — Updated the call-argument reordering logic to check for GT_LCLHEAP explicitly in the places where its stack-depth behavior still matters, rather than relying on GTF_EXCEPT.

  • Behavioral intentGT_LCLHEAP is no longer treated as inherently exceptional solely because it may grow the stack. Any exception-related behavior now comes from propagated operand flags rather than special casing on the node itself.

Testing

  • ./build.sh clr.jit -rc release
  • ./build.sh libs -rc release -lc release
  • src/tests/build.sh -Test JIT/Directed/localloc/localloc3_cs_r.csproj x64 Release -priority1

Focused validation succeeded for the affected JIT and localloc test build path.


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

Copilot AI and others added 2 commits March 10, 2026 04:49
If the GT_LCLHEAP node's value is unused (no consumer in LIR),
remove the node and mark its size arg as unused so it is still
evaluated for side effects. This works even when the length is
not a constant.

Co-authored-by: EgorBo <523221+EgorBo@users.noreply.github.com>
…oval

- Change LowerLclHeap from void to GenTree* return type to correctly
  communicate the next node for the lowering loop
- Save node->gtNext before removing the node when value is unused,
  since Remove() sets gtNext to nullptr
- Also convert all internal early returns to return node->gtNext
- Update the GT_LCLHEAP case in LowerNode to use 'return LowerLclHeap(node)'

Co-authored-by: EgorBo <523221+EgorBo@users.noreply.github.com>
Copilot AI changed the title [WIP] Remove unused GT_LCLHEAP node and set arg JIT: Remove unused GT_LCLHEAP node in LowerLclHeap Mar 10, 2026
@jakobbotsch
Copy link
Member

Doesn't liveness remove these?

@EgorBo
Copy link
Member

EgorBo commented Mar 10, 2026

Doesn't liveness remove these?

given it produces diffs - it doesn't?

@copilot please fix liveness to delete unused LCLHEAP nodes instead.

Co-authored-by: EgorBo <523221+EgorBo@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 10, 2026

Doesn't liveness remove these?

Yes. I moved the removal out of lowering and into liveness in 6456523, so unused GT_LCLHEAP nodes are now deleted during DCE and their size operand is marked unused there.

Doesn't liveness remove these?

given it produces diffs - it doesn't?
...

Updated in 6456523. LowerLclHeap is back to its original behavior, and liveness now removes unused GT_LCLHEAP nodes via DCE while marking the size operand unused so any side effects are preserved.

Copilot AI changed the title JIT: Remove unused GT_LCLHEAP node in LowerLclHeap JIT: Remove unused GT_LCLHEAP node in liveness Mar 10, 2026
@jakobbotsch
Copy link
Member

I think the real problem is that we mark GT_LCLHEAP with GTF_EXCEPT. GTF_EXCEPT nodes cannot be removed by liveness.

It feels inconsistent to be deleting them anyway. If we think we can do that, then we should probably stop marking them with GTF_EXCEPT.

@jakobbotsch
Copy link
Member

jakobbotsch commented Mar 10, 2026

But it is not clear that is valid -- stackalloc int[-1] is probably expected to throw something? So perhaps the best we can do is transform to a non-negative check on the length.

Edit: well actually, localloc IL instruction takes an unsigned integer. So removing entirely is probably ok.

@vcsjones vcsjones added area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI and removed area-System.Security labels Mar 10, 2026
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@EgorBo
Copy link
Member

EgorBo commented Mar 10, 2026

@copilot please revert the changes, just remove GTF_EXCEPT from LCLHEAP in importer (unless its argument propagates it). Remove it from OperExceptions. Check everywhere, we can assume StackOverflow is not a side-effect we care about.

Co-authored-by: EgorBo <523221+EgorBo@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 10, 2026

I think the real problem is that we mark GT_LCLHEAP with GTF_EXCEPT. GTF_EXCEPT nodes cannot be removed by liveness.

It feels inconsistent to be deleting them anyway. If we think we can do th...

Agreed. I changed the implementation in c59b003 to stop treating GT_LCLHEAP as inherently exceptional instead of deleting it specially in liveness. The liveness change is reverted, importer no longer sets GTF_EXCEPT, and OperExceptions no longer reports StackOverflowException for GT_LCLHEAP.

But it is not clear that is valid -- stackalloc int[-1] is probably expected to throw something? So perhaps the best we can do is transform to a non-negative check on the length.

Edit: well actu...

Went with that simpler direction in c59b003. Since localloc takes an unsigned size and we’re no longer modeling stack overflow here as an exception side effect, GT_LCLHEAP now just stops carrying the inherent GTF_EXCEPT/OperExceptions behavior.

@copilot please revert the changes, just remove GTF_EXCEPT from LCLHEAP in importer (unless its argument propagates it). Remove it from OperExceptions. Check everywhere, we can assume StackOve...

Done in c59b003. I reverted the liveness-specific removal, removed the importer-side GTF_EXCEPT from GT_LCLHEAP, dropped its OperExceptions entry, and updated the morph-side reordering logic to check for GT_LCLHEAP explicitly where it still matters.

Copilot AI changed the title JIT: Remove unused GT_LCLHEAP node in liveness JIT: Stop treating GT_LCLHEAP as inherently exceptional Mar 10, 2026
@EgorBo
Copy link
Member

EgorBo commented Mar 10, 2026

PTAL @jakobbotsch @dotnet/jit-contrib Diffs

I think it also fixes an existing CQ github issue I had in my bookmarks, but I can't find it.

Copy link
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

Updates CoreCLR JIT handling of GT_LCLHEAP (localloc) so it’s no longer treated as inherently exception-producing, and adjusts argument reordering logic to account for GT_LCLHEAP explicitly rather than via GTF_EXCEPT.

Changes:

  • Stop setting GTF_EXCEPT on imported GT_LCLHEAP nodes (while keeping GTF_DONT_CSE).
  • Remove GT_LCLHEAP from GenTree::OperExceptions so it no longer reports StackOverflowException as an inherent exception.
  • Update call-argument reordering constraints to explicitly detect GT_LCLHEAP in argument trees.

Reviewed changes

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

File Description
src/coreclr/jit/importer.cpp Removes GTF_EXCEPT from imported GT_LCLHEAP while preserving GTF_DONT_CSE.
src/coreclr/jit/gentree.cpp Removes inherent StackOverflowException reporting for GT_LCLHEAP in OperExceptions.
src/coreclr/jit/morph.cpp Makes argument reordering constraints explicitly detect GT_LCLHEAP rather than relying on GTF_EXCEPT.
src/coreclr/jit/lower.cpp Fixes parameter name in LowerLclHeap comment to match the function signature.

EgorBo and others added 2 commits March 10, 2026 19:29
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
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.

5 participants