Skip to content

Toolchain optimization hints? #255

@kripken

Description

@kripken

Wasm now has branch hints (whether a branch is likely or unlikely) and compilation hints (whether code is hot, cold, etc.). Those hints are for wasm VMs. This issue is about writing up some form of convention for toolchain optimizations (which VMs would not care about, so this repo is probably the only place that makes sense).

Concretely, we have annotated code in a few ways in the Binaryen optimizer for a while, and that is used by various toolchains (Java, Dart, etc.), including features like:

  • Assume a call has no side effects, allowing it to be removed if the result is unused. For example
x = getX();
bar(x.y);

Imagine that we optimize away the last line (perhaps bar is an empty function after other optimizations), leaving

x = getX();
// x is unused

Normally we cannot remove that call to getX() if it has side effects, and perhaps it allocates some global object there the first time it is called for. When annotated as "no side effects", we can remove it. That is, the hint tells the optimizer that it can do more than the wasm semantics allow.

  • Assume code does not trap (so paths leading to traps can be ignored/removed). This is a global flag in Binaryen atm (but could be function-level in theory).

We are considering some changes to our intrinsics, to build them around wasm code annotations, see discussion in WebAssembly/binaryen#7574 (comment) , and the question came up, is there interest in writing up such conventions at a higher level than Binaryen? That is what this issue is for.

That is, would other toolchains - producers, analyzers, optimizers, etc. - be interested to use such toolchain-focused optimization flags? Note that Binaryen's hints are used across toolchains already, in the sense that e.g. Java emits them and Binaryen optimizes with them, so I think we have some evidence of general usefulness.

If it helps, the current thinking in that Binaryen thread is to define something like these annotations, on functions:

  • @binaryen.no.side.effects - toolchain optimizer can assume this has no side effects, as in the example above.
  • @binaryen.idempotent - toolchain optimizer can assume that subsequent calls to this do nothing at all / return the same result as before, allowing the following:
idempotent();
idempotent();
=> // any call after the first is removable
idempotent();
x = idempotent();
y = idempotent();
// x == y

Of course, if we decide to write up these conventions here, we can pick a better names for everything.

Thoughts?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions