leventov opened PR #14973 from convex-in-prod:upstream-sparse-gc-liveness to bytecodealliance:main:
Motivation
GC-reference liveness currently scans every instruction on every fixed-point visit and again when recording safepoints. Most instructions in scalar-heavy functions cannot change that liveness set.
Change
Record the relevant definitions, uses and safepoints once, in the same backwards order as the existing analysis, and reuse those events for subsequent visits. Alias resolution, try-call edge argument ordering, exception-context rejection and live-set propagation retain their existing semantics. Empty safepoint sets do not need recording, and functions with no reference live across any safepoint skip rewriting.
Event storage is reused with the builder context and cleared between functions. A regression alternates dead/live/dead reference lifetimes in scalar-heavy functions using the same context, checking that spills and reloads appear only when required.
Validation
cargo test -p cranelift-frontend --lib safepoints: all 22 tests passed, including loops, irreducible control flow, aliases, try-call edges and context reuse. The new regression was rerun after updating its scalar instruction builder to the current nondeprecated API. Changed-file rustfmt check passed.The intended benefit is less work in repeated liveness visits; this PR does not change generated stack-map semantics or claim a universal compilation speedup. It adds a compact event list whose size depends on references and safepoints, rather than scalar instruction count.
leventov requested fitzgen for a review on PR #14973.
leventov requested wasmtime-compiler-reviewers for a review on PR #14973.
leventov removed the review request for wasmtime-compiler-reviewers from PR #14973.
leventov edited PR #14973:
Motivation
GC-reference liveness currently scans every instruction on every fixed-point visit and again when recording safepoints. Most instructions in scalar-heavy functions cannot change that liveness set.
Change
Record the relevant definitions, uses and safepoints once, in the same backwards order as the existing analysis, and reuse those events for subsequent visits. Alias resolution, try-call edge argument ordering, exception-context rejection and live-set propagation retain their existing semantics. Empty safepoint sets do not need recording, and functions with no reference live across any safepoint skip rewriting.
Event storage is reused with the builder context and cleared between functions. A regression alternates dead/live/dead reference lifetimes in scalar-heavy functions using the same context, checking that spills and reloads appear only when required.
Illustrative downstream measurement
A controlled local comparison in convex-wasm-compiler measured warm AOT compilation of a roughly 200 MB Core Wasm module generated from a TypeScript application. Both variants used the same input and engine settings, one AOT worker pinned to a single CPU, and independently populated function caches. Each invocation ran in a fresh process, in baseline/change/change/baseline order:
Order Variant Elapsed seconds CPU seconds Function-cache misses 1 Baseline 61.380 58.16 10 2 Sparse liveness events 47.382 42.25 10 3 Sparse liveness events 42.118 41.27 6 4 Baseline 61.192 57.91 6 Across the two invocations per variant, elapsed time fell 27.0% (122.572 → 89.500 s) and CPU time fell 28.0% (116.07 → 83.52 s), with matched miss counts. Every invocation reproduced the same approximately 569 MB AOT artifact byte for byte. This matters for incremental builds: frontend liveness work still runs even when almost all compiled function bodies can be reused.
This is a historical downstream measurement of the change, not a rerun on this PR's current upstream base. It measures remaining AOT work with warm function caches, not cold compilation, the complete application build, or guest execution. There are only two observations per variant; the result illustrates a workload where the change helps rather than predicting a universal compilation speedup.
Validation
cargo test -p cranelift-frontend --lib safepoints: all 22 tests passed, including loops, irreducible control flow, aliases, try-call edges and context reuse. The new regression was rerun after updating its scalar instruction builder to the current nondeprecated API. Changed-file rustfmt check passed.The intended benefit is less work in repeated liveness visits; this PR does not change generated stack-map semantics or claim a universal compilation speedup. It adds a compact event list whose size depends on references and safepoints, rather than scalar instruction count.
leventov edited PR #14973:
GC-reference liveness analysis scans every instruction on each fixed-point visit and again when recording safepoints. In scalar-heavy functions, most of those instructions cannot affect reference liveness.
Build per-block lists of reference definitions, uses and safepoints once, then replay those events on subsequent visits. Preserve the existing backwards ordering, including
try_calledge arguments. Event storage is reused with the builder context and cleared between functions. Also omit empty safepoint sets and skip rewriting when no reference is live across a safepoint.Performance
In the downstream convex-wasm-compiler integration, warm AOT compilation of a roughly 200 MB Core Wasm module improved as follows:
Mean per invocation Baseline Sparse events Reduction Elapsed time 61.286 s 44.750 s 27.0% CPU time 58.035 s 41.760 s 28.0% Four fresh-process runs used baseline/change/change/baseline order, one worker pinned to a CPU, warm function caches and matched cache-miss counts. All produced byte-identical AOT artifacts. This measures compilation with cached function bodies: frontend liveness still runs before those bodies can be reused.
Validation
cargo test -p cranelift-frontend --lib safepoints: all 22 tests passed, covering loops, irreducible control flow, aliases and exception edges. The new regression reuses one builder context across scalar-heavy functions with dead/live/dead reference lifetimes, checking that spills and reloads appear only when required.
github-actions[bot] added the label cranelift on PR #14973.
fitzgen commented on PR #14973:
This PR description looks like it was written by an LLM. Can you confirm whether this abides by the AI policy?
leventov updated PR #14973.
leventov commented on PR #14973:
No, I didn't author PR description and didn't try to understand this part of the codebase that this PR touches.
However, please consider the following:
- The 200 MB wasm module is a real production module, not some synthetic one created just for the benchmark.
- The 16s Cranelift compilation time reduction is also real, which doesn't seem like nothing and might be useful for many other users of Cranelift.
- The byte-identical native code output makes this change low-risk at least in some sense.
The AI policy invokes gestures towards multiple different things and ideas, which seems a bit inconsistent to me:
- The idea that all contributions should have personal human ownership.
- Whether the author has an interest to become a long-term maintainer.
- Whether the contribution a high-effort, or a low-effort one.
- Whether the contribution is extractive or not (worth more to the project than the time it takes to review it).
My self-assessment:
- No, I don't have personal ownership/understanding of this change set.
- No, I don't have a interest to become a long-term maintainer.
- Depends on what is meant here. In terms of personal effort, no, I didn't put a lot of personal effort into this change. However, it was authored and reviewed multiple times by Astra xhigh (and reviewed another one time just become I author this comment, to be sure, which edited some comment), which makes this contribution, together with its real-life validation, vastly higher "AI effort" than low-effort fire-and-forget contributions that gained AI contributions its bad rep.
- I'd argue it's not an extractive contribution: code change is small, Cranelift compilation time reduction is significant. And following the principle of mediocrity, I think my pattern is not that unique among all users of Cranelift.
leventov edited a comment on PR #14973:
No, I didn't author PR description and didn't try to understand this part of the codebase that this PR touches.
However, please consider the following:
- The 200 MB wasm module is a real production module, not some synthetic one created just for the benchmark.
- The 16s Cranelift compilation time reduction is also real, which doesn't seem like nothing and might be useful for many other users of Cranelift.
- The byte-identical native code output makes this change low-risk at least in some sense.
The AI policy gestures towards multiple different things and ideas, which seems a bit inconsistent to me:
- The idea that all contributions should have personal human ownership.
- Whether the author has an interest to become a long-term maintainer.
- Whether the contribution a high-effort, or a low-effort one.
- Whether the contribution is extractive or not (worth more to the project than the time it takes to review it).
My self-assessment:
- No, I don't have personal ownership/understanding of this change set.
- No, I don't have a interest to become a long-term maintainer.
- Depends on what is meant here. In terms of personal effort, no, I didn't put a lot of personal effort into this change. However, it was authored and reviewed multiple times by Astra xhigh (and reviewed another one time just become I author this comment, to be sure, which edited some comment), which makes this contribution, together with its real-life validation, vastly higher "AI effort" than low-effort fire-and-forget contributions that gained AI contributions its bad rep.
- I'd argue it's not an extractive contribution: code change is small, Cranelift compilation time reduction is significant. And following the principle of mediocrity, I think my pattern is not that unique among all users of Cranelift.
Last updated: Oct 31 2026 at 23:03 UTC