Skip to content

Conversation

@spotandjake
Copy link
Member

@spotandjake spotandjake commented Nov 23, 2025

I noticed that programs like:

provide let test = 1

were producing codegen like:

...global section
(global $test_1113_20 (mut i32) (i32.const 0))
... code section
(func $_start.19448
  ...
  (global.set $test_1113_20
   (i32.const 3)
  )
  ...
)

This isn't really optimal as binaryen doesn't see an oppurtunity to propogate a lot of these global constants outside the immediate scope and this produces a lot more codegen, instead we could just initialize the global to begin with.

This pr implements that behaviour where we instead directly produce:

...global section
(global $test_1113_20 (mut i32) (i32.const 3))

Notes:

  • We only really generate globals for top-level module values, and they are only initialized in the start functions, i.e an initialization is the first write and can never happen through a function call, so we are safe to remove the set in start.
  • As Compiler: Allow wasm global exports #2336 notes, we currently do not allow users to export globals. If we ever add that behaviour, we will need to figure out our user contract on those and possibly only run this optimization if use-start-section is used or the import is never exported.
  • Binaryen doesn't have an instruction to set the init value after making the global, and setting it initially would be rather complex and would probably miss some initializations, given wasm const instructions don't map 1 to 1 with the high-level anf instructions. So instead we have to remove it and add it back in (This does have the side effect of changing the index while building the module, we don't refer to them by index though, but instead by name, so that's not a worry and binaryen re-orders them later).
  • We don't handle extended const instructions, but we also rarely if ever seem to generate those, and they would be rather annoying to detect (Recursively traverse both sides of the valid const binops expressions ensuring everything is const or one of the valid const binops)
  • There is an issue open on binaryen Simplify mutable globals with single write in "start" WebAssembly/binaryen#4892 for a very similar optimization if this ever gets implemented we would probably want to use that instead.

@spotandjake spotandjake force-pushed the spotandjake-opt-globals branch from 459452d to e512671 Compare November 23, 2025 04:15
@spotandjake
Copy link
Member Author

After discussing this pr a bit over discord we decided the optimization is worth while but we are going to wait until after wasm-gc work is done before we merge as it will change what we can optimize here a lot and allow for a lot more optimizations.

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.

1 participant