# Round 26 Track C Audit Report: `DW<T_IQ4_XS>` / `DW<T_IQ4_NL>` / `DW<T_Q6_K>` Specializations & `mm_gu3` (`W8<T_IQ2_XS>`) Investigation

- **Agent**: `argon-r26-moemm-gu-and-dqf16` (`gemini-4-argon`)
- **Scratch Repo**: `/tmp/argon_r26_moemm/strata`
- **Unified Patch**: `/tmp/argon_r26_moemm/argon_r26_moemm.patch` (`git -C vendor/strata apply --check` verified `0`)
- **Touched Files**:
  - `metal/kernels/mma.metal`
  - `metal/kernels/dense_mm.metal`
  - `metal/kernels/moe_mm.metal`
  - `metal/tests/dense_mm_parity.cpp`
  - `metal/tests/moe_mm_parity.cpp`

---

## 1. Target 1: `DW<T_IQ4_XS>`, `DW<T_IQ4_NL>`, `DW<T_Q6_K>` Direct Specializations & Full Loop Unrolling (`mma.metal`, `dense_mm.metal`, `moe_mm.metal`)

### Findings & Implementation
1. **Direct `DW<T_IQ4_NL>` and `DW<T_IQ4_XS>` specializations (`metal/kernels/mma.metal`)**:
   - Previously, `T_IQ4_XS` and `T_IQ4_NL` fell back to the generic `DW<F>`, which allocated a separate `float q[32]` array in `deq<F>` and then multiplied `w[j] = q[j] * s` in a second loop before `dq_f16` / `gemv_mma` / `stage_w` copied `w[j]` out.
   - Added dedicated `DW<T_IQ4_NL>` and `DW<T_IQ4_XS>` specializations that fuse the scale multiply `float(w0.x) * d` directly into the unrolled 8-iteration `ushort` table lookup loop (`#pragma clang loop unroll(full)`), eliminating the intermediate `float q[32]` array and second loop while preserving exact fp32 multiplication order (`memcmp == 0`).
   - Also tested replacing the threadgroup `tab` lookup in `dq_f16<T_IQ4_XS>` / `dq_f16<T_IQ4_NL>` with direct constant-memory `kvalues_iq4nl[...]` nibble lookups (skipping `load_tab` + barrier); this regressed chunk time by `~1%` (`58.88 -> 59.47 ms` on `IQ4_XS`, `65.61 -> 65.98 ms` on `IQ4_NL`) due to constant-cache divergent lookup serialization on Apple GPUs, so the threadgroup `tab` lookup is retained.
2. **4-Byte `rd32` + Scalar `uint` Bitwise Unpack in `DW<T_Q6_K>` (`metal/kernels/mma.metal`)**:
   - Replaced the 16-iteration byte-by-byte loop in `DW<T_Q6_K>` with a 4-iteration unrolled loop using `rd32(ql + j)` and `rd32(qh + j)` plus SWAR mask/shift `(la & 0x0F0F0F0Fu) | (((ha >> sh) & 0x03030303u) << 4)`.
   - On small-row `dq_f16` dispatches (`2560x128`, `2560x48`, `10240x4`, `2560x1`), this speeds up `dq_f16<T_Q6_K>` by **1.04x–1.07x** (`3.7 -> 3.6 us`, `2.2 -> 2.1 us`, `1.8 -> 1.7 us`, `1.5 -> 1.4 us`) and `6144x2560` by **1.02x** (`322.0 -> 316.2 us`), while large matrices remain DRAM-write bandwidth bound at ~100 GB/s.
3. **Full Unrolling Across `DW<F>`, `dq_f16`, `gemv_mma`, and `stage_w`**:
   - Added `#pragma clang loop unroll(full)` to all `DW<*>` specializations (`DW<F>`, `DW<T_IQ4_NL>`, `DW<T_IQ4_XS>`, `DW<T_Q2_0>`, `DW<T_Q5_1>`, `DW<T_F32>`, `DW<T_BF16>`, `DW<T_Q4_K>`, `DW<T_Q5_K>`, `DW<T_Q6_K>`, `DW<T_Q3_K>`), `gemv_mma`'s threadgroup store loop, `dq_f16`'s `half4` store loop, and `moe_mm.metal`'s `stage_w` loop.
4. **Paired Alternating A/B Timing in `dense_mm_parity.cpp`**:
   - Updated `dq_ab_bench` in `metal/tests/dense_mm_parity.cpp` to alternate execution order (`round & 1`), filter thermal/contention outliers (`<= 1.15 * best_pair`), and accept `STRATA_DQ_AB_KERNELS` in addition to `DQ_AB_KERNELS`.

### Verification (`dense_mm_parity` & `mma_parity`)
- `dense_mm_parity`: **ALL PASS** across all 14 formats (`F32, BF16, Q8_0, Q4_0, Q5_0, Q5_1, IQ4_NL, IQ4_XS, Q2_0, IQ3_S, Q3_K, Q4_K, Q5_K, Q6_K`), `memcmp(wh)=0, memcmp(xh)=0` on every shape.
- `mma_parity`: **ALL PASS** across all 12 formats (`ntok = 1, 3, 8`), `window == one token: bitwise`.
- Quiet-GPU `dense_mm_parity --dq-ab` paired results (`memcmp=0` on all 11–13 shapes per format):
  - `IQ4_XS`: `60.91 -> 60.95 ms` (`1.00x`, `2560x6144`: `293.5 -> 291.3 us` `1.01x`, `memcmp=0`)
  - `Q6_K`: `66.13 -> 65.98 ms` (`1.00x` chunk; `6144x2560`: `322.0 -> 316.2 us` `1.02x`, `2560x48`: `2.2 -> 2.1 us` `1.06x`, `10240x4`: `1.8 -> 1.7 us` `1.06x`, `2560x1`: `1.5 -> 1.4 us` `1.07x`, `memcmp=0`)
  - `IQ4_NL`: `66.13 -> 65.94 ms` (`1.00x`, `2560x6144`: `286.7 -> 283.7 us` `1.01x`, `memcmp=0`)
  - `IQ3_S`: `59.56 -> 59.17 ms` (`1.01x`, `2560x6144`: `278.9 -> 274.4 us` `1.02x`, `6144x2560`: `286.4 -> 282.7 us` `1.01x`, `memcmp=0`)

---

## 2. Target 2: `mm_gu3` (`W8<T_IQ2_XS>`) Investigation & Ablations (`moe_mm.metal`, `moe_mm_parity.cpp`)

### Hardware Profiling (`MM_PROBE` Breakdown at `T=512`, `tile=16,32,32,4`, 512 Experts)
- `MM_PROBE=0` (full `mm_gu3` decode + `matmul2d`): `7723.7 us` (`4.34 TFLOP/s` useful)
- `MM_PROBE=3` (no `tab` lookup, `v0 * 0x01010101u`, with `w4_signed` + `sign4_iq2xs` + device loads): `7320.4 us` (`-403 us` = `5.2%` of total time)
- `MM_PROBE=5` (device loads `v0, v1, scb, d` + `sc0, sc1` only, no `tab` lookup, no `w4_signed`/`sign4_iq2xs`): `6604.0 us` (`-716 us` = `9.3%` of total time)
- `MM_PROBE=1` (no weight decode, cheap constant fill + `matmul2d`): `3680.6 us` (`-2923 us` = `37.8%` of total time)
- `QUANT_CTAB=1` (constant-memory grid instead of threadgroup `tab`): `8550.8 us` (`+10.7%` slower)

### Controlled Ablations Tested on M5 (`T=512 / 1024 / 2048`, all `HS_memcmp=PASS YE_memcmp=PASS Y_memcmp=PASS`)
1. **Pre-added 3-pointer stepping (`rgw, rgw_q, rgw_sc += step8`)**:
   - Maintaining three 64-bit pointers across the unrolled `i` loop added pointer-increment instructions and live registers across `op.run(tA, rw, accg)`, regressing `T=512` min time by `+0.93%` (`15269 -> 15411 us` under contention).
2. **Outer block loop (`kb += 256`, `ib = 0..7`) + `run_q(rgw, qoff, ib, hh, ...)`**:
   - Keeping `qoff = kl_q + 8u * ib`, `ib`, and `hh` live across `op.run(tA, rw, accg)` increased register pressure around the cooperative-tensor `matmul2d` op, regressing `T=512` by `0.55%` (`7748 -> 7791 us`), `T=1024` by `1.35%` (`12896 -> 13073 us`), and `T=2048` by `1.43%` (`22193 -> 22515 us`).
3. **Full compile-time template unrolling of `IB = 0..7` (`W8<T_IQ2_XS>::run_q<IB>`)**:
   - Unlike `mm_down3` (`Q2_0`, `QK=64 = 2 * TK`), `IQ2_XS` has `QK=256 = 8 * TK`. Unrolling all 8 `IB` steps (`16` `op.run` calls per `k0 += 256` iteration) blew up kernel code size and register allocation, regressing `T=512` from `7708 us` to `33176 us` (`-76.8%`).
4. **Vectorized `packed_ushort4` load (`q4 = *(device const packed_ushort4*)(bl + qoff)`)**:
   - Because `74 % 4 == 2`, odd blocks are only 2-byte aligned, so `packed_ushort4` loads all 8 bytes (`q[0..3]`) as 16-bit loads including the unused `q[1]` and `q[3]` words for the other `l` half, matching baseline within `0.00%–0.28%` (`12925.1 vs 12925.0 us` at `T=1024`).
5. **Cross-lane `simd_shuffle_xor(vm, 1)` sharing between adjacent `hh=0` and `hh=1` lanes**:
   - Both lanes already hit the same L1 cache line in the same cycle; adding `simd_shuffle_xor` + select instructions inside the unrolled loop regressed `T=512` by `-40.6%` (`7744 -> 13028 us`) and `T=1024` by `-16.0%` (`12914 -> 15367 us`).
6. **Dual `rw + ru` cooperative tensors in a single `i` loop**:
   - Allocating two `right_input_cooperative_tensor` instances simultaneously doubled the `half` register footprint (`32 -> 64` `half`s per lane) across `op.run`, reducing occupancy and regressing `T=512` by `-9.54%` (`7735 -> 8550 us`) and `T=2048` by `-4.03%` (`22217 -> 23149 us`).
7. **Bitwise float32 sign-XOR (`as_type<uint4>(p) ^ m`) and `w4_iq2xs` direct shift**:
   - The Apple M5 shader compiler fuses `(s & bit) ? -float(v[k]) : float(v[k])` into hardware conditional-negate/select instructions, whereas integer sign-bit XOR required `float <-> uint` bitwise reinterpretation (`-17.4%` at `T=512`), and splitting `s3` parity select (`w4_iq2xs`) added an extra branch/select per `w4` (`-3.75%` at `T=512`).

### Conclusion on `mm_gu3` (`W8<T_IQ2_XS>`) + Fast-Compile Guard (`MM_V3_ONLY`)
- Baseline `W8<T_IQ2_XS>::run` + `mm_gu3`'s single `j_in = (k0 + kl) & 255` index is already register- and instruction-optimal on M5: keeping only `k0` and `kl` live across `op.run(tA, rw, accg)` minimizes live scalar registers during the `matmul2d` cooperative-tensor op while LLVM CSE shares `(j_in & 255) >> 5`, `(j_in & 255) >> 3`, and `(j_in & 7) >> 2` across the 4 unrolled `i` iterations.
- Kept `W8<T_IQ2_XS>` and `mm_gu3` at exact baseline (`100%` bitwise identical, `HS_memcmp=PASS YE_memcmp=PASS Y_memcmp=PASS`), and added `#ifndef MM_V3_ONLY` guards around non-v3 kernels (`mm_gu`, `mm_down`, `mm_gu2`, `mm_down2`, `mm_gu4`, `mm_gu5`) in `metal/kernels/moe_mm.metal` + `#define MM_V3_ONLY 1` in `metal/tests/moe_mm_parity.cpp` when running `--v3`, cutting `moe_mm_parity --v3` Metal shader compilation time from `~15s` to `~1.5s` while leaving normal engine compilation 100% unchanged.
