hipfire
/learn · kernels · certification

PeaceMaker: certified kernels

A compiler hands you a code object. It does not hand you a proof that every memory wait is in place, that no two waves race through shared memory, or that the hardware's instruction hazards are covered. On RDNA those are the programmer's problem, and the bugs they cause are intermittent.

PeaceMaker (PM) is hipfire's own kernel authoring and assembly path. It writes RDNA code objects itself, reads them back byte for byte, and checks them before they ship. In 0.4.1 several of Flash-Next's hottest prefill kernels run from PM-built modules by default, each one a byte-identical replacement for the hipcc kernel it displaces.

01 What can go wrong below the compiler

the idea

RDNA issues memory operations asynchronously. A load or an LDS store returns immediately and increments a counter; the program must wait on that counter (s_waitcnt on gfx11, s_wait_dscnt and friends on gfx12) before it reads the result, or before a barrier tells other waves the data is ready. Some instruction pairs also need a gap between them (s_delay_alu, s_wait_alu guards). Get one wrong and the kernel still runs, usually gives the right answer, and occasionally does not.

fig · the bug class: an LDS store not drained before the barrier that publishes it
  wave A                         wave B
  ds_store  [slot 0] ← x          ·
  ·  (store still in flight)      ·
  s_barrier  ───────────────────  s_barrier
                                  ds_load  [slot 0]   ← may read the old value
  fix:  s_waitcnt lgkmcnt(0)  (gfx11) / s_wait_dscnt 0 (gfx12)  before s_barrier

hipfire has hit exactly this class in production kernels: a Strix Halo verify-attention co-residency race and a gfx11 FA2 mailbox race. 0.4.1 also adds explicit store waits before every LDS-only barrier in the Gated DeltaNet kernels.

02 The PM pipeline

how hipfire does it
fig · from kernel source to a certified module
authorkernel written in Rust, run at build time, through a typed core
buildchecked builder keeps a wait ledger, LDS slot states and hazard trackers per instruction
emitnative code object v6, no ROCm assembler, linker or bundler
liftdecode every word, re-encode, re-emit: must equal the input byte for byte
certifywhole-program wait, hazard, barrier and LDS-bounds checks; any obligation fails

Author: races as type errors

peacemaker-author puts types in front of the builder. Targets are types (Gfx1100, Gfx1151, Gfx1201); an LDS region carries its ownership state (Free, Writing, Published); a store returns a Pending token that must become Drained before the barrier that publishes it; a loop must carry the same state on entry and on its back edge. The two production races above are now rustc compile errors, pinned by compile-fail tests. The types emit nothing of their own, so kernels ported onto this core re-emit byte-identical assembly.

Build and emit: no ROCm in the path

The builder lowers each instruction through hipfire's own gfx11/gfx12 encoding tables and writes the whole code object: .text, the 64-byte kernel descriptors, the MessagePack AMDGPU metadata note, symbol and dynamic tables, and the offload-bundle wrapper. The ROCm assembler/linker path survives only as a test oracle. Across every PM-emitted symbol on gfx1100, gfx1151 and gfx1201 (55 symbols, as 55 single-symbol objects and 12 modules), every section other than the version-stamp comment is byte-identical to what llvm-mc + ld.lld + clang-offload-bundler produce.

Lift: the bytes are the proof

peacemaker-lift turns a code object back into a typed program: every instruction word is decoded through pinned opcode tables (unknown encodings are rejected), re-encoded from its typed fields and compared word for word, and the module is re-emitted and must equal the input byte for byte. Analyses then run on exactly the bytes that ship, not on a source that might compile differently.

Certify: pm_check

  • wait replay over the gfx11 VM / LGKM / VS counters (and the gfx12 equivalents), across the control-flow graph and loop back-edges;
  • hazard replay: gfx1100 transcendental use, VCMPX → PERMLANE, WMMA chaining, joined over back-edges;
  • barrier pairing and the rule that every LDS store is drained before a barrier;
  • s_clause / s_delay_alu windows and register resources;
  • lds_bounds: every LDS address is evaluated for every lane of every wave of the workgroup, and every access must end inside the launch allocation.

Any open obligation fails certification. The shipped QSA and MQ6 modules certify with zero obligations.

03 Twins: same math, better schedule

how hipfire does it

A PM kernel that replaces a hipcc kernel is written as an exact twin: the same unpack, the same dequantization instructions, the same WMMA lane map and the same ascending accumulation chain per output. Only tiling and scheduling change. The gfx1201 MQ6 trunk GEMM is a good example:

hipcc kernelPM twin
work per waveone dequant feeds 8 WMMAsa wave owns 16 rows × 256 tokens; one dequant feeds 16 WMMAs
activation staging—double-buffered 32-K LDS chunks, one barrier per chunk
B fragmentswait on LDS before each WMMA8-deep register ring, no per-WMMA s_wait_dscnt 0
arithmeticidentical: 6-bit unpack, v_cvt_f32_ubyte0, v_cvt_f16_f32, one v_fma_f16, ascending 16-K chain, 0 + acc F32 epilogue

Twins are checked by memcmp against the hipcc object, not by tolerance. For that MQ6 kernel: zero differing bytes over the six pp8192 trace shapes and 216 further runs over 12 shapes, including ragged tails and inputs that produce infinities and NaNs. For the Strix Halo QSA selector: every score bit, the whole ordered selection and its fill byte-identical across 83 cases and 707 records, including real 32K/64K captures of all 12 QSA layers.

04 Checking the kernels PM didn't write

Because the lifter reads any gfx11/gfx12 code object, the same analyses run over hipcc output. peacemaker audit --lds-barrier flags any path, loop back-edges included, that reaches a workgroup barrier with an LDS store still pending: the bug class from § 01. Over the gfx1201 JIT caches (412 modules, 62 distinct objects) it lifted every module byte-exactly and reported 0 findings. A module the tables cannot fully decode is reported as unchecked, never as clean.

05 What ships PM-built in 0.4.1

kernelarchrouteopt-out
QSA gathered attention (convert + attention)gfx1151, gfx1201default, byte-exact replacementHIPFIRE_QWEN4_QSA_PM=0
QSA selector: rows16 score + select-from-scoresgfx1151default for prefill calls of ≥ 512 rows; byte-exactHIPFIRE_QWEN4_QSA_SCORE_PM=0, …_SELECT_PM=0
QSA selector score for the opt-in q8 stategfx1151default when q8 QSA is chosen; byte-exactHIPFIRE_QWEN4_QSA_SCORE_PM=0
MQ6 trunk GEMMgfx1201; large shapes on gfx1151default, byte-exact replacementHIPFIRE_QWEN4_MQ6_X4_PM=0
Symmetric IU4 MoE grouped expert GEMMsgfx1151, gfx1201default for symmetric artifacts (the default Flash-Next pull); a new numeric route, KLD-gatedHIPFIRE_QWEN4_MOE_SYM_IU4=0
27B dense IU4 prefill, fused gate/up → A4 epiloguegfx1151default on admitted shapes, byte-exactHIPFIRE_V2B_A4_EPI=0

Graph capture and recorded replays, decode and verify, and unsupported shapes keep the hipcc kernels where the table says “prefill”. The certified modules are the *.hxaco files in kernels/.

06 What it buys you

0.4.1 · from the release notes and changelog
0bytes
difference vs the hipcc kernels for the PM routes on by default
PM QSA gather, PM QSA score/select, PM MQ6 trunk are listed as byte-exact replacements
0ROCm tools
in the PM build path
assembler, linker and bundler replaced by the native writer; ROCm stays as a test oracle
2races
real LDS races from hipfire's kernels that are now compile errors
Halo verify-attention lgkmcnt race; gfx11 FA2 mailbox race
PM routes are part of the Flash-Next prefill that 0.4.1 ships in its kernel packs for Strix Halo and the R9700, so those workloads run without cold-cache device compilation. Because the QSA and MQ6 replacements are byte-exact, turning one off changes speed, never output.

07 Limits

scope
  • PM targets gfx1100, gfx1151 and gfx1201. Other architectures run hipcc kernels.
  • Byte-identity is checked per kernel against its hipcc twin; the symmetric IU4 MoE route is a different numeric route from the F16 one it replaces and is KLD-gated, not bit-exact.
  • The audit covers what the decode tables cover; anything else is reported unchecked.
  • The XDNA2 NPU work that shares the PM name space is experimental and outside inference.

08 Sources