-
Notifications
You must be signed in to change notification settings - Fork 820
Description
Atm we provide a way to say that a call has no side effects with an intrinsic, which is just an imported function:
Lines 42 to 56 in f030449
| // | |
| // (import "binaryen-intrinsics" "call.without.effects" | |
| // (func (..params..) (param $target funcref) (..results..))) | |
| // | |
| // call.without.effects can take any parameters, and in addition a funcref, | |
| // and return any result. | |
| // | |
| // Precise semantics: | |
| // | |
| // * The optimizer will assume this instruction has no side effects. | |
| // * Final lowering turns a call.without.effects into a call of the given | |
| // function with the given parameters. (This will either be a direct call, | |
| // or a call_ref; note that either way, the function reference that appears | |
| // here must have the proper type - if not, you will get an error.) | |
| // |
The wasm spec has been adding similar code metadata in the form of branch hints and compilation hints. While call.without.effects is not meant to be used by VMs (it only make sense at the toolchain level), it may be nice to implement it similarly, to be consistent. That is, instead of the current intrinsic which is a specially-named function import, we could annotate the code the way those two proposals do:
- In the text format, using custom annotations, something like:
(@metadata.code.pure "\00")
(call $target)- In the binary format, add a custom section, and the binary offsets there point to the instructions that are annotated.
The binary format takes more work this way - in particular, it is easy to get the offsets wrong - but it is more consistent with other things in wasm. Thoughts on the tradeoff?
Separately, there are two changes we may want to make to call.without.effects if we make a new version of it:
- We can annotate the function itself (once) rather than all calls to it (many). That is, unless there are cases where some calls to the same target should be considered effect-free, but not others?
- Atm
call.without.effectsonly considers side effects (discussion), but it does not guarantee that it returns the same value for the same inputs. In particular, marking a call to a JS export that doesMath.random()ascall.without.effectswould be wrong - two such calls cannot be folded together. We could make the new version also assume it returns the same value, and call it "pure", perhaps?