Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JIT: clean up unused throw helpers #93948

Closed
AndyAyersMS opened this issue Oct 24, 2023 · 4 comments · Fixed by #95379
Closed

JIT: clean up unused throw helpers #93948

AndyAyersMS opened this issue Oct 24, 2023 · 4 comments · Fixed by #95379
Assignees
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Milestone

Comments

@AndyAyersMS
Copy link
Member

#93371 deferred creation of shared throw helper blocks, but introduced more cases where throw helper blocks end up not being needed.

There's a divergence between the point that the JIT "demands" the creation of a helper (via fgAddCodeRef) and requests the helper block, and in between the JIT may optimize away the code that needed the helper.

So the fix here is either to defer or reaffirm the demands, so that they better reflect actual needs, or else allow unused helper blocks to be removed later on.

@AndyAyersMS AndyAyersMS self-assigned this Oct 24, 2023
@dotnet-issue-labeler dotnet-issue-labeler bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Oct 24, 2023
@ghost ghost added the untriaged New issue has not been triaged by the area owner label Oct 24, 2023
@AndyAyersMS AndyAyersMS added this to the 9.0.0 milestone Oct 24, 2023
@ghost
Copy link

ghost commented Oct 24, 2023

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

Issue Details

#93371 deferred creation of shared throw helper blocks, but introduced more cases where throw helper blocks end up not being needed.

There's a divergence between the point that the JIT "demands" the creation of a helper (via fgAddCodeRef) and requests the helper block, and in between the JIT may optimize away the code that needed the helper.

So the fix here is either to defer or reaffirm the demands, so that they better reflect actual needs, or else allow unused helper blocks to be removed later on.

Author: AndyAyersMS
Assignees: AndyAyersMS
Labels:

area-CodeGen-coreclr

Milestone: -

@AndyAyersMS AndyAyersMS removed the untriaged New issue has not been triaged by the area owner label Oct 24, 2023
@AndyAyersMS
Copy link
Member Author

@BruceForstall which if these do you think is most likely to work:

  • leverage stack level setter to figure out which throw helpers are likely needed, remove the ones that aren't at the end of that phase (might keep a few that end up not being needed, if codegen conditionally generates code to throw exceptions)
  • have codegen call fgAddRef for throw helper blocks it actually targets. Generate code for all the helpers like we do now. Then at the end of codegen for blocks, walk the helper list and "remove" the IGs associated with any unreferenced helpers;
  • have codegen call fgAddRef for throw helper blocks it actually targets. Instead generating code for the helpers, emit placeholder IGs. Then walk the helper list at the end of codegen and generate code for any that were actually referenced, and "remove" the ones that weren't.
  • something else

@BruceForstall
Copy link
Member

leverage stack level setter to figure out which throw helpers are likely needed

You mean, enable this for all platforms (currently it's only x86 for the throw block work) and have it do what fgAddCodeRef is doing today? Since it is walking the entire IR it can look for still-existing nodes that might need a throw helper block.

This seems reasonable. There will obviously be a TP hit for another IR walk. (Maybe it can be short-circuited by setting some global anytime we have something that might need a throw helper, and/or setting a block flag on blocks that might need a throw helper.)

have codegen call fgAddRef for throw helper blocks it actually targets. Generate code for all the helpers like we do now. Then at the end of codegen for blocks, walk the helper list and "remove" the IGs associated with any unreferenced helpers;

I'm a little confused by this one. Codegen can't create any new blocks, so I don't think this would work.

I was thinking maybe you meant morph continues calling fgAddCodeRef as today, then codegen runs and generates all the throw blocks, then we have some post-codegen pass that deletes unreferenced throw blocks (so we'd need to keep track of which blocks are unreferenced). We don't have any code today that deletes IGs, and I'm not sure we want to add any.

have codegen call fgAddRef for throw helper blocks it actually targets. Instead generating code for the helpers, emit placeholder IGs. Then walk the helper list at the end of codegen and generate code for any that were actually referenced, and "remove" the ones that weren't.

placeholder IGs are a huge pain that we should avoid adding more of.

====
Seems like doing some kind of late IR walk to add the required throw helper blocks makes the most sense. StackLevelSetter makes sense (but the name would no longer be accurate. Adding a completely separate, new phase doing another IR walk seems possibly wasteful though, however there's a comment somewhere that we shouldn't be running StackLevelSetter at all in Release on non-x86, and we don't on Mac arm64, so adding a bunch more if/ifdef might make it convoluted code).

@AndyAyersMS
Copy link
Member Author

I meant to write: codegen would call fgAddRefPred when it adds a jump to a helper, so the throw helper ref count would tell us which were used/unused. We could also just set a bit on the AddCodeDesc.

At any rate I'll look into generalizing the stack level setter.

AndyAyersMS added a commit to AndyAyersMS/runtime that referenced this issue Nov 29, 2023
Various optimizations can happen between the time the throw helper blocks
are first requested (morph) and finally used (codegen). Prune away ones
that aren't needed during the stack level setter.

Fixes dotnet#93948.
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Nov 29, 2023
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Dec 5, 2023
AndyAyersMS added a commit that referenced this issue Dec 5, 2023
Various optimizations can happen between the time the throw helper blocks
are first requested (morph) and finally used (codegen). Prune away ones
that aren't needed during the stack level setter.

Fixes #93948.
@github-actions github-actions bot locked and limited conversation to collaborators Jan 4, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants