JIT: Fix assert in object allocation phase#117066
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.
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
JITDUMPmessage and returnsfalsewhen 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. | ||
| // |
There was a problem hiding this comment.
[nitpick] The standalone // line adds noise without additional context. Consider removing it or merging it with adjacent comment lines for clarity.
| // |
|
@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. |
amanasifkhalid
left a comment
There was a problem hiding this comment.
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.