# Round 25 Track C (`argon-r25-moemm-down-and-plan`): `mm_down3` `W4<T_Q2_0>` 64-Block Stepping + `mm_gu3` Coalesced `half4` `HS` Store

## 1. Summary of Shipped Changes

1. **`W4<T_Q2_0>::run_q<OFF>(device const uchar* b, uint kl4)` & `mm_down3` 64-Element Block Stepping (`metal/kernels/moe_mm.metal`)**:
   - In `mm_down3` (`F == T_Q2_0 && TK == 32`, `coop_k4`), two consecutive `TK = 32` steps (`k0` and `k0 + 32`) sit inside the same 64-element, 18-byte `Q2_0` block (`QK = 64, BB = 18`).
   - Previously, each `k0 += 32` iteration computed `boff = uint(k0 >> 6) * 18` and `j_in = (k0 + kl) & 63`, and `W8<T_Q2_0>` called `W4<T_Q2_0>::run(rdw, j_in)` and `W4<T_Q2_0>::run(rdw, j_in + 16)`, where the second call had to recompute `+ ((k >> 6) * 18)` and `2 + ((k & 63) >> 2)` because the compiler could not prove `(j_in + 16) < 64`.
   - By stepping `k0 += 64, w0_l += 18` and introducing `W4<T_Q2_0>::run_q<OFF>(device const uchar* b, uint kl4)` reading `(b + kl4)[OFF]` with compile-time constant immediate byte offsets `OFF in {2, 6, 10, 14}` and unsigned `kl4 = uint(kl) >> 2` (eliminating 32-to-64-bit sign extension `sext`, `(k >> 6) * 18`, and `(k & 63)` while keeping the minimal 1-`W4` VGPR live range across the 8-row unroll), `mm_down3` speeds up by **+2.48% (`-121.4 us/layer`, `-5.83 ms` across 48 layers) at `T = 1024`** and **+1.85% (`-146.1 us/layer`, `-7.01 ms` across 48 layers) at `T = 2048`**, with `+0.15%` at `T = 512`.

2. **`mm_gu3` `half4` Coalesced `HS` Store Pointer Hoisting + Format Expansion (`metal/kernels/moe_mm.metal`)**:
   - Hoisted `threadgroup const float4* ot_p = (threadgroup const float4*)(&ot[sg][mr * TN + f]);` and `device half* hs_p = HS + ulong(row0 + mr) * a.n_ff + n0 + f;` with stride `hs_step = uint(RP) * a.n_ff` out of the unrolled `m` store loop in `mm_gu3`.
   - Enabled the coalesced `half4` `HS` store path for `T_IQ3_XXS`, `T_IQ2_XXS`, and `T_Q2_0` in addition to `T_IQ2_XS` (`+0.09%` on `IQ2_XS`, `+0.33%` on `IQ3_XXS`, `+0.91%` on `IQ2_XXS`, `+0.60%` on `Q2_0` at `T = 1024`).

3. **`moe_mm_parity` Paired A/B Harness (`metal/tests/moe_mm_parity.cpp`)**:
   - Added candidate warmup and alternating `(i & 1)` A/B ordering to `gather_bench` plan timing (`7` paired iterations).
   - Updated `--ab` isolated kernel benchmarking (`--gu-bench` / `--dn-bench`) to run `19` interleaved pairs with external-contention spike filtering (`<= 1.10 * best_pair`).

## 2. Measured A/B Results on Apple M5

All benchmarks run with `STRATA_METAL_KERNELS=/tmp/argon_r25_moemm/strata/metal/kernels` (`A` = candidate) and `--ab /tmp/argon_r25_moemm/base_kernels` (`B` = baseline):

| Benchmark | `T` | Candidate `A` med (min) | Baseline `B` med (min) | Speedup `diff med` (`min`) | Bitwise Parity |
| :--- | :---: | :---: | :---: | :---: | :---: |
| `mm_down3` (`IQ2_XS/Q2_0`, `--dn-bench`) | `512` | `3572.3 us` (`3561.6 us`) | `3577.5 us` (`3558.6 us`) | **`+0.15%`** (`-0.08%`) | `HS/YE/Y memcmp=PASS` |
| `mm_down3` (`IQ2_XS/Q2_0`, `--dn-bench`) | `1024` | `4898.7 us` (`4886.9 us`) | `5020.1 us` (`5006.3 us`) | **`+2.48%`** (`+2.44%`) | `HS/YE/Y memcmp=PASS` |
| `mm_down3` (`IQ2_XS/Q2_0`, `--dn-bench`) | `2048` | `7914.2 us` (`7883.8 us`) | `8060.3 us` (`8033.7 us`) | **`+1.85%`** (`+1.90%`) | `HS/YE/Y memcmp=PASS` |
| `mm_gu3` (`IQ2_XS/Q2_0`, `--gu-bench`) | `512` | `7758.1 us` (`7725.8 us`) | `7754.5 us` (`7733.6 us`) | `-0.05%` (`+0.10%`) | `HS/YE/Y memcmp=PASS` |
| `mm_gu3` (`IQ2_XS/Q2_0`, `--gu-bench`) | `1024` | `12921.2 us` (`12842.6 us`) | `12933.4 us` (`12846.8 us`) | **`+0.09%`** (`+0.03%`) | `HS/YE/Y memcmp=PASS` |
| `mm_gu3` (`IQ2_XS/Q2_0`, `--gu-bench`) | `2048` | `22222.1 us` (`22044.8 us`) | `22229.8 us` (`22035.1 us`) | **`+0.03%`** (`-0.04%`) | `HS/YE/Y memcmp=PASS` |
| `mm_gu3` (`IQ2_XXS/Q2_0`, `--gu-bench`) | `1024` | `13530.1 us` (`13403.5 us`) | `13653.8 us` (`13544.2 us`) | **`+0.91%`** (`+1.05%`) | `HS/YE/Y memcmp=PASS` |
| `mm_gu3` (`Q2_0/Q2_0`, `--gu-bench`) | `1024` | `9455.1 us` (`9419.9 us`) | `9512.1 us` (`9470.1 us`) | **`+0.60%`** (`+0.53%`) | `HS/YE/Y memcmp=PASS` |
| `mm_gu3` (`IQ3_XXS/Q2_0`, `--gu-bench`) | `1024` | `13664.5 us` (`13537.5 us`) | `13710.0 us` (`13586.5 us`) | **`+0.33%`** (`+0.36%`) | `HS/YE/Y memcmp=PASS` |
| `gather-bench` (`mm_plan + mm_gather_h`) | `2048` | `plan 51.16 us`, `tg256 1228.1 us` | `plan 51.14 us`, `tg256 1233.2 us` | **`+0.42%`** | `all 8 plan + XS PASS` |

## 3. Ruled-Out Hypotheses (Measured Regressions / Neutral)
- **Sharing `d` and loading `q0, q1` upfront in `W8<T_Q2_0>`**: `-0.84%` at `T=1024`, `-1.39%` at `T=2048` (increases VGPR live ranges across the 8-row unrolled loop).
- **SWAR `0x40100401u` multiply in `W4<T_Q2_0>`**: `-0.65%` at `T=1024`, `-2.58%` at `T=2048` (adds 4 fp32 `fadd -1.0f` ops on the FPU pipe).
- **SWAR `0x00204081u` `char4` sign negation in `w4_signed`**: `-10.11%` at `T=1024` (serializes `float4` conversion behind `sign4_iq2xs` + 32-bit integer multiplies).
- **Unrolling `k0` by 2 (`k0 += 64`) in `mm_gu3`**: `-1.22%` at `T=1024`, `-3.42%` at `T=512` (`mm_gu3` already has 2 `i` loops and 2 `op.run` calls per `k0` step; doubling it to 4 spills VGPRs).
- **Adding `#pragma clang loop unroll(full)` on `acc` / `accg` zero-init loops**: `-0.10%` to `-0.40%` vs leaving MPP's cooperative tensor loop default.

## 4. Artifact Paths
- Clean unified diff (`git -C vendor/strata apply --check` verified): `/tmp/argon_r25_moemm/argon_r25_moemm.patch`
- Audit report: `audits/argon_r25_moemm.md`
