Files
d4r/kernels/rr/rrswin_dec4_epilogues.md
T
woutermans 0fe3a28cb7 kernels/rr: staged-image Swin layer engine prototypes
Per-layer staged-image engine for the eleven translated denoiser Swin
layers: descriptors (verified offsets per phase), cut recipes that splice an
isolated native phase into NVIDIA's PTX, wave templates, epilogue notes and
GPU probes. The isolated phase-8 splice produces a byte-identical final
4K frame but is slower than the translated body (14.90 vs 6.59 ms) - a
correctness experiment, not a shipping improvement; docs/rr-engine.md
records the design and the next direct-converter win (B operands built
from transposed accumulators).
2026-10-12 12:47:53 +02:00

674 lines
40 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# `cuda_dldn_engine_swin_dec4_kernel` — the epilogues of phases 1…62
Companion to `kernels/rr/rr_layer_spec.py dec4`. Everything below was read out of
`~/.cache/d4r-rr-corpus/0019-PREPASS_ENTRYPOINT_NAME.ptx`, entry
`cuda_dldn_engine_swin_dec4_kernel` (the entry opens at file line 1016, its body
holds statements s1…s24447, and s24447 is the `ret`).
dec4 is the widest of the eleven Swin layers: its attention/MLP width is 160 where
dec3's is 128, so every count below is *not* interchangeable with dec3's. Where a
region is the same code as dec3's, that is stated and the shared evidence is cited
on dec4's own statements.
## 0. Conventions
* **`sNNNN` is a statement index** in the linearisation `rr_layer_spec.py`
documents; **`LNNNNN` is the physical line** of the same instruction, so every
claim can be checked with `sed -n 'LNNNNN,LNNNNN p' …ptx`. (Example anchors:
phase 1's 300 `mma` occupy only L1707–L3799, and s871 = L3807.)
* An **epilogue** is the run of statements between one phase's last `mma` and the
next phase's first `mma`; a phase's own weight loads live in the previous
epilogue, and are named in place.
* `W` denotes the prepared weight image: `ld.param.u64 %rd2,
[cuda_dldn_engine_swin_dec4_kernel_param_0+40]` (s9) then
`cvta.to.global.u64 %rd3, %rd2` (s10). Every `ld.weak.global.ca.v4.u32` reads
`W + 16*laneid + imm`; tables and biases use
`W + ((laneid<<2)&12) + imm` (canonical construction s16157–s16161).
* `S` denotes the plane arena: `ld.param.u64 %rd1050, [%rd1+-32]` (s23917) then
`cvta.to.global.u64 %rd5, %rd1050` (s23918), with `%rd1 = param_0+80` (s4), so
`%rd1-32` is **`param_0+48`**. This is the entry's only read of `param_0+48`.
* `SM` denotes the 16384-byte shared array
`_ZZ33cuda_dldn_engine_swin_dec4_kernel33DldnEngineSwinEncParamsStructBaseE4smem`
(materialised by `mov.u32` at s11611 and others).
* `%r9 = %tid.z` (s19) is the **slab index**, and dec4 **guards it to 0…3**:
`s20 setp.gt.u32 %p3, %r9, 3` / `s21 @%p3 bra $L__BB1_121`. It scales the input
buffer ×25600 (s438), a second input stride ×160 (s543), ×40 (s1052), the shared
tile ×16 (s2301), ×2560 (s11503), ×2048 (`<<11`, s16069), ×512 (`<<9`, s16128)
and the phase-2…11 weight group ×27648 (`%r16781 = %r9*13824` s11607,
`%rd381 = %r16781*2` s11608, consumed at s11645 `add.s64 %rd383, %rd2, %rd381`).
* Register conventions are the settled family ones: `C/D reg0` = (row g, cols
2t,2t+1), `reg1` = (row g+8, same cols), `g = laneid>>2` (s37/s38), `t = laneid&3`.
* Anything I could not pin down from the PTX is in §6.
## 1. Shared vocabulary
### 1.1 Addresses and parameters an epilogue touches
| symbol | how it is obtained | statements |
|---|---|---|
| `param+0`, extents `(ex, ey)` | `ld.param.v2.u32 {%r1013, %r1014}, [param_0]` | s15 |
| `param+8`, the e4m3 feature buffer | `ld.param.u64 %rd60, [%rd1+-72]` → `cvta.to.global.u64 %rd61, %rd60` | s34–s35 |
| `param+24`, the f16 image buffer (**the skip input**) | `ld.param.u64 %rd253, [%rd1+-56]` → `cvta.to.global.u64 %rd4, %rd253` | s3640–s3641 |
| `param+40`, `W` (weight image) | `ld.param.u64 %rd2, [param_0+40]` → `cvta.to.global.u64 %rd3, %rd2` | s9–s10 |
| `param+48`, `S` (plane arena) | `ld.param.u64 %rd1050, [%rd1+-32]` → `cvta.to.global.u64 %rd5, %rd1050` | s23917–s23918 |
| `param+80`, block origin `(ox, oy)` | `ld.param.v2.u16 {%rs222, %rs223}, [param_0+80]` | s5 |
| `param+88`, low-res feature **texture** | `ld.param.u64 %rd1117, [%rd1129+8]` with `%rd1129 = param_0+80` (s24223) | s24334 |
| `param+96`, **texture** added unconditionally | `ld.param.u64 %rd1119, [%rd1129+16]` | s24410 |
| `param+104`, **texture** added under a NaN guard | `ld.param.u64 %rd1121, [%rd1129+24]` | s24412 |
| `param+112`, output **surface** | `ld.param.u64 %rd1123, [%rd1129+32]` | s24233 |
| `param+136`, `(sx, sy)` pixel→uv scale | `ld.param.v2.f32 {%f1180, %f1181}, [%rd1129+56]` | s24328 |
| `SM` (16384 B) | `mov.u32 %r16783, _ZZ33…E4smem` | s11611 |
| per-lane weight address | `mul.wide.u32 %rd382, %laneid, 16` + `add.s64 %rd384, %rd383, %rd382` | s11644–s11646 |
| per-lane *table* address | `shl.b32 %r, %laneid, 2` → `cvt.u64.u32` → `and.b64 %rd, %r, 12` → `add.s64 %rd, W, %rd` | s16157–s16161 |
| block origins | `%r1 = ctaid.x<<3 − ox` (s7), `%r2 = %r1 − 1` (s8), `%r3 = ctaid.y<<3 − oy` (s14), `%r6 = %r3 − 1` (s16) | s7–s16 |
| `%r7 = ex<<3`, `%r8 = ey*%r7` | s17–s18 | s17–s18 |
The `param+80`-relative form is worth stressing: dec4 keeps `%rd1127` and `%rd1129`
(both `= %rd1128/%rd1130 + 80`, s24198 / s24223) and then reads the decoder
parameters as `[%rd1127-80]` (= `param+0`), `[%rd1129+8]`, `[%rd1129+16]`,
`[%rd1129+24]`, `[%rd1129+32]`, `[%rd1129+56]`. So **`+96` and `+104` are exactly
`%rd1129+16` and `%rd1129+24`** (s24410 / s24412).
### 1.2 Constants
| register | first definition | literal | identity |
|---|---|---|---|
| `%f476` | s12177 `mov.f32 %f476, 0f3C8CCB50` | 0.017186790704727173 | score scale |
| `%fd383` | s12181 `mov.f64 %fd383, 0dBFE1CC0000000000` | −0.55615234375 | clamp low |
| `%fd385` | s12186 `mov.f64 %fd385, 0d3FE1CC0000000000` | +0.55615234375 | clamp high |
| `%f478` | s12192 `mov.f32 %f478, 0f3F6D6000` | 0.92724609375 | cubic coefficient |
| `%f480` | s12197 `mov.f32 %f480, 0f3FB00000` | 1.375 | cubic offset |
| `%fd1` | s10075 `mov.f64 %fd1, 0d3F20000000000000` | 2⁻¹³ | norm epsilon in E1 |
| `%fd386` | s16920 `mov.f64 %fd386, 0d3F20000000000000` | 2⁻¹³ | norm epsilon in E21 |
| `%f1117` | s17741 `mov.f32 %f1117, 0f3ED306EB` | 0.4121621549129486 | activation ramp |
| `%f1118` | s17744 `mov.f32 %f1118, 0f3DA60DD6` | 0.0810810774564743 | activation width |
| `%f1119` | s17747 `mov.f32 %f1119, 0f3F000000` | 0.5 | activation offset |
| `%f1120` | s17750 `mov.f32 %f1120, 0f40000000` | 2.0 | activation clamp |
`0f3FB8AA3B` (log2e) occurs 9 times in the final epilogue, first at s24246; the
negated form `0fBFB8AA3B` once at s24415; `0f3F800000` (1.0) at s24251's
`add.ftz.f32`. Neither layer ever uses the `.relu` requantiser: the string
`satfinite.relu` does not occur.
### 1.3 Two quantisation helpers
* `cvt.rn.satfinite.e4m3x2.f16x2` — requantisation.
* `cvt.rn.f16x2.e4m3x2` — the inverse unpack (one e4m3 byte pair → f16x2).
## 2. Phase table summary
From `rr_layer_spec.py dec4`: **62 phases, 1606 `mma`, 24447 statements**.
The tool prints M and N from the number of *distinct* A and B fragments, so the
identity `M/16 * N/8 * K/32 == mma` is the dense-GEMM check:
* holds for phases 2–12, 14–21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47,
49, 51, 53, 55, 57, 59, 61;
* **fails for 23 phases — 1, 13, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44,
46, 48, 50, 52, 54, 56, 58, 60, 62.** For the even phases 22…60 the tool prints
M=80 N=160 K=160 (`5*20*5 = 500`) against 20 `mma`: those phases are 5-step
cascades, not dense GEMMs (see E22). For **P62** it prints M=80 N=80 K=160
against 10 `mma`; P62 is a 5-fragment cascade (A = `%r938…%r957`) as §4/E62
describes.
Weight-image extent: the largest byte read from `W` is phase 62's second C seed at
`W + ((laneid<<2)&12) + 534800`, i.e. the image is **at least 534804 bytes**.
Phase 1's B block is `[0, 25600)`, phase 1's C seeds are `[102400, 102704]`, the
score bias (phase 12's C) is `[114240, 126028)`, the per-slab copy of the phase-2…11
weight group starts at `104000 + z*27648`, and phase 62's last weight tile is
`[532224, 534796)`.
**Phases that read no weight operand at all: 12 and 13.** Phase 12's A and B both
come from e4m3 packs of phase 10's D (E11), and phase 13's B is the `movmatrix`
transpose of registers (E12); see §4/E11, E12.
## 3. Summary of epilogues
| epilogue | range | stmts | named operation |
|---|---|---|---|
| E1 | s871–s11653 | 10783 | requantise P1's D, scatter to `SM`, read back, blend `param+24`, inverse-std, requantise, stage for P2 |
| E2–E10 | 7 stmts each | 7 | next-B weight loads only (s11678–s11900) |
| E11 | s11957–s12127 | 171 | score-bias C-seed loads + 80 packs of P10's D → P12 A and B |
| E12 | s12176–s16019 | 3844 | softmax of the 64×96 score block, V-transpose, pack |
| E13 | s16068–s16341 | 274 | stage P·V, P14 A from `SM`, next-B loads, column table + skip → P14 C |
| E14–E20 | 27 stmts each | 27 | P15…P21 A from `SM` + next-B loads (s16362–s16670) |
| E21 | s16691–s17719 | 1029 | RMS norm (², sum, rsqrt, gain) + packs + next B/C |
| E22 | s17740–s18060 | 321 | clamped cubic activation + column-bias add + packs + next B |
| E23 | s18081–s18172 | 92 | 40 packs → P24 A, next-B, next-C bias |
| E24…E60 | 172/92 alternating | | E22/E23 repeated for P24…P60 |
| E61 | s23857–s24154 | 298 | pack → plane-arena scatter (`param+48`) → next B/C |
| E62 | s24165–s24446 | 282 | `SM` stage, softmax over 5 taps, 3×3 texture gather, aux textures, surface write |
---
## 4. The epilogues
### E1 — s871–s11653: patch expand, image blend, inverse standard deviation
10783 statements (44 % of the entry), the same pipeline as dec3's E1 with every
count scaled by 160/128 = 1.25.
Evidence:
```
s871 L3807 cvt.rn.satfinite.e4m3x2.f16x2 %rs226, %r1298
s875 L3818 mov.b32 %r10, {%rs228, %rs229}
s1090 L4268 st.shared.v2.u16 [%r4580], {%rs226, %rs227}
s1117 L4297 st.shared.u32 [%r4593], %r10
s2295 L5592 bar.sync 0
s2340 L5647 ld.shared.v2.u16 {%rs346, %rs347}, [%r5246]
s3640 L7252 ld.param.u64 %rd253, [%rd1+-56]
s3794 L7417 ld.global.v2.u16 {%rs426, %rs427}, [%rd255]
s9055 L12990 cvt.rn.f16x2.e4m3x2 %r9582, %rs426
s9217 L13472 add.f16 … // first of 324
s10018 L15459 shfl.sync.bfly.b32 %r9963,%r9959,%r10029,%r9966,%r10040
s10075 L15607 mov.f64 %fd1, 0d3F20000000000000
s10321 L16341 rsqrt.approx.ftz.f32 fl, fl
s10963 L17382 ld.global.v2.u16 {%rs3159, %rs3160}, [%rd336+103696]
s11503 L18962 mul.lo.s32 %r936, %r9, 2560
s11521 L18998 st.shared.v4.u32 [%r10307], {%r10311, %r10310, %r10309, %r10308}
s11606 L19151 bar.sync 0
s11613 L19160 ld.shared.v4.u32 {%r16785, %r16786, %r16787, %r16788}, [%r16784]
s11651 L19201 ld.weak.global.ca.v4.u32 { %r10356,%r10357,%r10358,%r10359},[%rd337]
```
| range | stmts | what | operations (count) |
|---|---|---|---|
| s871–s1048 | 178 | requantise **phase 1's D** and pack | 120 `cvt.rn.satfinite.e4m3x2.f16x2`, 58 `mov.b32` → `%r10…%r67` |
| s1049–s1089 | 41 | lane / `%r9` → shared-index setup for the first store | `mov.u32 %r4338, %laneid` (s1049), `mul.wide.u32 %rd204, %r4338, -1431655765` (s1051) |
| s1090–s2295 | 1206 | guarded scatter into `SM`, one basic block per store | **58 `st.shared.u32`** + 2 `st.shared.v2.u16` |
| s2295 | 1 | `bar.sync 0` (L5592) | — |
| s2296–s3639 | 1344 | read back a window from `SM` (5-way switch per load) | **40 `ld.shared.v2.u16`** (s2340…s3639) |
| s3640–s3641 | 2 | **the `param+24` buffer pointer** | `ld.param.u64 %rd253, [%rd1+-56]`, `cvta` |
| s3642–s9054 | 5413 | clamped-coordinate gather from the `param+24` buffer | **40 `ld.global.v2.u16`** (s3794…s9054) |
| s9055–s9214 | 160 | dequantise both sources | 160 `cvt.rn.f16x2.e4m3x2` → `%r9582…%r9741` |
| s9215–s10017 | 803 | blend + reduction tree | 480 `mul.f16`, 324 `add.f16`, 84 `add.f16x2` |
| s10018–s10074 | 57 | cross-lane sums | **8 `shfl.sync.bfly.b32`** (s10018…s10071) |
| s10075–s10076 | 2 | epsilon `2⁻¹³` | `mov.f64 %fd1, 0d3F20000000000000` (s10075) |
| s10077–s10320 | 244 | epsilon add + packing of the sums | 160 `add.f16`, 81 `mov.b32` |
| s10321–s10956 | 636 | inverse standard deviation | **160 `rsqrt.approx.ftz.f32`** (s10321…s10954) |
| s10957–s10982 | 26 | per-column gain read | **20 `ld.global.v2.u16`** at `W + ((laneid<<2)&12) + {103680…103984}` (s10963…s10982) |
| s10983–s11502 | 520 | normalise and combine | 320 `mul.f16`, 160 `mov.b32`, 40 `cvt.rn.satfinite.e4m3x2.f16x2` |
| s11503–s11605 | 103 | requantise and stage for phase 2 | **10 `st.shared.v4.u32`** |
| s11606 | 1 | `bar.sync 0` (L19151) | — |
| s11607–s11642 | 36 | phase 2's A fragments | **30 `ld.shared.v4.u32`** → `%r16785…%r16904` |
| s11643–s11653 | 11 | phase 2's B | 2 `ld.weak.global.ca.v4.u32` at `W + z*27648 + 16*laneid + {104000, 104512}` |
**The scatter (s1090–s2295).** The 60 stores are guarded (`setp.gt.u32 %p, …, 9`
at s1052 and its siblings) and the index is
`byte = 4 * ( (col & 3) | (40*row + 400*(col>>2)) )` into `SM`
(`shr.u32 %r4584, %r79, 2` / `mul.lo.s32 %r4585, %r4584, 400` /
`mad.lo.s32 %r4586, %r80, 40, %r4585` / `shl.b32 %r4587, %r81, 2` /
`add.s32 %r4588, %r4587, %r4586` / `and.b32 %r4589, %r79, 3` /
`or.b32 %r4590, %r4589, %r4588` — s1107–s1113). So dec4 writes **10-by-10
sub-blocks of 400 bytes** and 58 distinct `(row, col)` triples, versus dec3's
literal `+{0,1600,…,11200}` plane offsets. As in dec3 the `(row, col)` order is a
permutation of `laneid` derived with the golden-ratio multiplier
(`mul.wide.u32 %rd204, %r4338, -1431655765`, s1051). The store count differs from
dec3's 48 because dec4's phase 1 produces 800 columns instead of 640.
**The `param+24` gather (s3642–s9054).** `%rd1-56` is `param_0+24` (s4, s3640);
`%rd4 = cvta.to.global.u64(%rd253)` (s3641). Each of the 40 loads computes a
clamped halo index and issues
`mul.wide.u32 %rd254, %r34933, 4` / `add.s64 %rd255, %rd4, %rd254` /
`ld.global.v2.u16 {%rs426, %rs427}, [%rd255]` (s3792–s3794). The gather's
interior index is `clamped_row * %r7 + 8*clamped_col + min(laneid&3, 7)`, i.e. the
same **8-u32-per-image-row f16 buffer** as dec3's (§4/E1 of `rrswin_dec3_epilogues.md`).
**The inverse-std block.** The residual `add.f16` fold (first at s9217) yields a
value that is squared (`mul.f16`, s9620ff), reduced in-lane, summed with the
two-step butterfly `shfl.sync.bfly` (s10018, s10071), offset by `2⁻¹³` (s10075) and
inverted by 160 `rsqrt.approx.ftz.f32` (s10321…s10954). The gain table is 20
`ld.global.v2.u16` at `W + ((laneid<<2)&12) + {103680…103984}` (s10963…s10982) —
40 f16 per lane = 160 columns.
**Staging for phase 2.** `%r936 = %r9*2560` (s11503); the 10 `st.shared.v4.u32`
write at `SM + z*2048 + 16*laneid + {0,512,1024,1536}` (s11521, s11533, s11545,
s11557) and at `+{10240,10752,11264,11776,12288}` in a second group guarded by
`setp.gt.u32 %p626, %r10328, 31` with `%r10328 = %r9<<4` (s11574–s11575), i.e. only
`z ∈ {0,1}`. After `bar.sync` (s11606) the **30 `ld.shared.v4.u32`** at
`SM + 16*laneid + 512*i` (s11613…s11642) become **phase 2's A**
`%r16785…%r16904` (30 A fragments = 6 m-tiles × 5 k-steps), and the 2
`ld.weak.global.ca.v4.u32` at s11651/s11653 are phase 2's B.
### E2–E10 — s11678…s11900: next-B weight loads only
Seven statements each, exactly dec3's E2–E8 shape: 8 B fragments (16 registers) per
phase, read as `W + z*27648 + 16*laneid + base + 512*i`. The bases are
`104000` (P2), `109120` (P3), `105024` (P4), `110144` (P5), `106048` (P6),
`111168` (P7), `107072` (P8), `112192` (P9), `108096` (P10), `113216` (P11) — the
even phases walk `104000, 105024, 106048, 107072, 108096` and the odd phases
`109120, 110144, 111168, 112192, 113216`, i.e. **five k-group pairs** (dec3 had
four), so phases 2–11 together form one **96×64×160** GEMM split into ten
`96×32×32` phases chained through C (verified from the operand sets: P2/P3 use A
fragment set 0, P4/P5 set 1, P6/P7 set 2, P8/P9 set 3, P10/P11 set 4; P2/P3 have
C = the single zero register `%r16707` while P4…P11 take the previous phase's D).
### E11 — s11957–s12127: score-bias seeds and 80 packs of phase 10's D
171 statements, 24 weight loads + 80 packs — the dec3 E9 design with the wider N.
```
s11961 L21128 ld.weak.global.ca.v4.u32 { … }, [%rd…] // first of 24
s12008 L21313 cvt.rn.satfinite.e4m3x2.f16x2 … // first of 80 packs
```
* **24 loads** at `W + z*27648 + 16*laneid + 114240 + 512*i`, `i = 0…23`
(s11960 `add.s64 %rd357, %rd404, 114240` with `%rd404 = %rd383 + 16*laneid`,
`%rd383 = W + z*27648`; s11961 the first load, s11962 the next at `+114752`) →
**phase 12's C seeds** (96 registers = 24 C pairs). The block is
`[114240, 126028)`. Note this is a different *kind* of C operand from phase 1's:
phase 1 seeds each mma with a single u32 duplicated into both halves
(`{%r…, %r…}`), loaded as **20** `ld.global.u32` at
`[%rd203 + {102400, 102416, …, 102704}]` (s551–s570), whereas phase 12 takes 24
full 512-byte tiles.
* **80 packs** whose sources are **phase 10's D**, not phase 11's; they split into
phase 12's A fragments (`%r13134…%r13497`, 16 registers) and B fragments
(`%r13388…%r13499`, 24 registers = 12 fragments). Phase 11's own D reaches
E12's `movmatrix` block instead.
* The C-seed layout is the same as dec3's §4/E9:
`byte = base + 512*(4*(n>>1) + m) + 16*laneid + 8*(n&1)`, so the tile index runs
over 4 m-tiles and 6 `(n>>1)` groups = 24 tiles = 12288 bytes.
### E12 — s12176–s16019: softmax of the 64×96 score block, V-transpose, pack
**Phase 12** = 48 `mma` of 64×96 with C = the 24 bias pairs (E11). The epilogue has
**no memory access at all** (0 `ld.*`, 0 `st.*`) and no `bar.sync`. Its op
histogram is byte-for-byte dec3's E10: 1048 `mov.b32`, 672 `cvt.rn.f16.f32`, 384
`cvt.rn.f16.f64`, 192 each of `fma.rn.f16x2` / `cvt.f32.f16` /
`rcp.approx.ftz.f32` / `mul.f16`, 144 packs, 112 `shl.b32`, 104 `add.f16x2`,
96 each of `mul.f16x2` / `max.f16x2` / `min.f16x2` / `neg.f16x2` / `and.b32`,
48 `movmatrix`, 16 `shfl.sync.bfly.b32`, 8 `add.f16`.
```
s12177 L21724 mov.f32 %f476, 0f3C8CCB50
s12178 L21727 cvt.rn.f16.f32 low, %f476
s12182 L21737 cvt.rn.f16.f64 %rs3280, %fd383
s14381 L28593 shfl.sync.bfly.b32 %r15668,%r15664,%r15820,%r15671,%r15831 // first of 16
s14511 L28919 rcp.approx.ftz.f32 fl, fl // first of 192
s15278 L30164 mul.f16 %rs4074,%rs4075,%rs4076 // first of 192
s15756 L31218 movmatrix.sync.trans.aligned.m8n8.b16 %r16028, %r12605 // first of 48
s15804 L31362 cvt.rn.satfinite.e4m3x2.f16x2 %rs4648, %r16036 // first of 144 packs
```
Sub-sections (the same partitioning dec3's §4/E10 documents):
| range | what |
|---|---|
| s12176–s14293 | 96 per-element groups: scale, clamp, cubic, exponent extract (all 96 `max.f16x2` ≤ s14278, `min.f16x2` ≤ s14282, `neg.f16x2` ≤ s14283, `and.b32` ≤ s14293) |
| s14294–s14508 | in-lane partial sums and the butterfly: 104 `add.f16x2` (s14294–s14503), 16 `add.s32` (s14378–s14500), 16 `or.b32` (s14379–s14501), **16 `shfl.sync.bfly.b32`** (s14381–s14502) → 8 row sums, 8 `add.f16` (s14390–s14505) |
| s14509–s15277 | 192 `cvt.f32.f16` (s14509–s15270) → **192 `rcp.approx.ftz.f32`** (s14511–s15272) → 192 `cvt.rn.f16.f32` (…s15274) = 96 reciprocals |
| s15278–s15755 | **192 `mul.f16`** (s15278–s15754) → 96 probabilities |
| s15756–s15803 | 48 `movmatrix` transposing **phase 11's D** |
| s15804–s16019 | 144 `cvt.rn.satfinite.e4m3x2.f16x2` packs (s15804–s16018) |
(The boundaries above are the runs between the first/last occurrence of each op,
verified with the lineariser; the exponent region's end is fixed by the last
`and.b32` at s14293 and the sum region's by the first `add.f16x2` at s14294.)
Per element the exponent is the clamped cubic of dec3's §4/E10:
```
m = clamp(f16(x * 0.017181396484375), -0.55615234375, +0.55615234375)
t = f16(m*(-m) + 0.92724609375)
u = f16(m*t + 1.375)
expval = f16 from bits ((bits(u)<<5) & 0x7FE07FE0)
```
and **there is no row maximum**: `max.f16x2` (96×) and `min.f16x2` (96×) are the
clamp, and the only warp shuffles are the 16 `shfl.sync.bfly` above. Contrast E62,
which does compute a real row max over 5 taps.
### E13 — s16068–s16341: stage P·V, seed phase 14
274 statements.
```
s16068 L32201 bar.sync 0
s16069 L32202 shl.b32 %r17033, %r9, 11
s16070 L32203 add.s32 %r17034, %r16783, %r17033
s16074 L32210 cvt.rn.satfinite.e4m3x2.f16x2 %rs4792, %r16368 // first of 32 packs
s16086 L32237 st.shared.v4.u32 [%r17036], {%r17040, %r17039, %r17038, %r17037}
s16128 L32328 shl.b32 %r34545, %r9, 9
s16133 L32335 ld.shared.v4.u32 {%r34550, %r34551, %r34552, %r34553}, [%r34549]
s16138 L32343 ld.weak.global.ca.v4.u32 { %r17055,%r17056,%r17057,%r17058},[%rd405]
s16162 L32388 ld.global.v2.u16 {%rs7270, %rs7271}, [%rd889+325200] // first of 20
s16183 L32410 add.f16 %rs4826,%rs7309,%rs4828 // first of 80
```
* s16068 `bar.sync`; s16069–s16073 build `%r17036 = SM + z*2048 + 16*laneid`;
* 32 `cvt.rn.satfinite.e4m3x2.f16x2` packing phase 13's D and 4
`st.shared.v4.u32` at `SM + z*2048 + 16*laneid + {0,512,1024,1536}`
(s16086, s16100, s16114, s16127);
* s16128–s16132 `%r34549 = SM + z*512 + 16*laneid`; s16133
`ld.shared.v4.u32` → **phase 14's A fragment #0** (`%r34550…%r34553`);
* s16137–s16156 **10 weight loads** at `W + 16*laneid + {126528, 127040, 128064,
128576, 129088, 129600, 130112, 130624, 131136}` → phase 14's B (20 fragments =
40 registers);
* s16161–s16181 **20 table loads** at `W + ((laneid<<2)&12) + {325184, 325200, …
325488}` (16-byte stride) → 40 f16 per lane = a per-column table;
* s16182–s16341 **80 `add.f16`** → 40 b32 `%r17104, %r17105, …` = **phase 14's C
seeds**, exactly `table[col] + residual` (s16183 `add.f16 %rs4826,%rs7309,%rs4828`
where the second operand is the E1 residual register).
So `phase 14: D = A·B + (skip_residual + column_table)`.
### E14–E20 — s16362–s16670: A from `SM` + next-B, seven times
27 statements each: one `ld.shared.v4.u32` (one A fragment, `%r34557…%r34560` in
E14, then `%r34563…`, `%r34569…`, `%r34575…`, `%r34581…`, `%r34587…`, `%r34593…`),
10 `ld.weak.global.ca.v4.u32` (the next phase's B, 20 fragments = 40 registers) and
the address arithmetic. Example, E14 (s16362–s16388): `s16365 ld.shared.v4.u32`,
`s16370 ld.weak.global.ca.v4.u32` (first of 10).
Together with E13 this supplies the A k-fragments of phases 14–21, which are one
GEMM **16×160×256** split across eight `mma` phases chained through C (P15 C = P14's
D, …, P21 C = P20's D). The B blocks are `126528` (P14), `154176` (P15), `181824`
(P16), `209472` (P17), `237120` (P18), `264768` (P19), `292416` (P20), `320064`
(P21).
### E21 — s16691–s17719: RMS norm before the MLP
1029 statements, no stores. The dec3 E15 design scaled by 160/128.
```
s16691 L34285 shl.b32 %r34597, %r9, 1
s16693 L34287 mov.b32 {%rs6072, %rs6075}, %r18790 // first of 302
s16694 L34289 mul.f16 %rs5066,%rs6075,%rs6075 // first of 240 squares
s16895 L34846 shfl.sync.bfly.b32 %r19103,%r19099,%r15820,%r19106,%r15831 // first of 4
s16920 L34912 mov.f64 %fd386, 0d3F20000000000000 // eps = 2^-13
s16921 L34914 cvt.rn.f16.f64 %rs5309, %fd386
s17046 L35286 rsqrt.approx.ftz.f32 fl, fl // first of 80
s17368 L35807 ld.global.v2.u16 {%rs7310, %rs7311}, [%rd906+325520] // first of 20 gain loads
s17632 L36554 ld.weak.global.ca.v4.u32 { %r19224,%r19225,%r19226,%r19227},[%rd485] // first of 10 next-B
s17656 L36599 ld.global.u32 %r19314, [%rd911+330944] // first of 4 next-C bias words
s17660 L36604 cvt.rn.satfinite.e4m3x2.f16x2 %rs6031, %r33783 // first of 40 packs
```
| range | stmts | op |
|---|---|---|
| s16691–s16903 | 213 | lane/origin setup and 160 `mul.f16` squares (the remaining 80 of the 240 are in the normalise) |
| s16853–s17040 | 188 | in-lane/butterfly sums: 42 `add.f16x2` (s16853–s16917), 4 `or.b32` (s16894–s16915), **4 `shfl.sync.bfly.b32`** (s16895–s16916), 82 `add.f16` (s16904–s17040) |
| s16920–s16921 | 2 | eps `2⁻¹³` in `%fd386` (`cvt.rn.f16.f64 %rs5309, %fd386` at s16921) |
| s17044–s17361 | 318 | 80 `cvt.f32.f16` (s17044–s17357) → **80 `rsqrt.approx.ftz.f32`** (s17046–s17359) → 80 `cvt.rn.f16.f32` (s17048–s17361) |
| s17368–s17387 | 20 | gain loads `W + ((laneid<<2)&12) + {325504…325808}` (`+325504` appears last, `+325520` first) |
| s17632–s17659 | 28 | 10 `ld.weak.global.ca.v4.u32` (phase 22's B, `320064 + 512*i`, s17632–s17650) then 4 `ld.global.u32` at `330944/330960/330976/330992` (phase 22's C bias word, s17656–s17659) |
| s17660–s17718 | 59 | 40 packs → phase 22's A |
**What it computes** — the same expression as dec3's §4/E15:
```
sumsq[row] = Σ_c x[row,c]² (f16, in-lane tree + 4-lane butterfly)
inv = rsqrt.approx.ftz.f32(f32(f16(sumsq + 2⁻¹³))) // rounded to f16
out[row,c] = x[row,c] * inv * gain[c]
```
with **no mean subtraction and no `1/N`**, and the gain is a per-column table read
with the `W + ((laneid<<2)&12) + off` pattern. The norm's bias is not added here:
it is phase 22's C seed, loaded at s17656.
### E22 — s17740–s18060: clamped cubic activation + column bias
321 statements.
```
s17740 L36884 mov.u32 %r19505, %laneid
s17741 L36886 mov.f32 %f1117, 0f3ED306EB
s17744 L36893 mov.f32 %f1118, 0f3DA60DD6
s17747 L36900 mov.f32 %f1119, 0f3F000000
s17750 L36907 mov.f32 %f1120, 0f40000000
s17753 L36915 neg.f16x2 %r19510,%r19509 // first of 8
s17754 max.f16x2 … // first of 8
s17755 min.f16x2 … // first of 8
s17756 abs.f16x2 … // first of 8
s17757 L36931 mul.f16x2 %r19520,%r19507,%r19518 // first of 24
s17758 sub.f16x2 … // first of 8
s17760 add.f16x2 … // first of 8
s17883 add.s64 … // column-table addressing
s17885 L37377 ld.weak.global.ca.v4.u32 … // first of 10 next-B loads
s17909 L37422 ld.global.v2.u16 {%rs7350, %rs7351}, [%rd916+336144] // first of 20 table loads
s17929 L37469 add.f16 … // first of 80 bias adds
s18049 L37803 cvt.rn.satfinite.e4m3x2.f16x2 %rs6311, %r19648 // first of 8 packs
```
Per element, over each of the 8 f16x2 groups of phase 22's D:
```
y = clamp(x, -2, +2) // neg/max/min, s17753–s17755
g = 0.5 + y * (0.412109375 - 0.0810546875 * |y|) // abs/mul/sub/mul/add, s17756–s17760
out = x * g
```
`g` is a **cubic ramp, not a sigmoid**: `g(+2) = 1` ⇒ `out = x` for `x ≥ 2`;
`g(-2) = 0` ⇒ `out = 0` for `x ≤ -2`. **Reproduce the formula, not SiLU/GELU.**
The constants `%f1117…%f1120` are defined here and are re-read as
`cvt.rn.f16.f32 low, %f1117…%f1120` by every later activation epilogue.
Then 20 table loads (s17909 = `+336144`) and 80 `add.f16` (s17929–s18047) write the
table over the activation **inputs**, producing **phase 23's C seeds**; the final 8
packs (s18049…) build **phase 23's A** (one 4-register fragment); and the 10
`ld.weak.global.ca.v4.u32` from s17885 are phase 23's B block `[331008, 336128)`.
### E23 — s18081–s18172: packs, then next B/C
92 statements:
```
s18081 L37971 mov.u32 %r19988, %laneid
s18085 L37979 ld.weak.global.ca.v4.u32 … // first of 10 next-B loads
s18109 L38022 ld.global.u32 %r20079, [%rd921+341568] // first of 4 next-C bias words
s18113 L38027 cvt.rn.satfinite.e4m3x2.f16x2 %rs6319, %r33783 // first of 40 packs
```
40 packs (20 b32) → **phase 24's A**; 10 `ld.weak.global.ca.v4.u32` → phase 24's B
`[336448, 341568)`; 4 `ld.global.u32` at `341568/341584/341600/341616` → phase 24's
C bias.
### E24 … E60 — the repeating MLP stack
The pattern `(activation, first one with a table add) → (40 packs + next B/C)`
repeats with a period of two phases. Numbering the phases: the **even** phases 22,
24, …, 60 each have a 321/172-statement activation epilogue; the **odd** phases 23,
25, …, 59 each have a 92-statement pack epilogue. Verified op histograms:
* P22 epi (s17740–s18060, 321): 80 `add.f16`, 76 `mov.b32`, 32 `cvt.rn.f16.f32`,
24 `mul.f16x2`, 20 `ld.global.v2.u16`, 10 `ld.weak`, 8 each of
`neg/max/min/abs/sub/add.f16x2`, 8 packs.
* P23 epi (s18081–s18172, 92): 40 packs, 20 `mov.b32`, 10 `ld.weak`, 4 `ld.global.u32`.
* P24 epi (s18193–s18364, 172): 172 statements with 8 packs and 10 `ld.weak` and
**no** `ld.global.v2.u16`, i.e. no column table add — the residual is carried by
the C operand that E23 loaded.
The B blocks advance 4128 bytes per phase: `336448` (P24), `341632` (P25),
`346752` (P26), `351936` (P27), `357056` (P28), … `521920` (P60), `527104` (P61),
`532224` (P62), and each phase's C bias words sit in the 48-byte window 48 bytes
below the next phase's B base (e.g. P24's C at `341568..341616`, loaded at s18109).
### E61 — s23857–s24154: pack → plane-arena scatter → next B/C
298 statements.
```
s23857 L57579 cvt.rn.satfinite.e4m3x2.f16x2 %rs7231, %r34324 // first of 40 packs
s23917 L57718 ld.param.u64 %rd1050, [%rd1+-32] // S = plane arena (param+48)
s23918 L57719 cvta.to.global.u64 %rd5, %rd1050
s23920 L57723 shr.u32 %r958, %r34544, 2 // g = laneid>>2
s23921 L57724 and.b32 %r959, %r34544, 3 // t = laneid&3
s23924 L57727 add.s32 %r34630, %r937, %r34628 // y = %r937 + (laneid>>5)
s23930 L57733 add.s32 %r34631, %r1, %r34629 // x = %r1 + (g&7)
s23943 L57747 st.global.u32 [%rd1052], %r938 // first of 20 stores
s24139 L57579-… ld.weak.global.ca.v4.u32 // first of 5 next-B loads
s24153 ld.global.u32 … // first of 2 next-C seeds
```
* 40 packs → 20 b32 `%r938…%r957`, which are simultaneously **phase 62's A
fragments** — the same 20 registers are scattered to memory and fed to the last
GEMM.
* `S = cvta.to.global.u64(param_0+48)` via `%rd1-32` (s23917–s23918) — the entry's
only read of `param_0+48`.
* **20 `st.global.u32`** (first at s23943 with value `%r938`), each guarded by
`setp.lt.s32 %p, %r34630, 0` / `setp.ge.u32 %p, %r34630, %r1014` /
`setp.gt.u32 %p, %r34544, 63` combined with `or.pred` (s23925–s23929) and the
matching x guards, then a `selp.b32 …, -1, …, %p1` + `setp.lt.s32` + `bra` that
turns a guard failure into "skip the store".
* The index is `idx = (8*ex)*y + 8*x + d` with `%r7 = ex<<3` (s17),
`y = %r937 + (laneid>>5)` where **`%r937 = %r3 + 2*%r9`** (s16691–s16692), and
`x = %r1 + ((laneid>>2)&7)`, `d = t` (or `d = t|4`), exactly dec3's §5 formula.
* after the stores: 5 `ld.weak.global.ca.v4.u32` at
`W + 16*laneid + {532224, 532736, 533248, 533760, 534272}` (s24138–s24147,
`%r34660…%r34679`) = phase 62's B (10 fragments = 20 registers), then 2
`ld.global.u32` at `W + ((laneid<<2)&12) + {534784, 534800}` (s24153–s24154,
`%r34690`/`%r34700`) = phase 62's C seeds.
### E62 — s24165–s24446: softmax over five taps, 3×3 texture gather, surface write
282 statements; the entry's last statement is the `ret`.
```
s24165 L58082 bar.sync 0
s24170 L58089 shl.b32 %r997, %r34888, 4
s24177 L58096 st.shared.u32 [%r998], %r34761
s24181 L58101 st.shared.u32 [%r998+16], %r34771
s24198 L58121 add.s64 %rd1127, %rd1128, 80
s24209 L58132 add.s32 %r1003, %r1, %r1001 // x
s24210 L58133 add.s32 %r1004, %r3, %r1002 // y
s24215 L58138 ld.param.v2.u32 {%r34806, %r34807}, [%rd1127+-80] // ex, ey
s24223 L58147 add.s64 %rd1129, %rd1130, 80
s24233 L58157 ld.param.u64 %rd1123, [%rd1129+32] // output surface (param+112)
s24246 L58191 (first of 12 mul.ftz.f32 by 0f3FB8AA3B)
s24247 L58192 ex2.approx.ftz.f32
s24328 L58360 ld.param.v2.f32 {%f1180, %f1181}, [%rd1129+56] // param+136 scale pair
s24334 L58366 ld.param.u64 %rd1117, [%rd1129+8] // param+88 low-res texture
s24336 L58369 tex.base.2d.v4.f16.f32 {%rs7418,…,}, [%rd1101, {%f1140,%f1141}]
s24410 L58541 ld.param.u64 %rd1119, [%rd1129+16] // param+96
s24411 L58543 tex.base.2d.v4.f16.s32 {%rs7562,…,}, [%rd1119, {%r1003,%r1004}]
s24412 L58545 ld.param.u64 %rd1121, [%rd1129+24] // param+104
s24413 L58547 tex.base.2d.v4.f16.s32 {%rs7566,…,}, [%rd1121, {%r1003,%r1004}]
s24445 L58635 sust.b.2d.v4.b16.zero [%rd1123, {%r34877,%r1004}], {%rs7619,%rs7620,%rs7621,%rs7618}
```
Op histogram (s24165–s24446): 30 `fma.rn.f16`, 17 `mov.b32`, 16 `add.s32`,
13 `setp.lt.s32`, 12 each of `mul.ftz.f32` / `cvt.rn.f16.f32` / `selp.b32`,
10 each of `cvt.f32.f16` / `ex2.approx.ftz.f32` / `add.ftz.f32`,
9 `tex.base.2d.v4.f16.f32`, 8 `mov.u64`, 6 each of `mov.u32` / `and.b32` /
`shl.b32` / `bra` / `cvt.rn.f32.s32` / `fma.rn.ftz.f32`, 5 `ld.shared.u32`,
5 `sub.f16x2`, 5 `mul.f16x2`, and 1 `sust`.
| range | stmts | what |
|---|---|---|
| s24165–s24197 | 33 | `bar.sync` (s24165) + stage phase 62's D into `SM` at `(48*y + 6*x)` slots (4 `st.shared.u32`, s24177–s24194) |
| s24198–s24227 | 30 | pointer setup: `%rd1127 = %rd1128 + 80` (s24198), second `bar.sync` (s24199), the integer coordinates `%r1003 = %r1+%r1001` / `%r1004 = %r3+%r1002` (s24209–s24210), `(ex, ey)` read from `%rd1127-80` (s24215), bounds guard (s24216–s24222), `%rd1129 = %rd1130 + 80` (s24223) |
| s24228–s24241 | 14 | surface pointer `param+112` = `[%rd1129+32]` (s24233), **5 `ld.shared.u32`** reading 5 consecutive taps (s24228–s24234), and the row max: 3 `max.f16x2` (s24236–s24238) + 2 `max.f16` (s24240–s24241) |
| s24233 / s24243–s24326 | — | surface pointer `param+112` (s24233); softmax: 5 `sub.f16x2` (s24243–s24295), 12 `mul.ftz.f32` (s24246–), 10 `ex2.approx.ftz.f32` (s24247–), `div.approx.ftz.f32` (s24304, s24418), 5 `mul.f16x2` (s24307–s24311), 3 `cvt.rn.f16.s32` (s24312–s24314), 12 `selp.b32` (s24319–) |
| s24327–s24333 | 7 | clamped coordinates `clamp(p-1, 1, ex-2)` / `clamp(p-1, 1, ey-2)` (6 `cvt.rn.f32.s32` s24327–, 6 `fma.rn.ftz.f32` s24330–, `ld.param.v2.f32` s24328) |
| s24334–s24410 | 77 | 9 `tex.base.2d.v4.f16.f32` (s24336–s24406) at the 3×3 stencil of `param+88`, accumulated with 30 `fma.rn.f16` (s24338–s24427) |
| s24411–s24413 | 3 | 2 `tex.base.2d.v4.f16.s32` at `param+96` (s24410–s24411) and `param+104` (s24412–s24413), both at `{%r1003, %r1004}` |
| s24414–s24444 | 31 | `sigmoid`-like blend (s24418 `div.approx`, s24421 `sub.f16`, 3 `mul.f16` s24422–s24426, 3 `fma.rn.f16`) then the per-channel NaN guard on `param+104`: 3 `set.nan.f16.f16` (s24428–s24438) → `setp.ne.s16` → `@p bra` → 3 `add.f16` (s24431–s24441) |
| s24445 | 1 | `sust.b.2d.v4.b16.zero` surface write |
**Where the +96/+104 reads go.** `%rd1129+16` = `param+96` (s24410) and
`%rd1129+24` = `param+104` (s24412). Both are `tex.base.2d.v4.f16.s32` reads at the
same integer coordinate `{%r1003, %r1004}` = `(x, y)` (s24209–s24210);
`param+96`'s channels are added unconditionally, while `param+104`'s are added
**per channel only when the channel is not NaN** (`set.nan.f16.f16`). The surface
written is `%rd1123 = param+112` (s24233), and the write lands at
`(%r34877, %r1004)` with `0` in the fourth channel (s24445).
**What the +24 skip input supplies.** `param_0+24` (reached as `%rd1-56`, s3640)
supplies the f16 image values that E1 adds to the shared-staged features (s9217
onward) to form the residual. That residual is used in E1's own normalisation
(`mul.f16`) and is added to the per-column table at `W+325184` in E13
(s16182–s16341) to seed phase 14's C operand.
## 5. The plane-arena writes (`param_0+48`)
`S = cvta.to.global.u64(%rd1050)` with `%rd1050 = ld.param.u64 [%rd1+-32]`
(s23917–s23918) is the **only** occurrence of `param_0+48` in the entry. There are
exactly two store groups in the whole entry:
**(i) E61, 20 × `st.global.u32 [%rd1052 + …], v` — s23943 … s24129.** The first
is `s23943 L57747 st.global.u32 [%rd1052], %r938` and the last is
`s24129 L57971 st.global.u32 [%rd1090], %r957`; the values are `%r938…%r957` in
file order (the same 20 registers that become phase 62's A). Each is guarded as
described in §4/E61:
```
idx = (8*ex)*y + 8*x + d, guard y >= 0, y < ey, laneid <= 63, x >= 0, x < ex
y = %r937 + (laneid>>5), %r937 = %r3 + 2*%r9, x = %r1 + ((laneid>>2)&7),
d = t (first of each pair) | d = t|4, with t = laneid&3
where ex = %r1013, ey = %r1014 (s15), %r1 = block origin x (s7), %r3 = block origin y (s14)
```
**(ii) E62, the shared staging** at s24177/s24181/s24190/s24194: `st.shared.u32`
into `SM`, not the arena.
**What is written:** phase 61's requantised 16×160 output (20 u32 per lane).
**What reads it back:** nothing inside this kernel — `param_0+48` is never the base
of an `ld.*`, and phase 62's A comes from registers (`%r938…%r957`, E61's own
packs). See §6.
## 6. Uncharacterised
**U1. The shared-memory layout of E1's first scatter.** dec4 writes with
`byte = 4 * ((col&3) | (40*row + 400*(col>>2)))` (s1107–s1113) into a 16 KB array,
rather than dec3's literal `+{0,1600,…,11200}` plane offsets. I did not reduce the
`(row, col)` permutation of `laneid` (built with `mul.wide.u32 %rd204, %r4338,
-1431655765`, s1051) to a closed form, nor map each plane to a source element of the
800-column phase-1 output. *Missing:* a shared-memory dump or the producer's D
layout.
**U2. `%r16781 = %r9*13824` (s11607) feeding `%rd381` (s11608).** `%rd381` is used
at s11645 as the slab term `W + z*27648` for phase 2's B. The *derivation* `13824*2`
looks like a per-slab stride expressed for a different tile width, so the constant
13824 is presumably the per-slab output-tile size divided by 2, but nothing in the
PTX states it. *Missing:* the weight-image layout description.
**U3. The identity of the per-column tables.** `W+325184` (E13), `W+336144` (E22),
`W+103680…103984` (E1's gain), `W+325504…325808` (E21's gain) are all read with the
same `W + ((laneid<<2)&12) + off` pattern. Their *roles* are computable (E13: added
to the skip before phase 14; E22: added after the activation; E1/E21: multiply the
inverse std) but their *names* are not. The same is true of the GEMM biases at
`102400…102704` (P12), `126528`-adjacent words and `534784/534800` (P62).
*Missing:* the weight image's `_prep` permutation or the model's parameter names.
**U4. The identity of the 12288-byte score bias.** Phase 12 adds a 12288-byte f16
table (`W + z*27648 + 114240 … 126028`) as its GEMM C operand, laid out as §4/E11
describes. Whether it is a relative position bias, a learned score bias, or a
per-lane constant cannot be decided from the PTX.
**U5. The geometry of the banded phases.** Twenty-three phases print an M/N/K that
fails `M/16·N/8·K/32 == mma` (P1, 13, 22–60 even, 62). For the even phases
22…60 I verified the 5-step cascade shape (A = 5 fragments, B = 20 fragments,
`mma = 20 = 5*4` with the C-chain running over the A fragments), and for P62
likewise (A = 5 fragments, B = 10 fragments, `mma = 10 = 5*2`). For **P1**
(300 mma, 100 B fragments, 250 distinct C/D pairs) and **P13** (48 mma, C set of 65
registers) I did not reduce the full (M, N, K) reading. The epilogue contracts
above do not depend on resolving this.
**U6. The logical meaning of E62's blend.** E62 computes a blend of a 3×3
`tex.base.2d.v4.f16.f32` gather of `param+88` (weighted by a 5-tap softmax) with the
`param+96` texture and, per channel under a NaN guard, the `param+104` texture, then
writes `param+112` at `(8·x, y)`. The PTX gives the arithmetic exactly but not
which model term this is. *Missing:* the high-level source or a reference.
**U7. The count of distinct input-buffer strides.** dec4's prologue/`E1` use
×25600 (s438), ×160 (s543) and ×40 (s1052) for `%r9` in addition to the shared and
weight strides. I did not determine which of the three addresses the prologue's
gather (`param+8`) versus E1's gather (`param+24`) versus some other buffer.
*Missing:* a mapping from `%r9` to buffer identity.
## 7. Quick acceptance index
| requirement | where |
|---|---|
| patch expand | §4/E1 (s871–s11653) and phase 1 (§2) |
| the norms | E1's rsqrt block (s9215–s10956, eps s10075) and E21 (s16691–s17719, eps s16920) |
| the attention | E11 (score seeds + packs), E12 (softmax + `movmatrix` s15756–s15803 + packs), E13 (P·V staging) |
| the activations | E22, E24, …, E60 — the clamped cubic `x·(0.5 + y·(0.412109375 − 0.0810546875·|y|))`, `y = clamp(x,±2)`; constants s17741–s17750 |
| the per-launch table in the plane arena | §5, s23917/s23943ff (`param_0+48`) |
| every epilogue of every phase | §3 summary table + §4 (E1–E62) |
| texture reads at +96/+104 and where the surface write goes | §4/E62, s24410–s24413 and s24233/s24445 |
| what the skip input at +24 supplies | §1.1 (s3640) and §4/E1, E13 |
| phase table M/N/K arithmetic checked | §2 (23 phases fail; listed) |
| weight-image extent | §2 (≥ 534804 bytes; last read s24153 + 2 words) |
| phases with no weight operand | §2: 12 and 13 |
| uncharacterised | §6 |