feat(rv32-promo): measured no-grow profitability for local promotion (#472, #601, epic #242) - #626
Merged
Merged
Conversation
…472, #601, epic #242) Salvaged from an interrupted session (299 tool uses): select_inner now MEASURES promotion profitability — lowers the unpromoted baseline plus every candidate subset (<=3 locals -> <=7 attempts) and keeps a promoted lowering only when emitted_byte_size <= baseline. Prices per-return epilogue restores and WAR-snapshot mvs by construction (the #601 flip blocker). emitted_byte_size mirror-pinned to assemble_function pass-1 sizing (#511 lesson). Corpus no-grow gate: rv32_local_promo_no_grow_corpus_472. Flag SYNTH_RV_LOCAL_PROMO stays opt-in. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
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.
RV32 local-promotion profitability: MEASURED no-grow decision (#472, #601, epic #242)
The
SYNTH_RV_LOCAL_PROMOflip was HELD out of the RV32 lever flip-wave (#601) because the v1 profitability model ("≥2 accesses repay the save/restore") under-charged: it priced neither the per-RETURN epilogue restore (preserve_callee_savedduplicates thelw s_irestores into EVERYret) nor the WAR-snapshotmvs. Small functions grew net: war_set 56→64 B, war_tee 60→68 B, control_step_decide +4 B.The fix — measure, don't model
select_innernow lowers the function unpromoted (the baseline — byte-identical to flag-off), then over every non-empty subset of the candidate locals (≤3 → ≤7 attempts), and keeps a promoted lowering only whenemitted_byte_size(promoted) <= emitted_byte_size(baseline)— strict no-grow, priced on the ACTUAL emitted sequence, so per-return restores, WARmvs, zero-inits and frameaddiinteractions are all charged by construction. Subsets matter: one local's win must not smuggle another local's loss past the gate.emitted_byte_sizeis mirror-pinned toassemble_function's pass-1 sizing byemitted_byte_size_matches_assembled_text(the #511 estimator↔encoder drift lesson).Salvage provenance
Recovered from an interrupted session (two predecessor agents died mid-work); the salvage commit was found complete in the worktree, then independently re-verified end-to-end below. Branch is based on current main (v0.30.2).
RED → GREEN
The new corpus gate
rv32_local_promo_no_grow_corpus_472(synth-cli tests) was re-run against the OLD model (both backend files reverted to origin/main, same test file):With the measured model:
test result: ok.Execution differentials — all 11
scripts/repro/*riscv*_differential.py, flag ON, fresh binaryPer-function byte deltas — ENTIRE repro corpus (67 RV32-compiling fixtures × flag-off/on, ELF .symtab sizes)
10 functions shrink, 0 grow, function sets unchanged across all 67 fixtures. Every other function is byte-neutral (the measured gate declines, falling back to the exact baseline lowering — war_set/war_tee/rbw/control_step_decide included).
Frozen anchors
Flag stays opt-in in this PR — flag-off is byte-identical (single baseline run).
frozen_codegen_bytes(ARM + RV32 gates + both escape hatches): untouched, green. Bonus, verified for the follow-up flip: the two pinned RV32 goldens (control_step 6ac5d7f9…/484, signed_div_const 15fa429d…/88) are byte-identical even flag-ON.Gate (all green)
cargo test -p synth-backend-riscv(210) ·cargo test -p synth-cli(all suites)cargo test --workspace— 104 suites, 0 failurescargo fmt --check·cargo clippy --workspace --all-targets -- -D warningsFollow-up: the default-on flip (#601 refreeze ritual) rides in the next PR.
🤖 Generated with Claude Code