From d913bca9b742a197490d3228c7ea7c12299e1eb4 Mon Sep 17 00:00:00 2001 From: Drew T <50529377+Druthulu@users.noreply.github.com> Date: Sat, 5 Sep 2026 13:20:36 -0600 Subject: [PATCH] =?UTF-8?q?docs(phase-32):=20T4b=20(2)=20ledger=20?= =?UTF-8?q?=E2=80=94=20func=5F80039DEC=20unpinned=20(5=20walls=20remain),?= =?UTF-8?q?=20backlog=20re-rendered,=20the=20Fable=20draft=20+=20report=20?= =?UTF-8?q?+=20verdict=20kept=20(R20)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .run/P32/t5x/fable/func_80039DEC.c | 47 +++++++++++++++++ .run/P32/t5x/reports/func_80039DEC.md | 74 +++++++++++++++++++++++++++ .run/P32/t5x/verdicts.jsonl | 1 + config/wave_exclude.txt | 3 +- docs/backlog.md | 29 +++++------ 5 files changed, 137 insertions(+), 17 deletions(-) create mode 100644 .run/P32/t5x/fable/func_80039DEC.c create mode 100644 .run/P32/t5x/reports/func_80039DEC.md diff --git a/.run/P32/t5x/fable/func_80039DEC.c b/.run/P32/t5x/fable/func_80039DEC.c new file mode 100644 index 0000000000..4401a19eab --- /dev/null +++ b/.run/P32/t5x/fable/func_80039DEC.c @@ -0,0 +1,47 @@ +void func_80039DEC(a0, a1, a2) + void *a0; + s16 a1; + s16 a2; +{ + u8 cnt; + s32 tmp; + + switch (a2) { + case 0x14: { + u8 *p = (u8 *)a0 + a1 * 26; + p[0x1F] = a2; + p[0x22] = 0x18; + p[0x21] |= 3; + break; + } + case 0x1E: + if (*(u8 *)((u8 *)a0 + 0x1F6) == 0) { + *(u8 *)((u8 *)a0 + 0x1F9) = 1; + return; + } + cnt = *(u8 *)((u8 *)a0 + 0x1F5); + if ((u8)cnt != 0x7F) { + *(u8 *)((u8 *)a0 + 0x1F5) = cnt + 0xFF; + if ((u8)cnt == 0) { + return; + } + } + tmp = *(s32 *)((u8 *)a0 + 0xC); + *(u8 *)((u8 *)a0 + 0x1F7) = a1 | 0xB0; + *(s32 *)a0 = tmp; + break; + case 0x28: { + u8 *p = (u8 *)a0 + a1 * 26; + p[0x1F] = a2; + p[0x22] = 0x1A; + p[0x21] |= 3; + break; + } + default: { + u8 *p = (u8 *)a0 + a1 * 26; + p[0x1F] = a2; + p[0x21] |= 1; + break; + } + } +} diff --git a/.run/P32/t5x/reports/func_80039DEC.md b/.run/P32/t5x/reports/func_80039DEC.md new file mode 100644 index 0000000000..6aa3411388 --- /dev/null +++ b/.run/P32/t5x/reports/func_80039DEC.md @@ -0,0 +1,74 @@ +# func_80039DEC (main / src/800_c.c, 74 ins) — Fable T5x report, 2026-09-05 + +**Verdict: MATCH** — `match_one` 74/74 and `rtu_match` MATCH in the real TU (`src/800_c.c`, decl `extern void func_80039DEC();`). +Draft: `.run/P32/t5x/fable/func_80039DEC.c` (identical to `.run/P32/t5x/work/func_80039DEC/sw2.c`). No pins, no +fences, no launders, no `do{}while(0)`. The `.s` carries no relocation lines (no jal/HI16/LO16), so there is no symbol +identity to cross-check (SYS law 1c) — every immediate was spelled from the target. + +## What closed it — the mechanism, read from the compiler + +The residual (sonnet-9: 9 ins; permuter: 2 ins) was a clean swap of the two K&R raw-preserve parameter copies: +target puts a2-raw in `$a3` and a1-raw in `$t0`, every draft did the reverse. Both copies are `reg/v:HI` parm pseudos +(73 = a1, 75 = a2; lreg dump insns 8/12) with NO satisfiable hard-reg preference (their sources 74/76 keep `$a1`/`$a2` +and overlap them), so both fall through `find_reg`'s pass 0 (candidates = `regs_used_so_far` only, `global.c:948-951`, +"we never allocate a register for the first time in pass 0") into pass 1, which hands out the LOWEST free register by +number (`global.c:960-985`; MIPS has no `REG_ALLOC_ORDER`). Hence: **whichever of the two is allocated FIRST gets `$7` +(`$a3`), the other `$8` (`$t0`).** The order is `allocno_compare` (`global.c:587-608`): + + pri = floor_log2(n_refs) * n_refs * size / live_length + +with `n_refs` from `flow.c:2067` (`reg_n_refs[regno] += loop_depth`) and `live_length` the insn count where the reg is live. + +Measured (lreg dumps, `.run/c294/dumps_t5x_9DEC_{s9,sw2}/*.i.lreg`): + +| draft | a1-raw (73) | a2-raw (75) | pri(73) | pri(75) | allocated first | greg dispositions | +|---|---|---|---|---|---|---| +| sonnet-9 (`L_merge` + `kind`) | 3 refs / 26 | **3 refs / 45** | 1·3/26 = 1153 | 1·3/45 = 666 | 73 | `73 in 7 75 in 8` (wrong) | +| sw2 (duplicated case tails) | 3 refs / 26 | **4 refs / 41, dies in 3 places** | 1153 | 2·4/41 = **1951** | 75 | `73 in 8 75 in 7` (target) | + +The target's dispatch (`beq 0x1E` → `slti 0x1F`/`beqz` → `beq 0x14` | `beq 0x28`) is gcc's `emit_case_nodes` balanced +tree for a 3-case `switch` (`stmt.c:4907`, `:5580-5651`; count < 5 → tree, no jump table), relocated in front of the case +bodies by `reorder_insns` at `stmt.c:5055` — which is why the bodies sit in SOURCE order (0x14, 0x1E, 0x28, default) after +the tree. The shared `.L80039ECC` tail (`sb $a3; sb $a0; ori 3; sb $v1`, entered by `j` from L_14 with `addiu $a0,0x18` in +the delay slot and by fall-through from L_28 after `addiu $a0,0x1A`) is jump.c's post-reload CROSS-JUMP (`jump.c:1923`, +`find_cross_jump`/`do_cross_jump`) of two textually identical case tails. So at flow/global-alloc time the +original had THREE `sb ` uses (case 0x14, case 0x28, default) — a2-raw's fourth ref, `floor_log2(4) = 2`, and the +higher priority. Every prior draft merged the two tails at the C level (`goto L_merge` + a `kind` variable pinned to `$4`), +which deleted one `sb` use: 3 refs, `floor_log2(3) = 1`, and a1-raw won `$a3`. Attempt 1's `do{}while(0)` "ref-count +boost" worked by the same arithmetic (`loop_depth` 2 doubles the refs inside the pseudo-loop) — a less natural spelling of +the same lever, and it dragged a1-raw's `ori` inside too in the permuter lineage. + +**The `config/wave_exclude.txt` claim "fixed by ARGUMENT POSITION … 2nd param → $a3, 3rd → $t0" is refuted:** sw2 puts the +3rd parameter's copy in `$a3` and the 2nd's in `$t0`, exactly the target. And the T4b NOTES' hypothesis (`local_reg_n_refs` +skipping in pass 0) is not what the code does: `local_reg_n_refs` is consulted only in the kick-out retry when +`best_reg < 0` (`global.c:1108-1160`), which never fires here. + +## Variants measured (all natural `switch`, same 0x1E block as sonnet-9) + +* **sw1** — one function-scope `u8 *p` assigned in all three cases: FAIL (structural, ~40 mismatched from idx 24). `p` is + then used in several blocks → `REG_BLOCK_GLOBAL` → one global allocno for all three address temps, which must be ONE + hard reg; the target has the entry pointer in `$v0` in L_14/L_28 but `$v1` in default (its `$v0` is taken by the + sign-extended a1 born in the `j` delay slot). Block-local temps are required. +* **sw2** — `case N: { u8 *p = …; … }` block-scope per case: **MATCH 74/74**, rtu MATCH. +* **sw3** — no temp, `((u8 *)a0 + a1 * 26)[k]` written out three times: 3 mismatches, all the final `addu`: + `addu $v0,$v0,$a0` vs target `addu $v0,$a0,$v0`. cse merges the three address expressions but the canonical form puts + the shift chain first; the named pointer local `p = (u8 *)a0 + a1 * 26` keeps `a0` as the first operand. Side-lesson: + when a base+scaled-index `addu` has its operands swapped, name the pointer as a local. + +## The permuter "closeness 2" was unsound (R63) + +`.run/S79w/permuter/func_80039DEC.c` stores `tmp` in the default path (`pd[0x1F] = tmp`) but assigns it only in +`L_merge` — uninitialized on that path. Its idx-65 `sb $a3` "matched" because the `tmp` pseudo (81, `reg/v:SI`, 5 refs/24) +out-prioritised both parm copies and took `$7` (`.run/c294/dumps_t5x_9DEC_perm2/*.i.greg`: `81 in 7`). The sound +ancestor's real residual was 9, not 2. + +## Cookbook harvest (for the coordinator) + +* **K&R raw-copy register choice is `allocno_compare` order, not argument position.** Two narrow K&R parms' HI copies have + no preference and take `$7`, `$8`, … in PRIORITY order (`floor_log2(n)·n/live_length`). To move one to `$a3`, give it + the ref count the original had — usually by NOT merging duplicated case tails at the C level (write the `switch` as + the author did; let cross-jump merge them post-reload). A `goto L_merge` + `kind` refactor deletes a ref and can flip + `floor_log2` (3→1 vs 4→2). Tell: exact-length draft, a pure `$a3<->$t0` swap of `addu $aN,$aM,$zero` copies, target + tails that look cross-jumped (`j` into a shared tail with a constant load in the delay slot). +* `switch` cases that share an address temp must declare it BLOCK-SCOPE per case (`case N: { T *p = …; }`) when the + target holds it in different registers per block; a function-scope temp becomes one global allocno. diff --git a/.run/P32/t5x/verdicts.jsonl b/.run/P32/t5x/verdicts.jsonl index 575fd5d58a..754e50555f 100644 --- a/.run/P32/t5x/verdicts.jsonl +++ b/.run/P32/t5x/verdicts.jsonl @@ -1 +1,2 @@ {"fn": "func_800391D4", "binary": "main", "arm": "fable", "status": "MATCH", "closeness": 0, "compiles": true, "draft_path": ".run/P32/t5x/fable/func_800391D4.c", "note": "explicit promotion `a1v = arg1` before `off = 0` (the extend becomes preheader source) + insn_count knife-edge re-padded 7 -> 9 __asm__(\"\") so loop.c:1631 keeps the D_800C6DD0 address un-hoisted (threshold 58 vs insn_count 59); coordinator rtu MATCH 75/75; gate_main BANKED 143dbb89", "session": "491895ad"} +{"fn": "func_80039DEC", "binary": "main", "arm": "fable", "status": "MATCH", "closeness": 0, "compiles": true, "draft_path": ".run/P32/t5x/fable/func_80039DEC.c", "note": "natural 3-case switch(a2) with DUPLICATED case tails (cross-jump merges them post-reload) + block-scope u8 *p per case; a2-raw keeps 4 refs (pri 1951) and is allocated first -> $a3 (global.c allocno_compare/find_reg); refutes the argument-position pin theory and the local_reg_n_refs hypothesis; the permuter's 2 was R63-unsound (tmp uninitialised). Coordinator rtu MATCH 74/74; gate_main BANKED 143dbb89", "session": "491895ad"} diff --git a/config/wave_exclude.txt b/config/wave_exclude.txt index ce584cafb1..b2480152cd 100644 --- a/config/wave_exclude.txt +++ b/config/wave_exclude.txt @@ -1,5 +1,5 @@ # regenerated by tools/exclude_audit.py from config/wave_exclude.txt -# 6 still-valid of 7; 1 dropped as stale (banked / linked / blocker-since-fixed). +# 5 still-valid of 6; 1 dropped as stale (banked / linked / blocker-since-fixed). # An exclude list records what the TOOLING could not do — regenerate it as # part of every tool fix, or it becomes a list of work you decided not to do. ov_SC03_105:func_801834A4 # WALL: loop.c movable ordering, closeness 6 (S71) | T4 S83: re-probed in the real TU (3 stored variants) DIFF 6 — CANDIDATE, unchanged @@ -7,4 +7,3 @@ ov_SC06_022:func_8017DF28 # WALL: expand_block_move copy_addr_to_reg pseudo cse main:func_80032A74 # WALL: candidate: 422/422, frame/offsets/27 symbols exact, sole residual idx 244 `lh` vs `lhu` — extendhisi2 is a force_not_mem EXPAND (an orphan frame slot is minted only at an lh), the target's 8 extra frame bytes are §172 producer 3 (caller-save area, reload1.c:1445); ~200 byte-probes incl. a 100-variant retyping sweep (S79 Opus) + permuter_ils 8x150s null (S80); closeness 1 | T4 S83: the S79w draft was a CC1 FAIL only for PLUMBING (7 header typedefs + 4 decl spellings); synced copy .run/P32/t4/drafts/func_80032A74_tuclean.c re-run in the real TU DIFF 1 (idx 244 lh vs lhu) — CANDIDATE, unchanged main:func_80020DA4 # WALL: candidate: 100/100, phantom 16-byte frame reproduced (address-taken frame_pad[3]); residual = mflo destination $t0 vs $a2 (REGALLOC-PERM), pinning regresses to 79; 5 attempts 51→20→14→8→2 (S7x/S79) + permuter_ils 8x150s null (S80); closeness 2 | T4 S83: re-probed in the real TU DIFF 2 — CANDIDATE, unchanged main:func_80011380 # WALL: §474 PROVED C-level floor (closeness 6) — fold-const.c:882 split_tree merges MULT(MULT(i,2),2); the two escapes each cost one instruction (stupid.c:497 adjacency / expand_decl use-brackets); §388 -O0 colouring oracle. Pinned S79 #8. | T4 S83: re-probed in the real TU (rtu --o0) DIFF 6 — PROVED (§474), unchanged -main:func_80039DEC # WALL: candidate: 74/74 exact length; the $a3<->$t0 swap of the two K&R raw-preserve parameter copies is fixed by ARGUMENT POSITION in gcc-2.7.2's narrow-parameter promotion (2nd param -> $a3, 3rd -> $t0) before the global allocator runs — every pin on the raw-preserve values regresses to 60-75; 3 attempts corroborate (S7x/S79 Sonnet 9) + permuter_ils 8x150s 9 -> 2 (S80); closeness 2 | T4 S83: CC1 FAIL was the TU's prototype (800_c.c:3496) vs the K&R definition; sandbox TU with the no-proto decl: permuter draft DIFF 2 (idx 0/56 t1 vs a3) — CANDIDATE, unchanged diff --git a/docs/backlog.md b/docs/backlog.md index 361bc7f9ba..23f8996440 100644 --- a/docs/backlog.md +++ b/docs/backlog.md @@ -2,22 +2,21 @@ > Generated by `tools/backlog.py render` from `.run/backlog.jsonl`. These are functions the Phase-21 automation got **close** on but did NOT byte-match. The whole-binary byte-gate is the sole arbiter (G3/P9): **byte-matches bank and are NOT listed here** — only genuine near-misses/blockers are. Ranked by hand-session priority: **reach** (×N propagation leverage) → **closeness** (match_one mismatch count, lower = closer) → **size**. Each row's `best_draft` is the closest C the machine reached — resume from there. -**Open near-misses:** 15 · by status {'near': 14, 'failed': 1} · by class {'WALL-CANDIDATE': 5, 'REGALLOC-PERM': 1, 'WALL-PROVED': 1, 'SCHED': 4, 'REGALLOC': 1, 'ALIAS': 1, 'FRAME': 1, None: 1} +**Open near-misses:** 14 · by status {'near': 13, 'failed': 1} · by class {'WALL-CANDIDATE': 4, 'REGALLOC-PERM': 1, 'WALL-PROVED': 1, 'SCHED': 4, 'REGALLOC': 1, 'ALIAS': 1, 'FRAME': 1, None: 1} | # | addr | reach | class | nins | status | closeness | where it stuck | best draft | |--:|------|------:|-------|-----:|--------|----------:|----------------|------------| | 1 | func_80032A74 | None | WALL-CANDIDATE | 422 | near | 1 | WALL candidate CONFIRMED in the real TU (S83): 422/422, sole residual idx 244 `lh v0,0x18(s1)` vs target `lhu` — extendhisi2 is a force_not_mem EXPAND (the orphan frame slot is minted only at an lh; §172 producer 3 caller-save area, reload1.c:1445), so lhu loses the 8 frame bytes; ~200 byte-probes + 100-variant retyping sweep (S79) + permuter_ils 8x150s null (S80). Citation current (§172, reload1.c:1445). Draft synced to the TU (typedefs stripped via cdecl.strip_provided_typedefs; D_80064D44/D_8006A970/func_8003F144/func_800316F8 spelled as the TU) | `.run/P32/t4/drafts/func_80032A74_tuclean.c` | -| 2 | func_80039DEC | None | WALL-CANDIDATE | 74 | near | 2 | WALL candidate CONFIRMED (S83 sandbox-TU rtu DIFF 2: idx 0 `move t1,a2` vs `addu a3,a2,zero`; idx 56 `sb t1` vs `sb a3`): 74/74 exact length; the $a3<->$t0/$t1 swap of the two K&R raw-preserve parameter copies is fixed by ARGUMENT POSITION in gcc-2.7.2 narrow-parameter promotion (2nd param -> $a3, 3rd -> $t0) before the global allocator runs — every pin regresses to 60-75; 3 attempts + permuter_ils 9 -> 2 (S80). Banking would need the TU decl -> no-proto (byte-neutral commit) — only worth it at closeness 0 | `.run/S79w/permuter/func_80039DEC.c` | -| 3 | func_80020DA4 | None | WALL-CANDIDATE | 100 | near | 2 | WALL candidate CONFIRMED (S83 rtu DIFF 2): 100/100, phantom 16-byte frame reproduced (address-taken frame_pad[3]); residual = mflo destination $t0 vs $a2 (REGALLOC-PERM), pinning regresses to 79; 5 attempts 51->20->14->8->2 + permuter_ils null (S80) | `.run/S79w/sonnet/func_80020DA4.c` | -| 4 | func_8017DF28 | None | WALL-CANDIDATE | 119 | near | 2 | WALL candidate CONFIRMED (S83 rtu DIFF 2): expand_block_move copy_addr_to_reg pseudo cse-reused for both later &mtx args (gcc-2.7.2-map cse_expr.md [A23-2]/§H); 119/119; the addiu $s2,sp,0x10 sits in the jal delay slot vs the target bnez slot; five RTL-verified attempts (S71/S79); permuter_ils (S80) "1" was a divergent rewrite (R63). Citation current ([A23-2] present in cse_expr.md) | `.run/S79w/sonnet/func_8017DF28.c` | -| 5 | func_800CD674 | None | REGALLOC-PERM | 174 | near | 2 | $a3<->$t1 across two masked prim pointers (one shared local can be only one; splitting = +1 pseudo displacing two hoisted constants, 31); SPRT-with-tpage family, §364 mirror (non-struct field stores). Inert: pin order (8 perms), assignment placement (6), volatile index, p+=0x18 spellings, u8* cursor, every pin subset. NEXT: permuter_ils on the pinned seed (§494 recipe) | `.run/P32/t3/opus/func_800CD674.c` | -| 6 | func_801834A4 | None | WALL-CANDIDATE | 106 | near | 6 | WALL candidate: loop.c movable ordering, closeness 6 (S71); re-probed S83 in the real TU: DIFF 6 for all three stored variants (unchanged) | `.run/S71_gate14/ov_SC03_105-cn-cast-rc-sd/func_801834A4.c` | -| 7 | func_80011380 | None | WALL-PROVED | 192 | near | 6 | §474 PROVED C-level floor (boot -O0): fold-const.c:882 split_tree merges MULT(MULT(i,2),2); the two escapes each cost one instruction (stupid.c:497 adjacency / expand_decl use-brackets); §388 -O0 colouring oracle. Pinned S79 #8; re-probed S83 in the real TU: DIFF 6 (unchanged) | `.run/m3/opus/func_80011380.c` | -| 8 | func_800CD92C | None | SCHED | 247 | near | 15 | map §S7 prologue WEAVE: the {sw,lui,ori} groups for 0xE100008D/8F land after the 9-insn li block instead of before — the §17 pins reproduce the ALLOCATION but the hoist happens in sched2. Same SPRT family as func_800CD674 (§364 mirror levers applied) | `.run/P32/t3/opus/func_800CD92C.c` | -| 9 | func_80039308 | None | REGALLOC | 518 | near | 17 | sched2 + cross-block regalloc: preheader 49/50 swap, un-spellable addu $a2,$a0,$zero (every p=r form cse-propagated), a temp on $t0 vs $s7, and 11 insns of one alias fact (2nd D_80073140[j] load cannot schedule above the D_800C7D20 store from C; /s unlock costs the address allocation, net 20-24). 34->17 via s16 b4 widening copy + dead-local identity sweep (.run/P32/t3/restored/sweep_func_80039308.py) + $2 pin. permuter_ils --klass REGALLOC 2x150s: no gain | `.run/P32/t3/opus/func_80039308.c` | -| 10 | func_800CF3E8 | None | ALIAS | 469 | near | 27 | ONE cause: the pinned-base alias basin (§500-D1) in the p5/p6 tail; blocks 1-2 byte-exact (idx 0-361). 54->27 via blk2 constant birth order + birthing-boost local w60 + §194-A fence relocation. Inert: all 9 pins load-bearing (+5..+1409), asm position x7, h6 hoist 32x2, tag reshape, P_TAG ADDPRIM, array p6 stores, ~92k annealed variants. Untested: an unpinned alias of p6 for the tag load alone (ONE Opus second look allowed) | `.run/P32/t3/opus/func_800CF3E8.c` | -| 11 | func_80185810 | None | SCHED | 489 | near | 35 | [permuter] 4 emission windows (see report .run/P32/t3/reports/func_80185810__opus__*.md); exact length, rtu-clean | `.run/P32/t3/opus/func_80185810.c` | -| 12 | func_8017DC80 | None | FRAME | 346 | near | 46 | the historic -33 LENGTH wall CLOSED (GTE macros must be REAL macros — the TU house block; the splat Handwritten tag is wrong): 346/346, exact 0x70 frame + 9 callee-saved. Residual: reload-slot frame + the la $a0 slot; cse1 unifies OT index and n<4 across func_80010A08(8) (§500-D2 zero-byte asm retire) | `.run/P32/t3/opus/func_8017DC80.c` | -| 13 | func_800CF408 | None | SCHED | 178 | near | 49 | [permuter] 3 hunks: two prologue sched2 slots, an mlo/mhi allocno tie, a 3-insn block-2 head hoist. Two LENGTH-bearing pins found (tp $17 shared by 0xE1000087/97 = the 6th callee-saved; ob $10 fixes the $t1/$t2/$t3 rotation, 56->49). §351 family (func_8001212C -O0 / func_8017DD04 -O2 exemplars) | `.run/P32/t3/opus/func_800CF408.c` | -| 14 | func_800CF6D0 | None | SCHED | 249 | near | 137 | sched1 rank_for_schedule last-insn-CLASS tie (every store priority 2, equal refs; QImode stores grouped, loads floated, HImode after — 5 of 6 blocks) + $t1<->$t3 local-alloc swap of the two masks. 249/249 exact length only with tpage-before-len field order (19 swept). Inert at 137: pins on tpage constants/masks, asm re-ties, volatile/memory fences, /s-denial on any store subset, *0x4000 vs <<14, p++ vs p+0x18, / swap. decomp-permuter 122 was semantically wrong (R63) | `.run/P32/t3/opus/func_800CF6D0.c` | -| 15 | func_80062144 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | | +| 2 | func_80020DA4 | None | WALL-CANDIDATE | 100 | near | 2 | WALL candidate CONFIRMED (S83 rtu DIFF 2): 100/100, phantom 16-byte frame reproduced (address-taken frame_pad[3]); residual = mflo destination $t0 vs $a2 (REGALLOC-PERM), pinning regresses to 79; 5 attempts 51->20->14->8->2 + permuter_ils null (S80) | `.run/S79w/sonnet/func_80020DA4.c` | +| 3 | func_8017DF28 | None | WALL-CANDIDATE | 119 | near | 2 | WALL candidate CONFIRMED (S83 rtu DIFF 2): expand_block_move copy_addr_to_reg pseudo cse-reused for both later &mtx args (gcc-2.7.2-map cse_expr.md [A23-2]/§H); 119/119; the addiu $s2,sp,0x10 sits in the jal delay slot vs the target bnez slot; five RTL-verified attempts (S71/S79); permuter_ils (S80) "1" was a divergent rewrite (R63). Citation current ([A23-2] present in cse_expr.md) | `.run/S79w/sonnet/func_8017DF28.c` | +| 4 | func_800CD674 | None | REGALLOC-PERM | 174 | near | 2 | $a3<->$t1 across two masked prim pointers (one shared local can be only one; splitting = +1 pseudo displacing two hoisted constants, 31); SPRT-with-tpage family, §364 mirror (non-struct field stores). Inert: pin order (8 perms), assignment placement (6), volatile index, p+=0x18 spellings, u8* cursor, every pin subset. NEXT: permuter_ils on the pinned seed (§494 recipe) | `.run/P32/t3/opus/func_800CD674.c` | +| 5 | func_801834A4 | None | WALL-CANDIDATE | 106 | near | 6 | WALL candidate: loop.c movable ordering, closeness 6 (S71); re-probed S83 in the real TU: DIFF 6 for all three stored variants (unchanged) | `.run/S71_gate14/ov_SC03_105-cn-cast-rc-sd/func_801834A4.c` | +| 6 | func_80011380 | None | WALL-PROVED | 192 | near | 6 | §474 PROVED C-level floor (boot -O0): fold-const.c:882 split_tree merges MULT(MULT(i,2),2); the two escapes each cost one instruction (stupid.c:497 adjacency / expand_decl use-brackets); §388 -O0 colouring oracle. Pinned S79 #8; re-probed S83 in the real TU: DIFF 6 (unchanged) | `.run/m3/opus/func_80011380.c` | +| 7 | func_800CD92C | None | SCHED | 247 | near | 15 | map §S7 prologue WEAVE: the {sw,lui,ori} groups for 0xE100008D/8F land after the 9-insn li block instead of before — the §17 pins reproduce the ALLOCATION but the hoist happens in sched2. Same SPRT family as func_800CD674 (§364 mirror levers applied) | `.run/P32/t3/opus/func_800CD92C.c` | +| 8 | func_80039308 | None | REGALLOC | 518 | near | 17 | sched2 + cross-block regalloc: preheader 49/50 swap, un-spellable addu $a2,$a0,$zero (every p=r form cse-propagated), a temp on $t0 vs $s7, and 11 insns of one alias fact (2nd D_80073140[j] load cannot schedule above the D_800C7D20 store from C; /s unlock costs the address allocation, net 20-24). 34->17 via s16 b4 widening copy + dead-local identity sweep (.run/P32/t3/restored/sweep_func_80039308.py) + $2 pin. permuter_ils --klass REGALLOC 2x150s: no gain | `.run/P32/t3/opus/func_80039308.c` | +| 9 | func_800CF3E8 | None | ALIAS | 469 | near | 27 | ONE cause: the pinned-base alias basin (§500-D1) in the p5/p6 tail; blocks 1-2 byte-exact (idx 0-361). 54->27 via blk2 constant birth order + birthing-boost local w60 + §194-A fence relocation. Inert: all 9 pins load-bearing (+5..+1409), asm position x7, h6 hoist 32x2, tag reshape, P_TAG ADDPRIM, array p6 stores, ~92k annealed variants. Untested: an unpinned alias of p6 for the tag load alone (ONE Opus second look allowed) | `.run/P32/t3/opus/func_800CF3E8.c` | +| 10 | func_80185810 | None | SCHED | 489 | near | 35 | [permuter] 4 emission windows (see report .run/P32/t3/reports/func_80185810__opus__*.md); exact length, rtu-clean | `.run/P32/t3/opus/func_80185810.c` | +| 11 | func_8017DC80 | None | FRAME | 346 | near | 46 | the historic -33 LENGTH wall CLOSED (GTE macros must be REAL macros — the TU house block; the splat Handwritten tag is wrong): 346/346, exact 0x70 frame + 9 callee-saved. Residual: reload-slot frame + the la $a0 slot; cse1 unifies OT index and n<4 across func_80010A08(8) (§500-D2 zero-byte asm retire) | `.run/P32/t3/opus/func_8017DC80.c` | +| 12 | func_800CF408 | None | SCHED | 178 | near | 49 | [permuter] 3 hunks: two prologue sched2 slots, an mlo/mhi allocno tie, a 3-insn block-2 head hoist. Two LENGTH-bearing pins found (tp $17 shared by 0xE1000087/97 = the 6th callee-saved; ob $10 fixes the $t1/$t2/$t3 rotation, 56->49). §351 family (func_8001212C -O0 / func_8017DD04 -O2 exemplars) | `.run/P32/t3/opus/func_800CF408.c` | +| 13 | func_800CF6D0 | None | SCHED | 249 | near | 137 | sched1 rank_for_schedule last-insn-CLASS tie (every store priority 2, equal refs; QImode stores grouped, loads floated, HImode after — 5 of 6 blocks) + $t1<->$t3 local-alloc swap of the two masks. 249/249 exact length only with tpage-before-len field order (19 swept). Inert at 137: pins on tpage constants/masks, asm re-ties, volatile/memory fences, /s-denial on any store subset, *0x4000 vs <<14, p++ vs p+0x18, / swap. decomp-permuter 122 was semantically wrong (R63) | `.run/P32/t3/opus/func_800CF6D0.c` | +| 14 | func_80062144 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | |