Skip to content

link: run fpcast-emu before optimization passes#26478

Open
thiblahute wants to merge 1 commit intoemscripten-core:mainfrom
thiblahute:directize-skip-type-mismatch
Open

link: run fpcast-emu before optimization passes#26478
thiblahute wants to merge 1 commit intoemscripten-core:mainfrom
thiblahute:directize-skip-type-mismatch

Conversation

@thiblahute
Copy link

Move the --fpcast-emu binaryen pass earlier in the pass pipeline so it runs before -O2. Previously, directize (part of -O2) would see type-mismatched call_indirect entries and replace them with unreachable before fpcast-emu had a chance to rewrite the table entries with matching types. This caused crashes for common C idioms like calling a 1-arg function through a 2-arg function pointer (e.g. GLib's g_list_free_full pattern).

This reordering also improves performance, on a real-world GStreamer test binary, the reordered pipeline produces a 1.8% smaller wasm output (5.30MB vs 5.40MB) and seems to run almost ~2x faster (not sure why).

Also move the fpcast-emu block outside if optimizing: so it runs even without -O2 in the link flags as this is not an optimization pass in practice.

Also add a regression test.

See WebAssembly/binaryen#8475

@sbc100 sbc100 requested review from kripken and tlively March 18, 2026 02:51
Copy link
Collaborator

@sbc100 sbc100 left a comment

Choose a reason for hiding this comment

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

I love the simplicity of the fix, but I wonder if we can come up with smaller/simpler test case?

@thiblahute thiblahute force-pushed the directize-skip-type-mismatch branch from 1fa9355 to b6d5733 Compare March 18, 2026 03:18
@thiblahute
Copy link
Author

Indeed, I wrote the test case that was as close as possible with the actual trigger I had, simplified now.

Copy link
Collaborator

@sbc100 sbc100 left a comment

Choose a reason for hiding this comment

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

lgtm, but I'll wait for @kripken for the final approval.

Copy link
Member

@kripken kripken left a comment

Choose a reason for hiding this comment

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

Nice! I was hoping this would be faster, great to see that it is. It makes sense I guess - now all the casts use the same type, and any indirect call of a constant is optimizable.

Move the `--fpcast-emu` binaryen pass earlier in the pass pipeline so it
runs before -O2. Previously, directize (part of -O2) would see
type-mismatched call_indirect entries and replace them with unreachable
before fpcast-emu had a chance to rewrite the table entries with
matching types. This caused crashes for common C idioms like calling a
1-arg function through a 2-arg function pointer (e.g. GLib's
`g_list_free_full` pattern).

This reordering also improves performance: on a real-world GStreamer
test binary, the reordered pipeline produces a 1.8%
smaller wasm output (5.30MB vs 5.40MB) and seems to run almost ~2x faster
(not sure why).

Also move the fpcast-emu block outside `if optimizing:` so it runs
even without -O2 in the link flags as this is not an optimization
pass in practice.

Also add a regression test.

See WebAssembly/binaryen#8475
@thiblahute thiblahute force-pushed the directize-skip-type-mismatch branch from b6d5733 to 4978e58 Compare March 18, 2026 19:09
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