Duplicate pure instructions survive to emit: the builder's CSE cache is per-block and resets at block boundaries (build.rs:99-111); LocalAddr is excluded even in-block citing an emit fusion that no longer exists (build.rs:56-62 — stale; emit_load reads the address from its register, x86_64/emit.rs:3747, aarch64/emit.rs:4619); inliner splices re-duplicate values post-build. dedup_imm covers only ImmData/ImmCode/TlsAddr vs an entry-block canonical; nothing merges Binop/BinopI/Extend/LocalAddr across blocks. Sizing: 21-23% of post-pipeline insts are dominator-VN duplicates (sqlite 58k/261k, quickjs 42k/200k), ~2/3 Imm constants.
Measured with a working prototype pass (passes cargo test --release --lib and fixture parity): the GATED config wins or ties everywhere on host arm64 — quickjs −1.4..2.1%, compress −1.2..1.7%, qsort −1.5..1.6%, sqlite_bench −1.5%, stb −1.1%, crypto −0.7%; verifier re-run reproduces direction on all, magnitudes ~0.3-0.7pp lower. This is a 1-2% class lever: the OoO core hides most 1-insn rematerializations.
GATE (load-bearing; the LICM hoist-then-spill lesson): merge same-block always; cross-block only when NO call sits between leader and dup AND dom-depth delta <= 3; Imm merges same-block ONLY (cross-block Imm merging showed pessimization signals: stb +2.2-3.0% reproduced, static spill slots +16-23%). Constants may be relaxed only after the spill-cost-ordering allocator work (#356).
Design: passes/cse.rs (~230 LOC, prototype exists): iterative dom-tree DFS (dominators at mem2reg.rs:141) with scoped map Key{LocalAddr(off), Imm(k), Binop(op, sorted vnL/vnR), BinopI, Extend, Fneg, FpCast} -> leader; operands resolve through the vn map (transitive canonicalization); redirect uses as dedup_imm.rs:106-141 does; dead dups swept by the existing is_dead_pure skip. Position: after index_fold, before store_forward (pre-fold merging can block index_fold's same-width disp fold; base canonicalization feeds store_forward). Keep dedup_imm (binding-aware keys). Compile cost measured ~+1.4% on the quickjs TU.
Duplicate pure instructions survive to emit: the builder's CSE cache is per-block and resets at block boundaries (build.rs:99-111); LocalAddr is excluded even in-block citing an emit fusion that no longer exists (build.rs:56-62 — stale; emit_load reads the address from its register, x86_64/emit.rs:3747, aarch64/emit.rs:4619); inliner splices re-duplicate values post-build. dedup_imm covers only ImmData/ImmCode/TlsAddr vs an entry-block canonical; nothing merges Binop/BinopI/Extend/LocalAddr across blocks. Sizing: 21-23% of post-pipeline insts are dominator-VN duplicates (sqlite 58k/261k, quickjs 42k/200k), ~2/3 Imm constants.
Measured with a working prototype pass (passes cargo test --release --lib and fixture parity): the GATED config wins or ties everywhere on host arm64 — quickjs −1.4..2.1%, compress −1.2..1.7%, qsort −1.5..1.6%, sqlite_bench −1.5%, stb −1.1%, crypto −0.7%; verifier re-run reproduces direction on all, magnitudes ~0.3-0.7pp lower. This is a 1-2% class lever: the OoO core hides most 1-insn rematerializations.
GATE (load-bearing; the LICM hoist-then-spill lesson): merge same-block always; cross-block only when NO call sits between leader and dup AND dom-depth delta <= 3; Imm merges same-block ONLY (cross-block Imm merging showed pessimization signals: stb +2.2-3.0% reproduced, static spill slots +16-23%). Constants may be relaxed only after the spill-cost-ordering allocator work (#356).
Design: passes/cse.rs (~230 LOC, prototype exists): iterative dom-tree DFS (dominators at mem2reg.rs:141) with scoped map Key{LocalAddr(off), Imm(k), Binop(op, sorted vnL/vnR), BinopI, Extend, Fneg, FpCast} -> leader; operands resolve through the vn map (transitive canonicalization); redirect uses as dedup_imm.rs:106-141 does; dead dups swept by the existing is_dead_pure skip. Position: after index_fold, before store_forward (pre-fold merging can block index_fold's same-width disp fold; base canonicalization feeds store_forward). Keep dedup_imm (binding-aware keys). Compile cost measured ~+1.4% on the quickjs TU.