Experiment with WebAssembly branch hints for CoreCLR ReadyToRun
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
### 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.
Contributor guide
Research direction
Start with the WebAssembly branch-hinting specification, then trace final Wasm instruction emission in RyuJIT and serialization in crossgen2's Wasm object writer. Run the browser-wasm ILCompiler.ReadyToRun.Tests suite and validate offsets after Webcil relocation shrinking. Done includes correct metadata generation, omission without qualifying profile data, and end-to-end engine measurements.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, wasm
- Domain
- backend, compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100