Skip to content

Experiment with WebAssembly branch hints for CoreCLR ReadyToRun #133794

Description

@lewing

Description

WebAssembly branch hinting was standardized as part of WebAssembly 3.0. It defines the metadata.code.branch_hint custom section, which lets a producer identify if and br_if conditions that are very likely to be true or false. Engines may use this metadata for native code layout and register-allocation decisions; engines that do not support it safely ignore the section.

CoreCLR ReadyToRun for WebAssembly already consumes profile data in RyuJIT. The JIT uses edge likelihoods when optimizing and laying out the structured Wasm control-flow graph, but the final Wasm module does not preserve those probabilities for the browser or standalone Wasm engine. This loses information between profile-guided R2R compilation and the engine that ultimately generates native machine code.

The proposed experiment is to emit branch hints for strongly biased conditional branches in CoreCLR Wasm R2R output:

  • select hints after final Wasm CFG layout and condition reversal;
  • emit only sufficiently strong profile-backed probabilities, initially using an 80/20 threshold;
  • carry finalized function-relative instruction offsets from RyuJIT to crossgen2;
  • resolve final function indices and emit one metadata.code.branch_hint custom section before the code section;
  • preserve correct offsets when Webcil relocation resolution shrinks variable-length LEB encodings;
  • omit the section when no qualifying profile data is available.

Specification: https://webassembly.github.io/branch-hinting/core/appendix/custom.html#branch-hinting-section

Configuration

  • Target runtime: CoreCLR ReadyToRun
  • Target OS/architecture: browser-wasm / wasm32
  • Producer: crossgen2 with static .mibc profile data
  • Consumer: WebAssembly engines implementing branch hinting

Regression?

No. This is an optimization opportunity enabled by recently standardized WebAssembly metadata. Existing CoreCLR Wasm R2R output remains valid and semantically unchanged without the section.

Data

Initial prototype validation shows:

  • the custom section is accepted by an independent Wasm parser;
  • every emitted offset points to an actual if or br_if opcode;
  • function and branch entries are sorted and unique as required by the specification;
  • offsets remain correct after Webcil relocation shrinking;
  • the full browser-wasm ILCompiler.ReadyToRun.Tests suite passes;
  • a small test module grew from 6,528 bytes to 6,560 bytes, a 32-byte increase for the section and its hints.

The experiment still needs end-to-end measurements on engines that consume branch hints. Useful success criteria include:

  • startup and steady-state results for representative CoreCLR Wasm workloads;
  • engine compilation time and generated native-code size;
  • branch/layout-sensitive microbenchmarks as diagnostics, followed by realistic application measurements;
  • R2R image-size impact on framework and application assemblies;
  • comparison across engines that consume or ignore the metadata.

Analysis

The correct layer boundary is between final RyuJIT Wasm instruction emission and the Wasm object writer:

  • RyuJIT owns the final branch direction and byte offset after CFG layout and condition reversal.
  • crossgen2 owns final function indices, custom-section ordering, and Webcil relocation shrinking.

The metadata should therefore be selected and reported by the JIT, retained as per-method side data, and serialized only after crossgen2 has resolved final indices and code offsets. It should not be represented as executable semantics or as a pseudo-relocation.

The feature should remain profile-gated. Synthesized probabilities are useful for deterministic testing but should not enable production hints by default.

Note

This issue was drafted with GitHub Copilot.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    • Status
      No status

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions