feat(vcr-ra): i64 pair-spill via param frame-backing — VCR-RA-001 acceptance closes (v0.11.40)#325
Merged
Merged
Conversation
…iterion closes (#242) The last hard-fail named by the v0.11.40 acceptance review: a high-pressure i64 module now compiles with no hard-fail. ROOT CAUSE (differs from the review's reading): the pair allocator (alloc_consecutive_pair) has ALWAYS spilled register-resident stack values — pair-aware, both halves into one 8-byte slot (#171). The remaining "no consecutive pair of free registers for i64" Err fires only when the operand stack holds nothing register-resident and the blockers are the PINNED PARAM HOME REGISTERS (#193 `reserved`, up to r0-r3) plus the popped operand pairs (`extra_avoid`, up to 4 regs) — 8 of the 9-register pool, no pair left, and no amount of stack spilling can free a param home register. FIX (same structural-bit-identity pattern as #320): a third retry mode, `set_param_backing_on_exhaustion`, forces the proven #204 `param_slots` frame-backing for call-free functions — params spill to frame slots at entry and reload on read, so `reserved` empties and a free consecutive pair always exists after stack spilling (extra_avoid is at most two adjacent pairs among nine registers; pigeonhole over the free segments). The backend's select_direct ladder: pass 1 default → pass 2 spill-only (#320, on the single-reg Err) → pass 3 spill+param-backing (on the pair Err). Functions that compile on an earlier pass are selected by exactly yesterday's code. Loop bound unchanged: each spill_deepest_reg iteration converts one StackVal::Reg to Spilled. Honest remaining bound: the i64 spill-slot pool ("spill-slot pool exhausted"), deliberately NOT retried. EVIDENCE - scripts/repro/high_pressure_i64.wat: 4 simultaneously-live i64 consts + 4 pinned i32 params. On main: skipped with the exact pair Err. On this branch: compiles; high_pressure_i64_differential.py (unicorn vs wasmtime, i64 result in r0:r1, large/negative vectors) 6/6 ORACLE PASS. - Bit-identity vs origin/main (cortex-m4, per differential headers): control_step 8248…32f6, div_const cada…45ede, flight_seam_flat 03ce…8579, high_pressure_i32 355c…e6c2 — all pairwise sha256-identical; all three frozen differentials ORACLE PASS on the branch. - Tests: 5 new (pair victim spill, single victims, pinned-blockers Err preserved verbatim, spilled-pair reload on pop, end-to-end 3-pass ladder); synth-synthesis 382 lib tests green; workspace 1468 passed / 0 failed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This was referenced Jun 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The last criterion
The #242 acceptance review left one gap: "a high-pressure i64 module compiles with no hard-fail." Investigation revised the diagnosis: the pair-spill loop already existed (#171) — the true blocker was pinned param home registers (#193's
reserved, up to R0–R3) which no stack spill can free. The fix is a third retry mode that forces the proven #204 param frame-backing onto call-free functions, emptying the reserve; pigeonhole over the freed pool then guarantees a consecutive pair.Backend retry ladder (each pass only on its predecessor's exact
Err, so bit-identity stays structural): default → spill-only (#320) → spill+param-backing (this PR).Evidence
scripts/repro/high_pressure_i64.wat: hard pair-exhaustionErron main → compiles + 6/6 unicorn-vs-wasmtime on the branch (incl. all-ones/sign-bit vectors).VCR-RA-001 status after this merges: all five criteria met
compile-no-hard-fail ✅ (both pressure classes) · fixtures bit-identical ✅ · cycles equal-or-better ✅ (gale silicon) · cost-gate revert ✅ (executed, #322) · validator guarding ✅ (#323). Honest bounds named: the 8-slot spill pool, the distinct R8-pair/i64-param-convention class (epic-tracked), stack-passed params.
Release: v0.11.40 — the allocator's acceptance release.
🤖 Generated with Claude Code