# Round 20 Track C Audit: `gdn_pre` Key-Head `t >= 3` Vectorized `conv_w` Fast Path + `gdn_scan_r` 32-Bit Base Offset Hoisting & Final-Token Dead-Lookahead Elimination

## 1. Summary of Changes (`metal/kernels/gdn_prompt.metal`)

1. **`gp_conv` & `gdn_pre` Key-Head `t >= 3` Fast Path (lines 26–105):**
   - In `gp_conv` (`t < 3` fallback), replaced 4 scalar `cw[ch * 4 + k]` loads with a single 128-bit `float4 w = *(device const float4*)(cw + ch * 4);` load and unrolled the 4-tap FMA loop.
   - In `gdn_pre`'s key-head branch (`if (x < k_tgs)`), added a `t >= 3` branchless fast path preserving the exact lane-to-channel mapping `d = int(lane) + m * 32` (`m = 0..3`).
   - Hoisted `pq = qkv + (t - 3) * C + kh * S + int(lane)` and `pk = qkv + (t - 3) * C + (hk_n + kh) * S + int(lane)`, loaded 128-bit `float4 wq` and `wk` from `conv_w`, and evaluated the 4-tap FMA chain at offsets `0, C, 2*C, 3*C` without `src >= 0` ternary branches.

2. **`gdn_scan_r` State Offset Hoisting, 32-Bit Base Offsets, and Final-Token Dead-Lookahead Elimination (lines 261–351, 421–423):**
   - **Hardware Register Discovery (64-bit VGPR vs 32-bit base offset):** Holding 64-bit `device` pointers (`sp`, `kn_p`, `qn_p`, `gb_p`, `vc_p`, `kq_p`, `o_p`) live across the `threadgroup_barrier` inside the token scan loop consumes 2 VGPRs per pointer per lane on Apple Silicon, crossing an occupancy cliff (`192.2 ms -> 197.8 ms`).
   - Instead, hoisted 32-bit integer strides and base offsets (`const int rs = hv * S, s0 = (i0 * hv + h) * S + j;`, `const int ks = hkn * S, k0 = hk * S + i0 + int(lr), v0 = h * S + j;`), keeping `device` base pointers in uniform argument registers and indexing `(state + s0)[i * rs]`, `kn[tn * ks + k0 + c * 32]`, `qn[tn * ks + k0 + c * 32]`, `vc[tn * rs + v0]`, and `o[t * rs + v0]`.
   - Split the `TB == 0` loop into `for (int t = 0; t < T - 1; ++t)` (with `tn = t + 1`, eliminating `min(t + 1, T - 1)`) followed by a `if (T > 0)` final-token epilogue for `t = T - 1` that skips the dead `kn_l`, `qn_l`, `g_b_n`, `v_n` global loads and skips the 64 dead `simd_broadcast`s (`knr`, `qnr`) and 64 dead `ka`/`qa` FMAs.

## 2. Bitwise Parity Verification (`memcmp == 0`)

Verified via `/tmp/argon_r20_gdn/strata/build-metal/gdn_prompt_parity` (standalone suite + `--ab` bitwise comparison against baseline `gdn_prompt.metal`):
- All `gdn_pre` outputs (`qn`, `kn`, `vc`, `gb`, `kq`, `history`), `gdn_scanr_4` outputs (`o`, `state`), and `gdn_post` outputs (`yh`, `y`) pass with **100% bitwise `memcmp == 0`** across `T = 1, 2, 3, 4, 64, 512, 1024, 2048`.

## 3. Paired A/B Timings (Apple M5, 36 GDN Layers, Quiet GPU)

| Token Count `T` | Stage | Baseline Median (ms) | Candidate Median (ms) | Delta (ms) | Ratio (`cand / base`) |
|---:|---|---:|---:|---:|---:|
| `512` | `stage 0` (`gdn_pre`) | `11.563` | `11.600` | `+0.037` | `1.0022` |
| `512` | `stage 1` (`gdn_scanr_4`) | `48.780` | `47.757` | **`-1.023`** | **`0.9791` (`-2.09%`)** |
| `512` | `stage 2` (`gdn_post`) | `7.423` | `7.427` | `+0.004` | `0.9988` |
| `1024` | `stage 0` (`gdn_pre`) | `23.221` | `23.175` | **`-0.046`** | **`0.9978` (`-0.22%`)** |
| `1024` | `stage 1` (`gdn_scanr_4`) | `96.569` | `93.866` | **`-2.703`** | **`0.9729` (`-2.71%`)** |
| `1024` | `stage 2` (`gdn_post`) | `16.501` | `16.458` | `-0.043` | `0.9960` |
| `2048` | `stage 0` (`gdn_pre`) | `46.118` | `46.262` | `+0.144` | `1.0036` |
| `2048` | `stage 1` (`gdn_scanr_4`) | `192.239` | `187.765` | **`-4.474`** | **`0.9764` (`-2.36%`)** |
| `2048` | `stage 2` (`gdn_post`) | `34.228` | `34.211` | `-0.017` | `0.9995` |

## 4. Artifacts
- Clean unified diff: `/tmp/argon_r20_gdn/argon_r20_gdn.patch` (verified with `git -C vendor/strata apply --check`).
- Isolated build & test binaries: `/tmp/argon_r20_gdn/strata/build-metal/gdn_prompt_parity` and `/tmp/argon_r20_gdn/strata/build-metal/strata_window_cli`.
