code wiki / _hdl_build / nx_regalloc_interp.nx
nx_regalloc_interp.nx
buildroot/runtime/_hdl_build/nx_regalloc_interp.nx
about
nx_regalloc_interp.nx -- EXECUTION-equivalence verifier for register allocation.
The static soundness checker (nx_regalloc_linscan: no two live vregs share a
register) is necessary but the absorption gate wants more: PROVE that code run
THROUGH the allocation (values living in physical registers + spill slots)
computes the IDENTICAL result to the reference (one slot per value). Two
interpreters, compared 1:1 over many inputs -- if they ever diverge, the
allocation miscompiled (the g1 failure, caught before it can ship).
The IR carries real opcodes so the interpretation is meaningful (it computes the
race kernel's actual arithmetic). live-out values (loop-carried) are kept live to
the block end so they remain readable -- exactly how a real backend treats them.
dependencies 1 imports · 3 importers
imports: nx_regalloc_linscan.nx
imported by: nx_regalloc_absorb_governed_test.nxnx_regalloc_calls.nxnx_regalloc_exec_test.nx
structs
| none |
consts
| 16 | const ROP_INPUT: i64 = 0 // imm = input index |
| 17 | const ROP_MUL_IMM: i64 = 1 |
| 18 | const ROP_ADD_IMM: i64 = 2 |
| 19 | const ROP_SHR_IMM: i64 = 3 |
| 20 | const ROP_XOR: i64 = 4 |
| 21 | const ROP_AND_IMM: i64 = 5 |
| 22 | const ROP_ADD: i64 = 6 |
| 23 | const ROP_LT_IMM: i64 = 7 |
| 25 | const RI_SPILL: i64 = 0 - 1 |
functions
| 27 | func ri_op_eval(op: i64, a: i64, b: i64, imm: i64) -> i64 |
| 39 | func ri_get(v: i64, alloc: *i64, regf: *i64, spill: *i64) -> i64 |
| 46 | func ri_interp_ref(n: i64, op: *i64, u0: *i64, u1: *i64, imm: *i64, inputs: *i64, |
| 66 | func ri_interp_alloc(n: i64, nreg: i64, op: *i64, u0: *i64, u1: *i64, imm: *i64, |