From f1652f122df4de17195598e3257d6528c79a314d Mon Sep 17 00:00:00 2001 From: Ralf Anton Beier Date: Wed, 24 Jun 2026 05:49:32 +0200 Subject: [PATCH] =?UTF-8?q?feat(vcr-sel):=20ship=20cmp=E2=86=92select=20fu?= =?UTF-8?q?sion=20default-on=20=E2=80=94=20v0.13.0=20(VCR-SEL-004,=20#428,?= =?UTF-8?q?=20#242)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The byte-changing default-on flip the cmp→select arc has been building toward. ARM compare→select lowering now predicates the moves on the compare's own flags (`cmp; mov{c}; mov{invert(c)}`) instead of materializing+re-testing a boolean, −2 insns/select. .text shrinks on every function with a select (control_step 354→324, flight_seam 1016→902, flight_seam_flat 1240→1122; −262 B across the frozen fixtures); gale measured gust_mix 2.375×→2.125× vs LLVM. Results preserved — validated three independent ways BEFORE shipping: 1. named-anchor differentials re-run with fusion ON, same commit as the re-freeze: control_step still 0x00210A55 (13/13), flat+inlined flight_algo still 0x07FDF307. 2. unicorn execution oracle running the two-move mov{invert(c)} arm (cmp-select- oracle CI job, 11/11 off==on==wasmtime) — its unfused baseline now opts out via SYNTH_NO_CMP_SELECT_FUSE. 3. gale's gale_decider_diff sweep: 8 verified primitives, 10,596 cases, native ≡ unfused ≡ fused. - arm_backend.rs: fusion default-on; escape hatch SYNTH_NO_CMP_SELECT_FUSE=1. - frozen_codegen_bytes.rs: ARM goldens re-frozen to the fused .text (RV32 + signed_div_const unchanged — fusion is ARM-only / 0 sites); harness now locks the shipped (fused) path and removes the opt-out var. - version 0.12.0 → 0.13.0 (pin sweep: all path-deps + MODULE.bazel); CHANGELOG; VCR-SEL-004 status approved → implemented. Pending follow-up (gale, post-ship): on-silicon G474RE DWT cycle no-regression — user waived it as a release gate in favor of the qemu+sweep+oracle evidence. Co-Authored-By: Claude Opus 4.8 --- CHANGELOG.md | 23 +++++++++++++ Cargo.lock | 34 +++++++++---------- Cargo.toml | 2 +- MODULE.bazel | 2 +- artifacts/verified-codegen-roadmap.yaml | 11 +++++- crates/synth-backend-awsm/Cargo.toml | 2 +- crates/synth-backend-riscv/Cargo.toml | 4 +-- crates/synth-backend-wasker/Cargo.toml | 2 +- crates/synth-backend/Cargo.toml | 4 +-- crates/synth-backend/src/arm_backend.rs | 19 +++++++---- crates/synth-cli/Cargo.toml | 16 ++++----- .../synth-cli/tests/frozen_codegen_bytes.rs | 31 ++++++++++------- crates/synth-frontend/Cargo.toml | 2 +- crates/synth-opt/Cargo.toml | 2 +- crates/synth-synthesis/Cargo.toml | 6 ++-- crates/synth-verify/Cargo.toml | 8 ++--- .../repro/cmp_select_two_move_differential.py | 6 +++- 17 files changed, 111 insertions(+), 63 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8d9def4..f3a30fe0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.13.0] - 2026-06-24 + +**cmp→select fusion is now DEFAULT-ON (VCR-SEL-004, #428, epic #242).** The ARM +backend's compare→select lowering no longer materializes a boolean and re-tests +it (`cmp; SetCond; cmp #0; movne; moveq`); it predicates the moves directly on +the compare's own flags (`cmp; mov{c}; mov{invert(c)}`), −2 instructions per +select. This is a **byte-changing** release: `.text` shrinks on every function +with a select (control_step 354→324 B, flight_seam 1016→902, flight_seam_flat +1240→1122; −262 B across the frozen fixtures), and gale's `gust_mix` measured +2.375×→2.125× vs LLVM with a 132→116 B function. + +Execution **results are preserved** — validated three ways before shipping: (1) +the named-anchor differentials re-run with fusion on (control_step still +`0x00210A55`, flat+inlined flight_algo still `0x07FDF307`); (2) a unicorn +execution oracle that runs the two-move `mov{invert(c)}` arm (`cmp-select-oracle` +CI job, 11/11 result-identical); (3) gale's `gale_decider_diff` sweep across all +8 verified primitives (10,596 cases, native ≡ unfused ≡ fused). The byte gates +were re-frozen to the fused `.text` on this commit. + +**Escape hatch:** `SYNTH_NO_CMP_SELECT_FUSE=1` reverts to the pre-fusion lowering. +**Pending follow-up:** the on-silicon G474RE DWT cycle no-regression check is +tracked post-ship (gale); the qemu `-icount` proxy showed a monotonic win. + ## [0.12.0] - 2026-06-23 **DWARF SOURCE-LINE DEBUGGING — `--debug-line` (VCR-DBG-001, #394, epic #242).** diff --git a/Cargo.lock b/Cargo.lock index 56373201..3eb52860 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2023,14 +2023,14 @@ dependencies = [ [[package]] name = "synth-abi" -version = "0.12.0" +version = "0.13.0" dependencies = [ "synth-wit", ] [[package]] name = "synth-analysis" -version = "0.12.0" +version = "0.13.0" dependencies = [ "anyhow", "synth-core", @@ -2039,7 +2039,7 @@ dependencies = [ [[package]] name = "synth-backend" -version = "0.12.0" +version = "0.13.0" dependencies = [ "anyhow", "synth-core", @@ -2049,7 +2049,7 @@ dependencies = [ [[package]] name = "synth-backend-awsm" -version = "0.12.0" +version = "0.13.0" dependencies = [ "anyhow", "synth-core", @@ -2058,7 +2058,7 @@ dependencies = [ [[package]] name = "synth-backend-riscv" -version = "0.12.0" +version = "0.13.0" dependencies = [ "anyhow", "proptest", @@ -2070,7 +2070,7 @@ dependencies = [ [[package]] name = "synth-backend-wasker" -version = "0.12.0" +version = "0.13.0" dependencies = [ "anyhow", "synth-core", @@ -2079,11 +2079,11 @@ dependencies = [ [[package]] name = "synth-cfg" -version = "0.12.0" +version = "0.13.0" [[package]] name = "synth-cli" -version = "0.12.0" +version = "0.13.0" dependencies = [ "anyhow", "clap", @@ -2108,7 +2108,7 @@ dependencies = [ [[package]] name = "synth-core" -version = "0.12.0" +version = "0.13.0" dependencies = [ "anyhow", "gimli", @@ -2122,7 +2122,7 @@ dependencies = [ [[package]] name = "synth-frontend" -version = "0.12.0" +version = "0.13.0" dependencies = [ "anyhow", "synth-core", @@ -2136,14 +2136,14 @@ dependencies = [ [[package]] name = "synth-memory" -version = "0.12.0" +version = "0.13.0" dependencies = [ "bitflags", ] [[package]] name = "synth-opt" -version = "0.12.0" +version = "0.13.0" dependencies = [ "criterion", "synth-cfg", @@ -2151,11 +2151,11 @@ dependencies = [ [[package]] name = "synth-qemu" -version = "0.12.0" +version = "0.13.0" [[package]] name = "synth-synthesis" -version = "0.12.0" +version = "0.13.0" dependencies = [ "anyhow", "proptest", @@ -2170,7 +2170,7 @@ dependencies = [ [[package]] name = "synth-test" -version = "0.12.0" +version = "0.13.0" dependencies = [ "anyhow", "clap", @@ -2186,7 +2186,7 @@ dependencies = [ [[package]] name = "synth-verify" -version = "0.12.0" +version = "0.13.0" dependencies = [ "anyhow", "chrono", @@ -2204,7 +2204,7 @@ dependencies = [ [[package]] name = "synth-wit" -version = "0.12.0" +version = "0.13.0" [[package]] name = "tempfile" diff --git a/Cargo.toml b/Cargo.toml index 6a611079..63b7a44f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ resolver = "2" # semver to publish, so the convention now catches up: workspace # version follows the release tag, bumped pre-tag in the release # checklist. See docs/release-process.md. -version = "0.12.0" +version = "0.13.0" edition = "2024" rust-version = "1.88" authors = ["PulseEngine Team"] diff --git a/MODULE.bazel b/MODULE.bazel index 3624839e..5cc842a4 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -7,7 +7,7 @@ module( name = "synth", # Kept in lockstep with [workspace.package] version in Cargo.toml. # Both are bumped pre-tag — see docs/release-process.md. - version = "0.12.0", + version = "0.13.0", ) # Bazel dependencies diff --git a/artifacts/verified-codegen-roadmap.yaml b/artifacts/verified-codegen-roadmap.yaml index a955aa0a..6c818eca 100644 --- a/artifacts/verified-codegen-roadmap.yaml +++ b/artifacts/verified-codegen-roadmap.yaml @@ -737,7 +737,16 @@ artifacts: exhaustive sweep); precond (2) (G474RE silicon no-regression) still OWED — gale's bench is thumbv7m/qemu today — flip stays held on it (user call 2026-06-23: keep the silicon gate; close the exec gap first). - status: approved + FLIP SHIPPED v0.13.0 (2026-06-24, #428): default-on landed. User authorized + shipping on the qemu+sweep+oracle evidence and WAIVING precond (2) for the + release (gale takes the on-silicon G474RE DWT no-regression as a tracked + post-ship follow-up). Re-froze the fused .text on the same commit the + named-anchor differentials were re-run on (control_step preserved 0x00210A55, + flat+inlined flight_algo preserved 0x07FDF307; .text −262 B across the frozen + fixtures). Escape hatch SYNTH_NO_CMP_SELECT_FUSE=1 reverts the lowering. + SCOPE: the select half shipped; the br_if→predicated-branch half remains a + separate follow-up (branch consumers unmodeled by reg_effect). + status: implemented tags: [codegen, selector, peephole, compare-select, flag-fusion, gale-209, perf, track-b, vcr-oracle-001] links: - type: derives-from diff --git a/crates/synth-backend-awsm/Cargo.toml b/crates/synth-backend-awsm/Cargo.toml index 24c9c9f7..5e938e10 100644 --- a/crates/synth-backend-awsm/Cargo.toml +++ b/crates/synth-backend-awsm/Cargo.toml @@ -11,6 +11,6 @@ categories.workspace = true description = "aWsm backend integration for the Synth compiler" [dependencies] -synth-core = { path = "../synth-core", version = "0.12.0" } +synth-core = { path = "../synth-core", version = "0.13.0" } anyhow.workspace = true thiserror.workspace = true diff --git a/crates/synth-backend-riscv/Cargo.toml b/crates/synth-backend-riscv/Cargo.toml index 1622b628..bcf6d7a9 100644 --- a/crates/synth-backend-riscv/Cargo.toml +++ b/crates/synth-backend-riscv/Cargo.toml @@ -11,8 +11,8 @@ categories.workspace = true description = "RISC-V encoder, ELF builder, PMP allocator, and bare-metal startup for synth" [dependencies] -synth-core = { path = "../synth-core", version = "0.12.0" } -synth-synthesis = { path = "../synth-synthesis", version = "0.12.0" } +synth-core = { path = "../synth-core", version = "0.13.0" } +synth-synthesis = { path = "../synth-synthesis", version = "0.13.0" } anyhow.workspace = true thiserror.workspace = true tracing.workspace = true diff --git a/crates/synth-backend-wasker/Cargo.toml b/crates/synth-backend-wasker/Cargo.toml index 95fecc51..2417d906 100644 --- a/crates/synth-backend-wasker/Cargo.toml +++ b/crates/synth-backend-wasker/Cargo.toml @@ -11,6 +11,6 @@ categories.workspace = true description = "Wasker backend integration for the Synth compiler" [dependencies] -synth-core = { path = "../synth-core", version = "0.12.0" } +synth-core = { path = "../synth-core", version = "0.13.0" } anyhow.workspace = true thiserror.workspace = true diff --git a/crates/synth-backend/Cargo.toml b/crates/synth-backend/Cargo.toml index b53ea728..3ac958a2 100644 --- a/crates/synth-backend/Cargo.toml +++ b/crates/synth-backend/Cargo.toml @@ -15,7 +15,7 @@ default = ["arm-cortex-m"] arm-cortex-m = ["synth-synthesis"] [dependencies] -synth-core = { path = "../synth-core", version = "0.12.0" } -synth-synthesis = { path = "../synth-synthesis", version = "0.12.0", optional = true } +synth-core = { path = "../synth-core", version = "0.13.0" } +synth-synthesis = { path = "../synth-synthesis", version = "0.13.0", optional = true } anyhow.workspace = true thiserror.workspace = true diff --git a/crates/synth-backend/src/arm_backend.rs b/crates/synth-backend/src/arm_backend.rs index 3322731e..babf774d 100644 --- a/crates/synth-backend/src/arm_backend.rs +++ b/crates/synth-backend/src/arm_backend.rs @@ -433,15 +433,20 @@ fn compile_wasm_to_arm( // sound (flags reused only when nothing clobbers them in the window; the // boolean deleted only when provably dead) — see `fuse_cmp_select`. // - // BEHIND `SYNTH_CMP_SELECT_FUSE=1` while it is validated against the - // differential oracle + gale's on-target gust_codegen_bench (G474RE). Off by - // default ⇒ a literal no-op ⇒ every fixture stays bit-identical - // (control_step 0x00210A55 / flat+inlined flight_algo 0x07FDF307 / divseam). - // The default-on flip is the held byte-changing step, gated on silicon. - let arm_instrs = if std::env::var("SYNTH_CMP_SELECT_FUSE").is_ok() { + // DEFAULT-ON as of v0.13.0 (#428): cmp→select fusion ships by default. The + // byte-changing flip is validated by (a) the unicorn execution oracle that runs + // the two-move `mov{invert(c)}` arm (cmp_select_two_move_differential.py), (b) + // gale's gale_decider_diff 10,596-case sweep across all 8 verified primitives + // (native ≡ flag-off ≡ flag-on = 0x88e73178d232bcf5), and (c) the named-anchor + // differentials re-run with fusion ON — control_step still 0x00210A55, flat+ + // inlined flight_algo still 0x07FDF307 (results preserved; bytes deliberately + // changed, re-frozen on this commit). Escape hatch: `SYNTH_NO_CMP_SELECT_FUSE=1` + // reverts to the pre-fusion lowering. The on-silicon G474RE DWT no-regression + // check is a tracked post-ship follow-up (gale owns it). + let arm_instrs = if std::env::var("SYNTH_NO_CMP_SELECT_FUSE").is_err() { // The rewritten stream is identical to `fuse_cmp_select`'s 2-tuple form; // the extra `two_move` count is diagnostic only (the fusion census / - // blast-radius datum for the flip decision — #7 made that arm reachable). + // blast-radius datum — #7 made that arm reachable). let (out, fused, two_move) = synth_synthesis::liveness::fuse_cmp_select_with_stats(&arm_instrs); if std::env::var("SYNTH_FUSE_STATS").is_ok() { diff --git a/crates/synth-cli/Cargo.toml b/crates/synth-cli/Cargo.toml index 7e2b8a35..47968363 100644 --- a/crates/synth-cli/Cargo.toml +++ b/crates/synth-cli/Cargo.toml @@ -27,18 +27,18 @@ verify = ["synth-verify"] # Path deps carry `version` so `cargo publish` rewrites them to the # crates.io coordinate. Bumping the workspace version requires # updating these in lockstep — see docs/release-process.md. -synth-core = { path = "../synth-core", version = "0.12.0" } -synth-frontend = { path = "../synth-frontend", version = "0.12.0" } -synth-synthesis = { path = "../synth-synthesis", version = "0.12.0" } -synth-backend = { path = "../synth-backend", version = "0.12.0" } +synth-core = { path = "../synth-core", version = "0.13.0" } +synth-frontend = { path = "../synth-frontend", version = "0.13.0" } +synth-synthesis = { path = "../synth-synthesis", version = "0.13.0" } +synth-backend = { path = "../synth-backend", version = "0.13.0" } # Optional external backends -synth-backend-awsm = { path = "../synth-backend-awsm", version = "0.12.0", optional = true } -synth-backend-wasker = { path = "../synth-backend-wasker", version = "0.12.0", optional = true } -synth-backend-riscv = { path = "../synth-backend-riscv", version = "0.12.0", optional = true } +synth-backend-awsm = { path = "../synth-backend-awsm", version = "0.13.0", optional = true } +synth-backend-wasker = { path = "../synth-backend-wasker", version = "0.13.0", optional = true } +synth-backend-riscv = { path = "../synth-backend-riscv", version = "0.13.0", optional = true } # Optional verification (requires z3) -synth-verify = { path = "../synth-verify", version = "0.12.0", optional = true, features = ["z3-solver", "arm"] } +synth-verify = { path = "../synth-verify", version = "0.13.0", optional = true, features = ["z3-solver", "arm"] } # Optional PulseEngine WASM optimizer # Uncomment when loom crate is available: diff --git a/crates/synth-cli/tests/frozen_codegen_bytes.rs b/crates/synth-cli/tests/frozen_codegen_bytes.rs index 915bbcdc..aa07b99c 100644 --- a/crates/synth-cli/tests/frozen_codegen_bytes.rs +++ b/crates/synth-cli/tests/frozen_codegen_bytes.rs @@ -55,15 +55,16 @@ fn fixture(name: &str) -> std::path::PathBuf { /// Compile a frozen fixture for `(backend, target)` with the exact `--all-exports /// --relocatable` config the `.py` differentials use, and return the SHA-256 hex -/// of its `.text` and the section length. `SYNTH_CMP_SELECT_FUSE` / `SYNTH_CONST_CSE` -/// are explicitly removed so an enabled-in-the-environment flag can never silently -/// re-freeze the gate — it locks the SHIPPED, flag-off lowering. The `object` -/// crate reads `.text` arch-agnostically (ARM Thumb-2 and RV32 alike). +/// of its `.text` and the section length. `SYNTH_NO_CMP_SELECT_FUSE` (the v0.13.0 +/// cmp→select opt-out) / `SYNTH_CONST_CSE` are explicitly removed so a flag set in +/// the environment can never silently re-freeze the gate — it locks the SHIPPED +/// lowering, which since v0.13.0 INCLUDES cmp→select fusion (default-on). The +/// `object` crate reads `.text` arch-agnostically (ARM Thumb-2 and RV32 alike). fn text_sha256(wasm: &str, backend: &str, target: &str) -> (String, usize) { let path = fixture(wasm); let elf = format!("/tmp/frozenbytes_{backend}_{wasm}.elf"); let out = Command::new(synth()) - .env_remove("SYNTH_CMP_SELECT_FUSE") + .env_remove("SYNTH_NO_CMP_SELECT_FUSE") .env_remove("SYNTH_CONST_CSE") .args([ "compile", @@ -125,24 +126,30 @@ fn assert_frozen(cases: &[(&str, &str, usize)], backend: &str, target: &str) { /// the `.py` differentials cover): control_step ↔ 0x00210A55, flight_seam_flat ↔ /// flat+inlined flight_algo 0x07FDF307, plus flight_seam and the div seam. /// -/// Goldens derived on main @ ef97f86 (post-#444 cmp→select, flag-off), 2026-06-23. +/// Goldens RE-FROZEN for v0.13.0 (#428): cmp→select fusion is now default-on, so +/// these lock the FUSED .text. The execution RESULTS are preserved — re-verified on +/// this commit with fusion on: control_step still 0x00210A55 (control_step_differential +/// .py 13/13), flat+inlined flight_algo still 0x07FDF307 (flight_seam_differential.py +/// MATCH). .text shrank: control_step 354→324, flight_seam 1016→902, flight_seam_flat +/// 1240→1122 (−262 B total); signed_div_const (0 fusion sites) unchanged. Prior +/// flag-off goldens were on main @ ef97f86 (post-#444), 2026-06-23. #[test] fn frozen_fixtures_text_is_bit_identical_oracle_001() { let cases = [ ( "control_step.wasm", - "5efa58ca2667fb2f910b5ebf0ef8020a7fc1b9224f3ec070e9e0028de9d83a57", - 354usize, + "b4c4c290be2c8a83055d4c9696ae4ebb16486a8fd3fc268531607eeef35325e5", + 324usize, ), ( "flight_seam.wasm", - "1f39b77b65f0695693deda9ee56e3a7fb3af4127858a8ac6c3ce0fd3398de516", - 1016, + "300fdf3b92a0941da63b3215441a799d9b32ef942fd404b4803a83a6efb1bb60", + 902, ), ( "flight_seam_flat.wasm", - "f6244f35f932aac7661b9ed1cbf70dc1b5353a9f5c03178ebad3a38a891d7b8f", - 1240, + "23d0b6829414a855f365d84c7c3301c256f1843fe46b2cc9b369fec30610913d", + 1122, ), ( "signed_div_const.wasm", diff --git a/crates/synth-frontend/Cargo.toml b/crates/synth-frontend/Cargo.toml index a55e8ec8..2208e1ff 100644 --- a/crates/synth-frontend/Cargo.toml +++ b/crates/synth-frontend/Cargo.toml @@ -14,7 +14,7 @@ description = "WASM/WAT parser and module decoder frontend for the Synth compile # Internal path deps carry an explicit version so `cargo publish` # can rewrite to the crates.io coordinate. `path` is used for # in-workspace builds; `version` is what crates.io sees. -synth-core = { path = "../synth-core", version = "0.12.0" } +synth-core = { path = "../synth-core", version = "0.13.0" } wasmparser.workspace = true wasm-encoder.workspace = true diff --git a/crates/synth-opt/Cargo.toml b/crates/synth-opt/Cargo.toml index 254b5207..516138fe 100644 --- a/crates/synth-opt/Cargo.toml +++ b/crates/synth-opt/Cargo.toml @@ -11,7 +11,7 @@ categories.workspace = true description = "Peephole optimization passes for the Synth compiler" [dependencies] -synth-cfg = { path = "../synth-cfg", version = "0.12.0" } +synth-cfg = { path = "../synth-cfg", version = "0.13.0" } [dev-dependencies] criterion = { version = "0.8", features = ["html_reports"] } diff --git a/crates/synth-synthesis/Cargo.toml b/crates/synth-synthesis/Cargo.toml index 583a24ff..eab6db1d 100644 --- a/crates/synth-synthesis/Cargo.toml +++ b/crates/synth-synthesis/Cargo.toml @@ -11,9 +11,9 @@ categories.workspace = true description = "WASM-to-ARM instruction selection and peephole optimizer" [dependencies] -synth-core = { path = "../synth-core", version = "0.12.0" } -synth-cfg = { path = "../synth-cfg", version = "0.12.0" } -synth-opt = { path = "../synth-opt", version = "0.12.0" } +synth-core = { path = "../synth-core", version = "0.13.0" } +synth-cfg = { path = "../synth-cfg", version = "0.13.0" } +synth-opt = { path = "../synth-opt", version = "0.13.0" } serde.workspace = true anyhow.workspace = true thiserror.workspace = true diff --git a/crates/synth-verify/Cargo.toml b/crates/synth-verify/Cargo.toml index 9fdfa30e..37917f8a 100644 --- a/crates/synth-verify/Cargo.toml +++ b/crates/synth-verify/Cargo.toml @@ -17,12 +17,12 @@ arm = ["synth-synthesis"] [dependencies] # Core dependencies (always required) -synth-core = { path = "../synth-core", version = "0.12.0" } -synth-cfg = { path = "../synth-cfg", version = "0.12.0" } -synth-opt = { path = "../synth-opt", version = "0.12.0" } +synth-core = { path = "../synth-core", version = "0.13.0" } +synth-cfg = { path = "../synth-cfg", version = "0.13.0" } +synth-opt = { path = "../synth-opt", version = "0.13.0" } # ARM synthesis (optional, behind 'arm' feature) -synth-synthesis = { path = "../synth-synthesis", version = "0.12.0", optional = true } +synth-synthesis = { path = "../synth-synthesis", version = "0.13.0", optional = true } # SMT solver for formal verification z3 = { version = "0.19", features = ["static-link-z3"], optional = true } diff --git a/scripts/repro/cmp_select_two_move_differential.py b/scripts/repro/cmp_select_two_move_differential.py index 0aa49680..cfaac016 100755 --- a/scripts/repro/cmp_select_two_move_differential.py +++ b/scripts/repro/cmp_select_two_move_differential.py @@ -74,10 +74,14 @@ def arm_branch(a, b): def compile_elf(out, fused): + # As of v0.13.0 cmp→select fusion is DEFAULT-ON, so the unfused baseline must + # opt OUT (SYNTH_NO_CMP_SELECT_FUSE); the fused build is just the default plus + # stats. (Pre-v0.13.0 this was inverted: fused opted IN via SYNTH_CMP_SELECT_FUSE.) env = {"PATH": "/usr/bin:/bin"} if fused: - env["SYNTH_CMP_SELECT_FUSE"] = "1" env["SYNTH_FUSE_STATS"] = "1" + else: + env["SYNTH_NO_CMP_SELECT_FUSE"] = "1" r = subprocess.run( [SYNTH, "compile", WASM, "-o", out, "--target", "cortex-m4", "--all-exports", "--relocatable"],