-
Notifications
You must be signed in to change notification settings - Fork 5.2k
JIT: Improve interference checks for thrown exceptions and enable CSE/hoisting of GVM resolution helpers #122017
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
base: main
Are you sure you want to change the base?
Conversation
- Introduce `ExceptionSetFlags::UnknownException`. This special value marks that an operation may throw an exception that we cannot say anything about. Consumers of flags must be specially aware about this exception type. - Make `GenTree::OperExceptions` callable on all trees by changing arbitrary user calls to return the new `UnknownException` type. - Switch `OperMayThrow` to be literally `OperExceptions() != None` - Enhance precision about exceptions thrown by helper calls. Instead of just modelling "may throw" and "may not throw", we model the exact exceptions a helper may throw via `ExceptionSetFlags`. - Add helper call properties for `CORINFO_HELP_VIRTUAL_FUNC_PTR`, `CORINFO_HELP_GVMLOOKUP_FOR_SLOT`, `CORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTR`. These do not mutate the heap and we use the new mechanism above to indicate that the only exception they can throw is NRE. They are also pure, so add a VN function so VN can model them. - Update `SideEffectSet` to track and precisely handle interference for exceptions. We can now reorder two operations if we know they can only throw the exact same exception. - Generalize `OptimizeCallIndirectTargetEvaluation`; manual interference handling is no longer necessary, and we can use it for all calls.
|
cc @dotnet/jit-contrib PTAL @AndyAyersMS @EgorBo Diffs. On xarch this allows more containment of indirections, and on all platforms it allows us to CSE/hoist GVM resolution helpers (most of the diffs of that comes from tests). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR improves the JIT's ability to optimize GVM (Generic Virtual Method) resolution helpers by introducing more precise exception tracking and enabling CSE/hoisting optimizations.
Key changes:
- Introduces
ExceptionSetFlags::UnknownExceptionto model operations with unknown exception types - Extends exception modeling to all helper calls with precise exception sets instead of just "may throw" vs "may not throw"
- Marks
CORINFO_HELP_VIRTUAL_FUNC_PTR,CORINFO_HELP_GVMLOOKUP_FOR_SLOT, andCORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTRas pure with only NRE exceptions, enabling CSE/hoisting
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/coreclr/jit/valuenumfuncs.h | Adds VN function definitions for the three GVM resolution helpers |
| src/coreclr/jit/valuenum.cpp | Implements VN function handling and precise NRE exception modeling for GVM helpers; refactors fgValueNumberIndirNullCheckExceptions for reuse |
| src/coreclr/jit/utils.h | Moves ExceptionSetFlags enum and adds UnknownException value; updates HelperCallProperties to track precise exceptions |
| src/coreclr/jit/utils.cpp | Updates helper property initialization to use ExceptionSetFlags; marks GVM helpers as pure with NRE only |
| src/coreclr/jit/sideeffects.h | Adds m_preciseExceptions field to track precise exception sets |
| src/coreclr/jit/sideeffects.cpp | Implements precise exception interference checking - allows reordering when both sides throw the exact same single exception |
| src/coreclr/jit/morph.cpp | Swaps argument order to match new helper signature; updates exception interference checks for unknown exceptions |
| src/coreclr/jit/lower.cpp | Generalizes OptimizeCallIndirectTargetEvaluation to work with any call target; removes manual NRE handling now handled by SideEffectSet |
| src/coreclr/jit/gentree.h | Updates OperEffects signature to output precise exceptions; removes duplicate ExceptionSetFlags definition |
| src/coreclr/jit/gentree.cpp | Makes OperExceptions callable on all nodes including calls; simplifies OperMayThrow to use OperExceptions; updates OperEffects to populate precise exceptions |
| src/coreclr/jit/forwardsub.cpp | Updates exception accumulation to handle UnknownException and stop tracking once multiple/unknown exceptions are seen |
| src/coreclr/jit/compiler.h | Adds declaration for fgValueNumberIndirNullCheckExceptions |
ExceptionSetFlags::UnknownException. This special value marks that an operation may throw an exception that we cannot say anything about. Consumers of flags must be specially aware about this exception type.GenTree::OperExceptionscallable on all trees by changing arbitrary user calls to return the newUnknownExceptiontype.OperMayThrowto be literallyOperExceptions() != NoneExceptionSetFlags.CORINFO_HELP_VIRTUAL_FUNC_PTR,CORINFO_HELP_GVMLOOKUP_FOR_SLOT,CORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTR. These do not mutate the heap and we use the new mechanism above to indicate that the only exception they can throw is NRE. They are also pure, so add a VN function so VN can model them. This allows us to CSE and hoist these helpers.SideEffectSetto track and precisely handle interference for exceptions. We can now reorder two operations if we know they can only throw the exact same exception.OptimizeCallIndirectTargetEvaluation; manual interference handling is no longer necessary, and we can use it for all calls.Fix #86173
Example:
Before:
After: