Skip to content

feat(vcr-ra): range re-allocation default-ON + dead callee-saved-save elimination (v0.11.36) - #309

Merged
avrabe merged 1 commit into
mainfrom
feat/v0.11.36-realloc-on-prologue-shrink
Jun 10, 2026
Merged

feat(vcr-ra): range re-allocation default-ON + dead callee-saved-save elimination (v0.11.36)#309
avrabe merged 1 commit into
mainfrom
feat/v0.11.36-realloc-on-prologue-shrink

Conversation

@avrabe

@avrabe avrabe commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

What

The two halves of gale's #209 verdict, same release:

  1. SYNTH_RANGE_REALLOC → default-ON — gale's on-target gate cleared it (byte-identical on 3 benches, cycle-neutral + correct where it fires, silicon selfchecks green). Opt-out: SYNTH_RANGE_REALLOC=0; per-function stats: SYNTH_REALLOC_STATS=1.
  2. Dead callee-saved-save elimination (shrink_callee_saved_saves) — the "next consequential lever" from the same comment: after re-allocation packs a leaf into r0/r1, push {r4-r8,lr}+ldmia {r4-r8,pc} is ~12 cycles of pure overhead on a 37-cycle function. Save lists shrink to the callee-saved registers actually used, padded to an even count (8-byte AAPCS alignment preserved).

Bounded v1 soundness scope (declines otherwise): single LR-push prologue + PC-pop epilogues; zero SP touches (frame offsets can't shift); leaf-only; every op register-modeled or label-only control flow (BrTable declines — its index register is invisible to reg_effect).

Gate

check result
4 differentials under the new default RESULT-identical (13/13, 0x07FDF307×2, 338/338)
opt-out build vs v0.11.35 cmp bit-identical
.text div_const −52 B (small leaves drop dead saves), flat −4 B, control_step ±0
tests / clippy 342/342, clean

Deliberate fixture re-freeze (bytes change, results proven); gale is staged for same-day on-target re-measure — expected: −25%-class cycle wins on the small leaves, neutral elsewhere.

Also files VCR-RA-010 (gale #290): scry as untrusted regalloc oracle + soundness-bearing narrowing.

Falsification

Wrong if any module faults or diverges where a shrunk save list dropped a register that was actually live (i.e. the used-set scan missed an occurrence class), or if alignment-sensitive code observes a misaligned SP — both bounded by the decline rules and watched by the differentials + gale's reflash.

Traceability: VCR-RA-001 (epic #242). Release: v0.11.36 (plan #242, gale interleave — GI-NPA-003 shifts to v0.11.37).

🤖 Generated with Claude Code

… elimination (#209/#242, v0.11.36)

gale cleared the SYNTH_RANGE_REALLOC gate on-target (G474RE, #209
2026-06-10): flag-on byte-identical to flag-off on flat_flight/controller/
control_step, fires on the filter family with zero cycle delta and a size
win, all selfchecks green on silicon. This release flips it default-ON
(opt-out SYNTH_RANGE_REALLOC=0, stats via SYNTH_REALLOC_STATS=1) and ships
the follow-up lever gale identified in the same comment:

shrink_callee_saved_saves — after re-allocation packs a small body into low
registers, the prologue still saves dead callee-saved regs; push{r4-r8,lr} +
ldmia{r4-r8,pc} is ~12 cycles of pure overhead on a 37-cycle leaf. Shrink
the save lists to the callee-saved registers the body actually touches,
padded to an EVEN count (preserves the 8-byte AAPCS alignment the original
even-count push established). Deliberately bounded v1 scope, decline
otherwise: single LR-push prologue + PC-pop epilogues only, no SP touch
anywhere (frame offsets would shift), leaf-only (no calls), every op either
reg_effect-modeled or label-only control flow (BrTable declines — its index
register is invisible to reg_effect).

Gate:
  - all four differentials RESULT-identical under the new default
    (control_step 13/13 0x00210A55, flight_seam inlined+flat 0x07FDF307,
    div_const 338/338)
  - opt-out build cmp-BIT-IDENTICAL to v0.11.35
  - .text: div_const 284 -> 232 (-52 B: many small leaves drop dead saves),
    flat 1244 -> 1240 (realloc), control_step unchanged
  - 342/342 lib tests (4 new shrink tests: filter-shape pad-even, used-reg
    kept, declines on call/SP/BrTable, multiple epilogues), clippy clean

Also files VCR-RA-010 (gale #290): scry annotations as untrusted regalloc
oracle (validated by VCR-RA-003, outside the TCB) + soundness-bearing i64
narrowing with per-rewrite refinement obligations.

This is a deliberate fixture re-freeze release (bytes change, results
proven identical); gale staged for same-day on-target re-measure.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@avrabe

avrabe commented Jun 10, 2026

Copy link
Copy Markdown
Contributor Author

Pre-merge silicon validation (G474RE): −8 cyc uniform on the filter family, all correct, big-3 untouched — good to merge + tag

Built this branch (b762ac1), byte-diffed the full suite, funcchecked both flag states (ALL GREEN), reflashed and measured:

bench v0.11.35 PR #309 native gap
filter full 37 29 (−8) 19 1.95×→1.53×
filter nodiv 29 21 (−8) 12 →1.75×
filter div 30 22 (−8) 15 →1.47×
flat_flight / controller / control_step 241 / 150 / 151 byte-identical .o unchanged

SELFCHECKs all OK (1088 / −1917). Prologue shrinks push {r4-r8,lr} → 16-bit push {r4,lr}, code 40→34 B. The conservative v1 scope behaves exactly as designed: fires only on the no-SP-access leaves, passes through everything else.

Falsification note (my prediction was wrong on magnitude): I predicted −12 (full elimination of the 6-reg push/pop). Measured: −8, because v1 retains the {r4, lr} pair for AAPCS 8-byte alignment. Direction and mechanism confirmed; the retained pair costs the remaining ~4 cycles.

v2 lever this exposes — leaf-function prologue elimination: these functions make no outgoing calls, so nothing clobbers lr and in-body SP alignment is unconstrained on M-profile (exception entry auto-aligns). A leaf with zero used callee-saved regs needs no prologue at all: no push/pop, return bx lr. That converts the remaining 4 cycles (29→25 on full, matching the original −12 estimate) and is strictly scoped: is_leaf && used_callee_saved_after_realloc == ∅. Happy to validate same-day as usual.

@codecov

codecov Bot commented Jun 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.59259% with 14 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
crates/synth-synthesis/src/liveness.rs 94.44% 10 Missing ⚠️
crates/synth-backend/src/arm_backend.rs 55.55% 4 Missing ⚠️

📢 Thoughts on this report? Let us know!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant