Skip to content

[CFP][GSI] Fix catch pops after optimizing reads - #9289

Open
tlively wants to merge 1 commit into
mainfrom
cfp-block-nested-pops
Open

tlively wants to merge 1 commit into
mainfrom
cfp-block-nested-pops

Conversation

@tlively

@tlively tlively commented Oct 20, 2026

Copy link
Copy Markdown
Member

When ConstantFieldPropagation or GlobalStructInference optimizes a struct.get or ref.get_desc, it either wraps the reference operand in a Block or places it into the condition (third child) of a Select. Any pop instruction inside the reference from a legacy exception-handling catch body then becomes either nested inside a block or displaced out of the catch body's first-descendant chain. Update EHUtils::handleBlockNestedPop to also find and lift pops that have been moved out of the first-descendant chain, and call EHUtils::handleBlockNestedPops in both passes when reads are optimized.

When ConstantFieldPropagation or GlobalStructInference optimizes a struct.get or ref.get_desc, it either wraps the reference operand in a Block or places it into the condition (third child) of a Select. Any pop instruction inside the reference from a legacy exception-handling catch body then becomes either nested inside a block or displaced out of the catch body's first-descendant chain. Update EHUtils::handleBlockNestedPop to also find and lift pops that have been moved out of the first-descendant chain, and call EHUtils::handleBlockNestedPops in both passes when reads are optimized.
@tlively
tlively requested a review from a team as a code owner October 20, 2026 20:34
@tlively
tlively requested review from aheejin, kripken and stevenfontanella and removed request for a team October 20, 2026 20:34
Comment thread src/ir/eh-utils.cpp
Comment on lines +145 to +147
// The pop may have been moved out of the first-descendant line, e.g.
// into the condition of a select. Find it and fix it up just like a
// block-nested pop.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do we think about this solution? The alternative would be to inhibit these optimizations in the presence of pops.

@aheejin aheejin Oct 21, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are gonna ignore getFirstPop's "no", we probably should remove it and replace it with this? There's no point in calling and keeping getFirstPop at this point.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a helper function findPopPtr in eh-utils.cpp to locate nested Pop expressions and fix them up when they are moved out of the first-descendant line (e.g., into select conditions or blocks). This fix-up logic is integrated into the ConstantFieldPropagation and GlobalStructInference passes, with accompanying tests. A critical issue was identified in the new findPopPtr function where curr can be nullptr for optional AST children, which would lead to a segmentation fault when calling curr->is<Pop>(). A null check should be added to prevent this.

Comment thread src/ir/eh-utils.cpp
Comment thread src/ir/eh-utils.cpp
pop = *popPtr;
isPopNested = true;
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we separate this fix from adding calls to the two passes?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason this fix goes along with these two passes is that these passes are the only ones (that we know about) that can move the pop out of that first-child position. We could of course split it up in principle, but I think it makes sense to keep them together.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, then let me try to understand this change more. How does getFirstPop differ from findPopPtr? The new function isn't documented and I'm not sure exactly what it is doing yet.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getFirstPop only looks at the leftmost leaf in the expression tree, i.e. where pop is supposed to be found. findPopPtr looks for a pop in the entire expression tree, except inside nested trys.

@aheejin aheejin left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the reason I only allowed pops in first-descendant lines in #4348 was because otherwise the code was invalid, and all optimizations that needed the fixup so far were only nesting pops into a block and nothing more. (@kripken Is this right? You are who added almost all fixup code in various passes. Does this reflect your experience, or you saw cases where pops were displaced out of first-descendant lines but you just gave up optimizing them?)

Anyway, if we are to allow pops to be hoisted from anywhere within a catch block, I think we should just replace it with the existing first-descendant searching (because we are ignoring its result anyway). I'm also wondering, should we go into loops, where pops can run multiple times, and if's true/false bodies, where pops run conditionally? Or should we just avoid going into nested catches?

Comment thread src/ir/eh-utils.cpp
Comment on lines +145 to +147
// The pop may have been moved out of the first-descendant line, e.g.
// into the condition of a select. Find it and fix it up just like a
// block-nested pop.

@aheejin aheejin Oct 21, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are gonna ignore getFirstPop's "no", we probably should remove it and replace it with this? There's no point in calling and keeping getFirstPop at this point.

@tlively

tlively commented Oct 21, 2026

Copy link
Copy Markdown
Member Author

I'm also wondering, should we go into loops, where pops can run multiple times, and if's true/false bodies, where pops run conditionally? Or should we just avoid going into nested catches?

I think it would be harmless to search in ifs and loops. It's hard to imagine a case where an optimization would be able to move a pop into an if or a loop, and maybe that never makes sense. But if it did make sense, then we would definitely need to fix it up. I don't think there's much downside to searching in ifs or loops, either. I doubt it makes much of a performance difference.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants