Skip to content

[wip][Wasm] Emit R2R branch hints from profile data - #133795

Draft
lewing wants to merge 1 commit into
mainfrom
lewing-wasm-r2r-branch-hinting
Draft

lewing wants to merge 1 commit into
mainfrom
lewing-wasm-r2r-branch-hinting

Conversation

@lewing

@lewing lewing commented Sep 12, 2026

Copy link
Copy Markdown
Member

Summary

Emit the standardized WebAssembly metadata.code.branch_hint custom section from CoreCLR ReadyToRun compilation when static PGO identifies strongly biased conditional branches.

This is an experimental implementation for #133794. Engines that do not consume branch hints safely ignore the custom section.

Design

  • Select hints in RyuJIT after final Wasm CFG layout and condition reversal.
  • Require static, sufficiently trustworthy PGO and an 80/20 likelihood threshold in production.
  • Attach the final hint to the emitted br_if instruction descriptor.
  • Report function-relative instruction offsets through the existing JIT metadata channel.
  • Retain hints as ReadyToRun per-method side data and resolve final function indices in the Wasm object writer.
  • Emit one sorted metadata.code.branch_hint custom section immediately before the code section.
  • Adjust hint offsets when Webcil relocation resolution shrinks variable-length LEB encodings.
  • Reset reported metadata on internal JIT retries so discarded compilation attempts cannot leak stale hints.
  • Keep relocatable Wasm output explicitly unsupported because its function indices and code offsets are not final.

A JitWasmBranchHintStress switch permits deterministic tests using synthesized profile weights without changing production gating.

Validation

  • ./build.sh clr
  • PATH=/opt/homebrew/bin:$PATH ./build.sh -os browser -c Debug -subset clr+libs
  • python3 src/coreclr/scripts/jitformat.py -r <runtime> -o osx -a arm64 -b Checked --verbose --fix --projects dll
  • Full browser-wasm ILCompiler.ReadyToRun.Tests: 75 passed, 37 skipped, 0 failed
  • Independent Wasm parsing confirmed the custom section is present before the code section.
  • Tests verify function and branch ordering, metadata shape, final function indices, funclet handling, relocation-adjusted offsets, and that each hint points to an actual if or br_if opcode.
  • Tests also verify the section is absent without qualifying profile data or the test stress switch.

Size impact

For the test module, identical synthesized profile input produced:

Configuration Size
Profile data, branch hints disabled 6,528 bytes
Profile data, branch hints enabled 6,560 bytes

The custom section and hints add 32 bytes in this sample.

Follow-up measurements

This draft establishes correct metadata generation. Before considering it ready to merge, it needs end-to-end measurements on Wasm engines that consume branch hints, including representative application startup/steady-state results, engine compilation time, generated native-code size, and broader R2R image-size impact.

Note

This pull request description was drafted with GitHub Copilot.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 6 pipeline(s).
10 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/crossgen-contrib
See info in area-owners.md if you want to be subscribed.

@lewing lewing added the arch-wasm WebAssembly architecture label Sep 12, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara
See info in area-owners.md if you want to be subscribed.

@lewing lewing changed the title [Wasm] Emit R2R branch hints from profile data [wip][Wasm] Emit R2R branch hints from profile data Sep 12, 2026
@lewing lewing added the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Sep 12, 2026
@lewing

lewing commented Sep 12, 2026

Copy link
Copy Markdown
Member Author

I'm exploring tooling changes against this prototype.

}
metadata[8] = branchHint == WasmBranchHint::LikelyTrue ? 1 : 0;

JitMetadata::report(m_compiler, JitMetadata::WasmBranchHint, metadata, sizeof(metadata));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to call report here, it will get called automatically when the jit is done with the method. Instead, increment the metric.

Comment thread src/coreclr/jit/emit.cpp
instrDesc* prevId = nullptr;
#endif // defined(DEBUG) && defined(TARGET_ARM64)

#ifdef TARGET_WASM

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Omit this (see below).

If you want to know what % of branches got hinted it will take more work.

assert(trueTarget != block->Next());

WasmBranchHint branchHint = WasmBranchHint::None;
bool const hasStaticProfile =

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just call fgHaveProfileWeights here and not worry about the source or quantity.

WasmBranchHint branchHint = WasmBranchHint::None;
bool const hasStaticProfile =
(m_compiler->fgPgoSource == ICorJitInfo::PgoSource::Static) && m_compiler->fgHaveSufficientProfileWeights();
if (hasStaticProfile || (JitConfig.JitWasmBranchHintStress() != 0))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of forcing on hints then you could force them off here.

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

Labels

arch-wasm WebAssembly architecture area-ReadyToRun NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants