Skip to content

[OptimizeInstructions] Fix trapOnNull unreachable If - #9339

Merged
tlively merged 1 commit into
mainfrom
optimize-instructions-trap-on-null-unreachable
Nov 2, 2026
Merged

tlively merged 1 commit into
mainfrom
optimize-instructions-trap-on-null-unreachable

Conversation

@tlively

@tlively tlively commented Nov 2, 2026

Copy link
Copy Markdown
Member

In Binaryen IR, Ifs with unreachable conditions are unreachable even if the arms have concrete types, whereas Blocks keep the concrete type of their final element even when an earlier element is unreachable. Unreachable Ifs can validly appear as the reference operand of an instruction like array.set or struct.set, even if their concrete arms have unrelated types.

In OptimizeInstructions::trapOnNull, under --traps-never-happen, when one arm of an If flowed out a null reference, the If was replaced with a drop of the condition followed by the other arm. This created invalid IR when the condition was unreachable and the other arm had an unrelated type. Fix the problem by only doing this optimization when the If condition is not unreachable.

In Binaryen IR, `Ifs` with unreachable conditions are unreachable even if the arms have concrete types, whereas `Block`s keep the concrete type of their final element even when an earlier element is `unreachable`. Unreachable `If`s can validly appear as the reference operand of an instruction like `array.set` or `struct.set`, even if their concrete arms have unrelated types.

In `OptimizeInstructions::trapOnNull`, under `--traps-never-happen`, when one arm of an `If` flowed out a null reference, the `If` was replaced with a drop of the condition followed by the other arm. This created invalid IR when the condition was unreachable and the other arm had an unrelated type. Fix the problem by only doing this optimization when the `If` condition is not unreachable.
@tlively
tlively requested a review from a team as a code owner November 2, 2026 21:33
@tlively
tlively requested review from stevenfontanella and removed request for a team November 2, 2026 21:33

@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 prevents the optimization of If instructions when the condition is unreachable to avoid generating invalid intermediate representation, and adds a corresponding test case. The reviewer suggests defensively combining the null check for iff->ifFalse with the condition check instead of using an assertion, which improves robustness against unexpected IR states.

Comment on lines +1760 to +1761
if (iff->condition->type != Type::unreachable) {
assert(iff->ifFalse);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Instead of asserting that iff->ifFalse is non-null, we can defensively combine the null check into the if condition. This is safer and avoids potential assertion failures in environments with unexpected or intermediate IR states.

        if (iff->condition->type != Type::unreachable && iff->ifFalse) {

if (auto* iff = ref->dynCast<If>()) {
if (iff->ifFalse) {
if (iff->condition->type != Type::unreachable) {
assert(iff->ifFalse);

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 I'm missing context here. Why must an if whose condition isn't unreachable have an else? Can't we have an if without an else?

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.

We know that the If here has a concrete output type because it will flow into some instruction that will do an implicit null check on that output. In Binaryen IR, an If can only have a concrete output type if it has two arms. A single-arm if always has type Type::none or Type::unreachable. (If you tried to have a concrete-typed single-arm If, what value would it produce when the condition is false?)

Notably, Wasm can have concretely typed single-arm ifs when the if takes input parameters that match its results. Binaryen IR doesn't support input parameters, though.

@tlively
tlively merged commit 85a596c into main Nov 2, 2026
18 checks passed
@tlively
tlively deleted the optimize-instructions-trap-on-null-unreachable branch November 2, 2026 22:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants