-
Notifications
You must be signed in to change notification settings - Fork 5.2k
JIT: Fix assert in object allocation phase #117066
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
Conversation
The previous DFS and remove phase may leave unreachable pred blocks around. Bail out of conditional escape analysis when this happens. Fixes dotnet#117039.
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
The PR updates the object allocation phase to guard against unreachable predecessor blocks by adding a DFS containment check and bailing out of conditional escape analysis when such blocks are encountered.
- Adds a check using
comp->m_dfsTree->Contains(predBlock)
to detect and handle unreachable predecessors. - Emits a
JITDUMP
message and returnsfalse
when an unreachable block is found.
Comments suppressed due to low confidence (2)
src/coreclr/jit/objectalloc.cpp:4049
- This new bailout path for unreachable predecessor blocks isn't exercised by existing tests. Consider adding a JIT or unit test that triggers this scenario to ensure the code path is covered.
if (!comp->m_dfsTree->Contains(predBlock))
src/coreclr/jit/objectalloc.cpp:4056
- The removed comment about EH paths suggests uncertainty around exception-handler edges. Confirm and document whether EH paths are accounted for by this DFS check or require separate handling.
//
|
||
// We may see unreachable pred blocks here. If so we will | ||
// conservatively fail. | ||
// |
Copilot
AI
Jun 26, 2025
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.
[nitpick] The standalone //
line adds noise without additional context. Consider removing it or merging it with adjacent comment lines for clarity.
// |
Copilot uses AI. Check for mistakes.
@dotnet/jit-contrib PTAL This assert was firing in xunit code. Because of how xunit randomizes test execution order the PGO data for this method is quite different from one run to the next, so it took a while to repro this. |
Are we not walking the blocklist in RPO here? If not, can we? That way, we never waste time with unreachable blocks. |
We are generally walking in RPO, but when we find a CEA opportunity we need to walk backwards in flow from the GDV uses, and that is where we may find unreachable preds. |
I see. Normally, if a block's pred becomes unreachable, I'd expect the previous phase to remove the edge into the block, so we wouldn't encounter unreachable preds during normal pred edge iteration. In this case, is the unreachable pred we're finding an EH pred? Sorry for asking for these clarifications when the repro is tricky... |
Yes it's EH flow from some blocks that couldn't be removed by the DFS/remove phase. We have deeply nested EH in this huge example, here's snippet of the flow graph
BB449/BB450 are unreachable but remain; BB40 has BB450 as an EH pred and is part of the region we want to clone for CEA. |
Along those lines, we might want to revisit places where we decide we can't remove blocks because of EH, as much of it was written before we had upgraded the flow graph representation and EH removal capabilities. |
Agreed, sounds like something I can take a look at. |
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.
Thanks for walking me through this
The previous DFS and remove phase may leave unreachable pred blocks around. Bail out of conditional escape analysis when this happens.
Fixes #117039.