Skip to main content

Module peephole

Module peephole 

Source
Expand description

★ THE IR PEEPHOLE ★ — a semantics-preserving CompiledProgram → CompiledProgram transform: block-local forward copy-propagation followed by dead-move elimination. It exists for the backends that lower the bytecode straight to a final target with no downstream optimizing assembler — RISC-V asm, WASM, the spatial fabric. gcc already performs exactly this coalescing for the C tier (register-to-register moves fold away, dead copies vanish), so C does not need it; the flat backends ship the VM compiler’s move cascades verbatim without it.

The measured target is the swap idiom. Set a to b. Set b to t. lowers to a five-move cascade through fresh temps every loop iteration:

  Move R10 = R8   Move R11 = R3   Move R1 = R11   Move R12 = R10   Move R3 = R12

Copy-propagation rewrites the temp reads to their roots and the now-dead temp moves fall to DCE, leaving the optimal Move R1 = R3. Move R3 = R8. — three fewer ops in the hottest loop, per iteration.

§Soundness — the asymmetry that makes it safe

A wrong coalesce miscompiles every backend, so the register model is deliberately one-sided:

  • reads is a superset of the true reads (over-approximate). Liveness can then never under-count a use, so a still-needed value is never judged dead.
  • kills is a subset of the registers an op FULLY overwrites (under-approximate). Liveness can then never over-count a def, so a live range is never cut short.
  • clobbers = kills ∪ mutates invalidates a copy on BOTH its key and its value side. This is what keeps copy-propagation sound under LOGOS’s value-semantics collections: after Move x = list, mutating OR reassigning list must kill the x = list fact, because a copy-on-write push makes x and list diverge.
  • The in-place-mutated collection/struct register is never rewritable — pushing to x (a copy of list) is not the same as pushing to list once value semantics clone on write, so a read that is really an in-place mutation site is left untouched.
  • Only Move ops are ever deleted (their semantics are total and side-effect free); and only when the destination is provably dead or the move is a self-copy.

Every register classifier below is EXHAUSTIVE on Op (no _ arm): a newly added instruction fails to compile until it is classified, so no op can silently escape the model. peephole_soundness_lock proves program_outcome(peephole(P)) == program_outcome(P) over the corpus + a fuzzer, and that the op count strictly drops on the swap-idiom programs.

Functions§

peephole
Run the peephole to a fixpoint, in place. Copy-propagate once (a single forward pass fully resolves within-block chains, because the copy map stores roots), then iterate liveness + dead-move elimination until no move is removed.