Skip to content

test(vcr-ra): RV32 lever baselines — pin pre-lever codegen for #472 levers (#472, #242)#485

Merged
avrabe merged 1 commit into
mainfrom
vcr-ra/472-rv-lever-baselines
Jun 25, 2026
Merged

test(vcr-ra): RV32 lever baselines — pin pre-lever codegen for #472 levers (#472, #242)#485
avrabe merged 1 commit into
mainfrom
vcr-ra/472-rv-lever-baselines

Conversation

@avrabe

@avrabe avrabe commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Frozen-safe oracle-first baselines for the RISC-V lever port (#472)

No codegen change — three in-tree selector tests that assert the current RV32 codegen for the patterns the #472 levers target, validating the scoping doc (riscv_lever_parity_472.md, #484) with executable evidence and pinning the pre-lever baseline.

test pins lever that flips it
const_addr_store_not_folded_baseline_472 const-addr store computes add _,s11,addr; sw v,0(t) (not sw v,ADDR(s11)) const-address-fold
const_shift_uses_register_form_baseline_472 const shift uses register sll (not slli #shamt) immediate-shift-fold
nonparam_local_frame_spilled_baseline_472 non-param i32 local frame-spilled (sw _,off(sp)) local-promotion

Why

The RV32 path has no cargo byte-gate and no local RISC-V disassembler (flagged in #484). These baselines are the RISC-V analogue of the ARM-side spill/remat baselines: green today (assert what the selector emits now), and each flips when its lever lands default-on — so CI surfaces the codegen change as a deliberate, reviewed assertion update rather than silent drift on the un-byte-gated path.

cmp→select is out of scope for RV32IMAC (no conditional-move), so it has no baseline here.

Full RISC-V suite green (178 tests incl. these 3); fmt + clippy clean.

🤖 Generated with Claude Code

… levers (#472, #242)

Frozen-safe oracle-first baselines (no codegen change) for the RISC-V lever port
scoped in scripts/repro/riscv_lever_parity_472.md. Three in-tree selector tests
assert the CURRENT RV32 codegen for the patterns the levers target, validating the
scoping doc's source-read claims with executable evidence:

- const_addr_store_not_folded_baseline_472: a constant-address store computes
  `add _,s11,addr; sw v,0(t)` and does NOT fold to `sw v,ADDR(s11)`.
- const_shift_uses_register_form_baseline_472: a constant shift amount uses the
  register form `sll`, not `slli #shamt`.
- nonparam_local_frame_spilled_baseline_472: a non-param i32 local is frame-spilled
  (`sw _,off(sp)`), not register-homed.

These are the RISC-V analogue of the ARM-side spill/remat baselines. They are green
today (assert what the selector emits now) and each flips when its lever lands
default-on — so on the un-byte-gated RV32 path, CI surfaces the codegen change as a
deliberate, reviewed assertion update rather than silent drift. cmp→select is out
of scope for RV32IMAC (no conditional-move), so it has no baseline here.

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

codecov Bot commented Jun 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@avrabe avrabe merged commit 11c018d into main Jun 25, 2026
26 of 29 checks passed
@avrabe avrabe deleted the vcr-ra/472-rv-lever-baselines branch June 25, 2026 08:55
avrabe added a commit that referenced this pull request Jun 25, 2026
…#472, #242) (#486)

Traceability sync — the VCR-* roadmap's update logs had drifted behind the shipped
RISC-V lever-port prep. Records the RV32 lever-baseline slice (#472/#484/#485) under
VCR-ORACLE-001, its accurate home (it already logs the RV32 oracle slices: the
frozen-fixture byte gate and the cmp-select execution differential).

The entry captures: the three `*_baseline_472` selector tests pinning the current
pre-lever RV32 codegen at the RiscVOp-stream level (const-address store unfolded,
register-form shift, frame-spilled local), green today and flipping when each lever
lands default-on so a codegen change on the un-byte-gated RV32 path surfaces as a
reviewed assertion update; and the scoping finding that reshaped the port —
cmp->select is N/A for RV32IMAC (no conditional-move), so it is local-promotion +
immediate-shift-fold + a RISC-V-specific const-address-fold, not a 1:1 port.

Frozen-safe: a single description append + a `riscv` tag on an existing item; no
status change, no new links. rivet validate clean (0 non-cross-repo errors under the
CI gate). The ARM perf levers' roadmap reconciliation is deliberately left to a
focused pass rather than slotted into ambiguous homes here.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
avrabe added a commit that referenced this pull request Jun 25, 2026
…ccess immediate off s11, flag-off (#472, #242) (#491)

Loop-4 step 2 of the RISC-V lever-parity port (#472), the RISC-V analogue of the
ARM base-CSE address half (#468). A `i32.load/store (i32.const ADDR) …` lowers as
`addi a,zero,ADDR; add tmp,s11,a; lw/sw _,off(tmp)`; when `ADDR+off` fits the
signed-12-bit access immediate, `fold_const_addr` collapses it to a single
`lw/sw _,(ADDR+off)(s11)`, dropping the `add` and the address `addi` — 2
instructions per constant-address access.

Post-pass peephole (the structural twin of the #487 shift fold). Soundness:
  * `ADDR+off` is range-checked as a SUM against [-2048, 2047] (each term is
    already <=12 bits, so two in-range values can sum out of range);
  * the `add` base must be s11 and its address operand a `addi a,zero,ADDR`
    (single-`addi` small constant; a `lui+addi` large address stays the `add`
    form, out of v1 scope);
  * 3->1 rewrite, so BOTH dropped temps must be dead — `tmp` (add result) read
    only by the access, and `a` (address constant) read only by the `add`
    (rv_reg_dead_after + an untouched-between-def-and-use check); a bounds check
    between the add and the access reads `a` and disqualifies the fold.

Flag-off behind SYNTH_RV_ADDR_FOLD (default off => byte-identical to baseline, so
the frozen RV32 fixtures and `const_addr_store_not_folded_baseline_472` (#485)
stay green — frozen-safe). The on-target cycle win is validated before the flip.

Oracle (scripts/repro/const_addr_fold_riscv_differential.py, reusing the
redundant_base_materialization fixture): runs `init_fields` (7 constant-address
stores) under unicorn UC_ARCH_RISCV in both flag states; the resulting linear
MEMORY is bit-identical to wasmtime. Non-vacuity: .text 120B -> 64B (-56B = 14
instructions, 2 per store). CI-gated as an isolated `rv32-const-addr-fold-oracle`
job mirroring the shift-fold oracle. 5 unit tests (store/load fold, offset sum,
12-bit range guard, addr-reused decline). RV32 suite (189) + frozen byte gate
(ARM+RV32) green; fmt + clippy clean.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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