diff --git a/.run/P32/t3s3/bank_md_MAIN_009_185450.log b/.run/P32/t3s3/bank_md_MAIN_009_185450.log new file mode 100644 index 000000000..88f72f6d7 --- /dev/null +++ b/.run/P32/t3s3/bank_md_MAIN_009_185450.log @@ -0,0 +1,5 @@ + CC build/src/md_MAIN_009/md_MAIN_009.o + LD build/md_MAIN_009/md_MAIN_009.elf + OBJCOPY build/md_MAIN_009/md_MAIN_009 +[ OK ] build/md_MAIN_009/md_MAIN_009 + sha1 d270f695b793b5c03db159b7aabcc066daa87eda == config/check.md_MAIN_009.sha (BYTE-IDENTICAL) diff --git a/.run/P32/t5x/fable/func_800CD92C.c b/.run/P32/t5x/fable/func_800CD92C.c new file mode 100644 index 000000000..67d551ea7 --- /dev/null +++ b/.run/P32/t5x/fable/func_800CD92C.c @@ -0,0 +1,211 @@ +/* func_800CD92C — md_MAIN_009 (-O2). Builds six 0x18-byte SPRT-with-own-tpage prims + * (tag / 0xE1xxxxxx draw-mode word / rgb+code 0x64 / xy / uv+clut / wh) at the + * D_800A71D0 prim cursor and addPrim()s each onto OT word [0] of the frame's + * ordering table D_800ABA24[D_800BAE22 * 0x1000], then republishes the advanced + * cursor. Four 256-wide tiles at (x-0xA0 + 0x100*i, y-0x78) plus a fixed + * 2x(0xA0 x 0x100) backdrop. Same-TU sibling: func_800CD674 (4 prims). + * + * MATCH 247/247 with ZERO register pins (P32 T5x, Fable). The two prologue + * mechanisms, both read from the gcc-2.7.2 source and the -dS/-dl dumps: + * + * A. `m24` lands in $t1 by REF COUNT. local_alloc orders qtys by + * floor_log2(n_refs)*n_refs/life with n_refs = flow's count, taken BEFORE + * combine (toplev.c) and never adjusted by it (combine.c:56). The libgpu + * P_TAG bitfield store re-masks an already-masked getaddr() value + * (store_fixed_bit_field must_and), so the pre-combine RTL holds + * `(and (and ot m24) m24)`; combine folds it (associative rule + + * simplify_binary_operation op0==op1) to ONE `and`, but m24 keeps 19 refs + * (4*19=76) against la's 13 (3*13=39) and is allocated first -> $9. The + * `(... & m24) & m24` below IS that double mask; a `register ... $9` pin is + * the wrong tool (it also forbids $9 to every retried allocno, cf. 501-E). + * + * B. tp8D/tp8F float to the block top because the TAG LOAD is an in-place + * (multi-set) pseudo, exactly as the bitfield RMW expands (`t = *p; + * t &= FF00; t |= v; *p = t` on ONE pseudo). sched1 splits every large + * constant into lui+ori (sched.c:4826, mips.md large_int) and + * update_n_sets makes reg_n_sets 2, so the tpage constants are unboosted + * pri-1 floaters; a floater is consumed only by an EMPTY ready-list cycle, + * and each RMW chain has one (the lhu->sll latency gap). A single-set tag + * load is birthing-boosted and glued to its `and`; a multi-set one is not, + * and it fills those gaps instead -- so nothing eats tp8D/tp8F, they float + * like tp89/m24/tp8B, and local-alloc hands out $16..$19 in the target's + * order (tp8B < tp86 < tp8D < tp8F by life; tp87 shares $16 with tp8B). + * The mask temp `v` must stay a fresh expression: an in-place `v &= m24` + * is a 4-ref/2-insn qty that outranks `p` and steals $2 (the $v0/$v1 swap). + * Statement order matters once more: `v` (the OT read) BEFORE `t &= FF00`, + * so the FF00 constant's UID is above the index `sll` -- among two boosted + * insns sched1 picks the higher UID first, and with FF00 emitted early it + * takes prim 1's lhu->sll gap, the tag load then lingers into the store + * stream (memory-unit `blocking insn`), and its bubble hands tp8F's `ori` + * the wrong LUID (the last closeness-2 residual). + * + * Kept from the t3 draft (each byte-measured there): plain `*(T *)(p + off)` + * field stores (a non-QImode MEM_IN_STRUCT_P varying store is exempt from + * conflicting with the fixed non-struct `lhu D_800BAE22`, so struct fields let + * the sh stores sink -- sched.c true_dependence); the OT store as an ARRAY_REF + * lvalue with a block-scoped `oi` (lets the final publish hop above the last + * OT RMW); `x -= 0xA0` on the parameter; the chained r0=g0=b0 store. + * D_800BAE22 must stay the TU's plain scalar: any struct/array/cast spelling + * goes through change_address -> memory_address -> force_reg (one shared + * `la`), which is not the target's 12 lui/lhu macro loads. + */ + +extern u8 *D_800A71D0; +extern u32 D_800ABA24[]; +extern u16 D_800BAE22; + +void func_800CD92C(s32 x, s32 y, s32 c) { + u8 *p; + u32 m24; + + p = D_800A71D0; + x -= 0xA0; + y -= 0x78; + + *(u8 *)(p + 0x3) = 5; + *(u32 *)(p + 0x4) = 0xE1000089; + *(u8 *)(p + 0xB) = 0x64; + *(u16 *)(p + 0x12) = 0x7840; + *(u8 *)(p + 0x8) = *(u8 *)(p + 0x9) = *(u8 *)(p + 0xA) = c; + *(s16 *)(p + 0xC) = x; + *(s16 *)(p + 0xE) = y; + *(u8 *)(p + 0x10) = 0; + *(u8 *)(p + 0x11) = 0; + *(s16 *)(p + 0x14) = 0x100; + *(s16 *)(p + 0x16) = 0x100; + m24 = 0x00FFFFFF; + { + u32 v = (D_800ABA24[D_800BAE22 * 0x1000] & m24) & m24; + u32 t = *(u32 *)p; + t &= 0xFF000000; + t |= v; + *(u32 *)p = t; + } + { + s32 oi = D_800BAE22 * 0x1000; + D_800ABA24[oi] = (D_800ABA24[oi] & 0xFF000000) | ((u32)p & m24); + } + p += 0x18; + + *(u8 *)(p + 0x3) = 5; + *(u32 *)(p + 0x4) = 0xE100008B; + *(u8 *)(p + 0xB) = 0x64; + *(u16 *)(p + 0x12) = 0x7840; + *(u8 *)(p + 0x8) = *(u8 *)(p + 0x9) = *(u8 *)(p + 0xA) = c; + *(s16 *)(p + 0xC) = x + 0x100; + *(s16 *)(p + 0xE) = y; + *(u8 *)(p + 0x10) = 0; + *(u8 *)(p + 0x11) = 0; + *(s16 *)(p + 0x14) = 0x100; + *(s16 *)(p + 0x16) = 0x100; + { + u32 v = (D_800ABA24[D_800BAE22 * 0x1000] & m24) & m24; + u32 t = *(u32 *)p; + t &= 0xFF000000; + t |= v; + *(u32 *)p = t; + } + { + s32 oi = D_800BAE22 * 0x1000; + D_800ABA24[oi] = (D_800ABA24[oi] & 0xFF000000) | ((u32)p & m24); + } + p += 0x18; + + *(u8 *)(p + 0x3) = 5; + *(u32 *)(p + 0x4) = 0xE100008D; + *(u8 *)(p + 0xB) = 0x64; + *(u16 *)(p + 0x12) = 0x7840; + *(u8 *)(p + 0x8) = *(u8 *)(p + 0x9) = *(u8 *)(p + 0xA) = c; + *(s16 *)(p + 0xC) = x + 0x200; + *(s16 *)(p + 0xE) = y; + *(u8 *)(p + 0x10) = 0; + *(u8 *)(p + 0x11) = 0; + *(s16 *)(p + 0x14) = 0x100; + *(s16 *)(p + 0x16) = 0x100; + { + u32 v = (D_800ABA24[D_800BAE22 * 0x1000] & m24) & m24; + u32 t = *(u32 *)p; + t &= 0xFF000000; + t |= v; + *(u32 *)p = t; + } + { + s32 oi = D_800BAE22 * 0x1000; + D_800ABA24[oi] = (D_800ABA24[oi] & 0xFF000000) | ((u32)p & m24); + } + p += 0x18; + + *(u8 *)(p + 0x3) = 5; + *(u32 *)(p + 0x4) = 0xE100008F; + *(u8 *)(p + 0xB) = 0x64; + *(u16 *)(p + 0x12) = 0x7840; + *(u8 *)(p + 0x8) = *(u8 *)(p + 0x9) = *(u8 *)(p + 0xA) = c; + *(s16 *)(p + 0xC) = x + 0x300; + *(s16 *)(p + 0xE) = y; + *(u8 *)(p + 0x10) = 0; + *(u8 *)(p + 0x11) = 0; + *(s16 *)(p + 0x14) = 0x40; + *(s16 *)(p + 0x16) = 0x100; + { + u32 v = (D_800ABA24[D_800BAE22 * 0x1000] & m24) & m24; + u32 t = *(u32 *)p; + t &= 0xFF000000; + t |= v; + *(u32 *)p = t; + } + { + s32 oi = D_800BAE22 * 0x1000; + D_800ABA24[oi] = (D_800ABA24[oi] & 0xFF000000) | ((u32)p & m24); + } + p += 0x18; + + *(u8 *)(p + 0x3) = 5; + *(u32 *)(p + 0x4) = 0xE1000086; + *(u8 *)(p + 0xB) = 0x64; + *(u16 *)(p + 0x12) = 0x7880; + *(u8 *)(p + 0x8) = *(u8 *)(p + 0x9) = *(u8 *)(p + 0xA) = c; + *(s16 *)(p + 0xC) = -0xA0; + *(s16 *)(p + 0xE) = -0x78; + *(u8 *)(p + 0x10) = 0; + *(u8 *)(p + 0x11) = 0; + *(s16 *)(p + 0x14) = 0xA0; + *(s16 *)(p + 0x16) = 0x100; + { + u32 v = (D_800ABA24[D_800BAE22 * 0x1000] & m24) & m24; + u32 t = *(u32 *)p; + t &= 0xFF000000; + t |= v; + *(u32 *)p = t; + } + { + s32 oi = D_800BAE22 * 0x1000; + D_800ABA24[oi] = (D_800ABA24[oi] & 0xFF000000) | ((u32)p & m24); + } + p += 0x18; + + *(u8 *)(p + 0x3) = 5; + *(u32 *)(p + 0x4) = 0xE1000087; + *(u8 *)(p + 0xB) = 0x64; + *(u16 *)(p + 0x12) = 0x7880; + *(u8 *)(p + 0x8) = *(u8 *)(p + 0x9) = *(u8 *)(p + 0xA) = c; + *(s16 *)(p + 0xC) = 0; + *(s16 *)(p + 0xE) = -0x78; + *(u8 *)(p + 0x10) = 0x20; + *(u8 *)(p + 0x11) = 0; + *(s16 *)(p + 0x14) = 0xA0; + *(s16 *)(p + 0x16) = 0x100; + { + u32 v = (D_800ABA24[D_800BAE22 * 0x1000] & m24) & m24; + u32 t = *(u32 *)p; + t &= 0xFF000000; + t |= v; + *(u32 *)p = t; + } + { + s32 oi = D_800BAE22 * 0x1000; + D_800ABA24[oi] = (D_800ABA24[oi] & 0xFF000000) | ((u32)p & m24); + } + p += 0x18; + + D_800A71D0 = p; +} diff --git a/.run/P32/t5x/reports/func_800CD92C.md b/.run/P32/t5x/reports/func_800CD92C.md new file mode 100644 index 000000000..2ffe1b35b --- /dev/null +++ b/.run/P32/t5x/reports/func_800CD92C.md @@ -0,0 +1,80 @@ +# func_800CD92C (md_MAIN_009, 247 ins) — Fable arm (t5x) — **MATCH 247/247, real TU, zero pins** + +Deliverable: `.run/P32/t5x/fable/func_800CD92C.c` (N9b). `match_one` MATCH; `rtu_match --split md_MAIN_009 --source md_MAIN_009` +MATCH in the real TU; relocation audit (R1c) 2×D_800A71D0 (lw/sw), 2×D_800ABA24 (la + `lw D_800ABA24($3)`), 12×D_800BAE22 — +identical to the target's `%hi/%lo` counts. Externs spelled as the TU's file-scope lines 224-226 (`extern u8 *D_800A71D0;` +`extern u32 D_800ABA24[];` `extern u16 D_800BAE22;`); no typedefs, no `register`, no `__asm__` (the Opus draft's five §17 +pins are gone — the prior `extern u32 D_800A71D0` now CC1-FAILs in the TU because func_800CD674 was banked with `u8 *`). + +## What the residual actually was (read from the compiler + `-dS/-dl` dumps, not guessed) +The Opus draft's 15 was NOT "sched2 prologue weave steered by nothing". Two independent mechanisms, both decided in sched1 +and local-alloc, both fixed by spelling the addPrim the way libgpu's `P_TAG` bitfield macros expand: + +**1. m24's register is a REF-COUNT effect, not a pin.** `qty_compare` (local-alloc.c:1579) = floor_log2(n_refs)·n_refs·size / +(death−birth) with `qty_n_refs = reg_n_refs` (local-alloc.c:297) — FLOW's count, computed before combine (toplev.c:2983 vs +3004) and not adjusted by combine (combine.c:56). la (13 refs, life 342) beats an unpinned m24 (13 refs, life 420) → la=$9 +(E1 measured: 41 mismatched — Opus's "dropping the m24 pin → 41"). The libgpu `setaddr(p, getaddr(ot))` bitfield store +re-masks its already-masked value (`store_fixed_bit_field` must_and, expmed.c:608-620): pre-combine RTL `(and (and ot m24) +m24)`, folded by combine's associative rule (combine.c:3140-3170 → `simplify_binary_operation` AND op0==op1, cse.c:3930) to +ONE `and` — but m24 keeps 19 refs → 4·19=76 > la's 39 → m24 first → $9, la $10, FF00 $11. Spelled `(ot & m24) & m24` with +`u32 m24 = 0xFFFFFF` (E3: identical bytes to the pinned draft, closeness 15, m24 "used 19 times" in `-dl`). + +**2. tp8D/tp8F float because the TAG LOAD is a multi-set pseudo.** sched1 `try_split`s every insn before scheduling +(sched.c:4826; mips.md:3210 `large_int` → lui+ori) and `update_flow_info` → `update_n_sets` bumps `reg_n_sets` to 2 +(sched.c:4617/4234), so every 0xE10000xx constant is an unboosted pri-1 floater (pinned or not — E2 no-pins had the identical +stall picks). Backward list scheduling consumes a floater only in an EMPTY ready-list cycle; each RMW chain has exactly one +(the `lhu→sll` latency gap, cost 2 queue): base trace stalls T-44/54, 81/91, 116/126, 150/160 = prim (k−1)'s two gaps eat +prim k's constant (tp87→r5, tp86→r4, tp8F→r3, tp8D→r2; tp8B/m24/tp89 reach the top). In the target's sched2 top block +(= ascending LUID of the pri-1 pool, memory ops hazard-first) tp8D/tp8F sit BELOW li5, i.e. they floated. The bitfield +RMW expands `t = *p; t &= FF00; t |= v; *p = t` on ONE pseudo (expand_binop target reuse): `reg_n_sets`=3 → no birthing +boost (sched.c:2490) → the tag load is not glued to its `and` and fills the `lhu→sll` gap instead (N1 trace T-52, +N7 stall list shrinks to one) → tp8D/tp8F float, and local-alloc's life order gives tp8B $16, tp86 $17, tp8D $18, tp8F $19, +tp87 sharing $16 (N6/N7 dumps). Spelled `{ u32 v = (ot & m24) & m24; u32 t = *(u32 *)p; t &= 0xFF000000; t |= v; +*(u32 *)p = t; }`. + +**Two sub-lessons inside #2 (each cost one probe):** +* `v` must be a FRESH expression: `v &= m24` in place makes a 4-ref/2-insn qty (pri 2.0 > p's 1.6) that is allocated + before `p` and takes $2 → the 178-diff $v0/$v1 swap (N4/N6). +* `v` (the OT read) must precede `t &= FF00`: the FF00 constant is force_reg'd where the `and` is expanded; if its UID is + below the index `sll`'s, sched1's boosted tie (LUID rule) picks the `sll` first and FF00 drops into prim 1's `lhu→sll` + gap; the unboosted tag load then lingers into the store stream, is memory-unit `blocking insn 81` each cycle, and its + bubble (T-207) takes the highest-LUID floater = tp8F's `ori` → the closeness-2 `li $t7`/`ori $s3` swap (N7 vs N1 traces). + +## Why the natural libgpu form itself is NOT the draft (measured, for the record) +N1 (struct fields + `P_TAG` bitfield addPrim + `/s` index) reproduces the whole prologue/body SHAPE (239 ins, only −8), +but any struct/array/cast spelling of D_800BAE22 goes through `change_address → memory_address → force_reg` (constant +address, pre-cse) = one shared `la $11,D_800BAE22` + 12 `lhu 0($11)`, which steals $11 and shifts every later register. +The target's 12 `lui/lhu D_800BAE22` gas-macro loads mean the original read it as the plain scalar the TU declares. A `/s` +tag store with a plain scalar index would CSE the second `lhu` (§364: cse.c `note_mem_written` sets `all=0` for a +MEM_IN_STRUCT_P or PLUS-address non-QI store, `invalidate_memory` then spares non-struct fixed entries), so the tag store +stays the non-`/s` `*(u32 *)p` while the mask/pseudo SHAPE of the bitfield expansion is kept by hand. The OT side keeps the +t3 levers (ARRAY_REF lvalue, block-scoped `oi`) — N6 showed the OT spelling is irrelevant to the prologue. + +## Levers measured (all in `.run/P32/t5x/work/func_800CD92C/`, dumps in `dumps_/`) +| variant | change | result | +|---|---|---| +| base (Opus t3) | 5 pins | 15 | +| v_unpin8D8F | tp8D/tp8F inline, other pins kept | 245 ins (alloc shift) | +| e1_m24unpin | m24 plain local | 41 (la takes $9) | +| e2_nopins | everything plain | 241 ins, frame 16 | +| e3_dblmask | m24 plain + `(ot&m24)&m24` | **15, byte-identical to base** (m24 $9 by 19 refs) | +| n1_libgpu | struct fields + P_TAG bitfields + `/s` index | 239 ins (−8 = the `la` index), prologue SHAPE = target | +| n2A/B/C/D, n3 | other `/s` index spellings (array, cast, asm-label alias) | `la` in all but A; A is non-`/s` and CSEs to 6 loads (222) | +| n4_inplace | E3 + in-place `t`/`v`/`o` temps, no pins | 247, 178 ($v0/$v1 swap) | +| n5_otonly / n6_tagonly | bisect | OT side inert (241); tag side = 178 | +| n7_tagT | in-place `t`, fresh `(ot&m24)&m24`, FF00 first | **2** (`li 5`/`ori $s3` swap) | +| n8_u8ptr | n7 + TU's `extern u8 *D_800A71D0` | 2, rtu compiles | +| n9a / n9b | FF00 after the OT read | **MATCH** (both instruments) | + +## Cookbook-worthy generalizations (for the coordinator's harvest) +* **REF-COUNT ALLOCATION LEVER:** a mask/constant's local-alloc priority counts flow-time refs; a source that produces a + combine-foldable redundant use (`(x & m) & m`, the bitfield must_and) raises the pseudo's priority at zero bytes. This is + how libgpu's bitfield addPrim puts the 24-bit mask in `$t1` ahead of the OT base in every SPRT/POLY function — check + `-dl` "used N times" before pinning a mask register (§17 pins are a symptom-fix here; §501-E shows their side effects). +* **UNBOOSTED TAG LOAD = STALL FILLER:** an in-place RMW temp (multi-set) frees the `lhu→sll` gaps that otherwise eat + the split large-constant floaters; the "prologue weave" of hoisted `lui/ori` pairs is decided by which pseudos are + single-set in the RMW chains, not by any prologue-side lever (extends map §S7/§S2). +* **Struct-member GLOBAL access = one `la`:** `change_address → memory_address` force_regs a constant address pre-cse; a + target with N `lui/lhu SYMBOL` macro loads read a plain scalar — do not spell it as a struct field. +* **Statement order inside an RMW block sets the UID tie among boosted insns** (FF00 vs the index `sll`): materialize a + mask constant AFTER the address expression it competes with. diff --git a/.run/P32/t5x/resume_queue.txt b/.run/P32/t5x/resume_queue.txt index 8b7eb5e37..be5a5eaa1 100644 --- a/.run/P32/t5x/resume_queue.txt +++ b/.run/P32/t5x/resume_queue.txt @@ -1,7 +1,6 @@ # T4b Fable resume queue (Drew 2026-09-05: "resume agents, but not all at once, just 3 at a time"). Delete a line when resumed. # fn agentId closeness -func_8017DC80 a7c2c1e4865e5590d 46 func_800CF408 aac6ce9fdfdcc093c 49 func_800CF6D0 a7f7e477e9878acdd 137 func_80011380 a60ffea4022b891fc 6 (-O0, §474 PROVED — last) -# RUNNING: func_800CD92C a5587b9d5c7006214 · func_80039308 a55fbfb4fb896bd71 · func_80185810 a547e70e9a7735c8a (DONE MATCH: 391D4 39DEC CD674 DF28 20DA4 1834A4 CF3E8; NEAR: 32A74 1) +# RUNNING: func_80039308 a55fbfb4fb896bd71 · func_80185810 a547e70e9a7735c8a · func_8017DC80 a7c2c1e4865e5590d (DONE MATCH: 391D4 39DEC CD674 DF28 20DA4 1834A4 CF3E8 CD92C; NEAR: 32A74 1) diff --git a/.run/P32/t5x/verdicts.jsonl b/.run/P32/t5x/verdicts.jsonl index 9bf71ec13..b881fe71c 100644 --- a/.run/P32/t5x/verdicts.jsonl +++ b/.run/P32/t5x/verdicts.jsonl @@ -6,3 +6,4 @@ {"fn": "func_801834A4", "binary": "ov_SC03_105", "arm": "fable", "status": "MATCH", "closeness": 0, "compiles": true, "draft_path": ".run/P32/t5x/fable/func_801834A4.c", "note": "CSE-quantity split, not loop.c: expand_divmod (expmed.c:3034-3057) emits const/mult/sra/subu adjacently from ONE op0 so loop.c treats mult and sra alike (force_movables loop.c:1226 doubles K's savings -> hoists all, or a hard-reg dividend kills all). cse.c canon_reg never rewrites a hard reg but hashes by reg_qty: `sign = half >> 31` at the loop TOP (movable, maybe_never==0) + `hh = half` (register $2) + `pos[0] -= hh / 3` makes the mult read $2 (not movable; K unlinked, inline) while the division's sra is CSE'd into sign (hoisted); combine folds the copy into the mult. Traps: a callee-saved pin enters regs_ever_live before combine -> global pass 0 gives it to j (7); an asm feed for the unread sign store adds +2 weighted refs and swaps half/sign in allocno_compare (4) -> a dead `sign = 0` initializer instead (flow deletes it). Coordinator rtu MATCH 106/106; bank.sh byte-identical", "session": "491895ad"} {"fn": "func_80032A74", "binary": "main", "arm": "fable", "status": "NEAR", "closeness": 1, "compiles": true, "draft_path": ".run/P32/t5x/fable/func_80032A74.c", "note": "rtu DIFF 1 in src/800_b_2.c (idx 244 lh vs lhu; frame 0x78 exact); the lhu respelling is code-exact 422/422 with vars=56. Residual mechanism READ + byte-reproduced: the never-referenced 8-byte slot at 0x48 is a GHOST pseudo — a stranded middle temp of a 3-insn combine whose refs-zeroing is skipped when newi2pat!=0 (combine.c:2306-2313); zero occurrences -> regclass 'ST_REGS or none' -> reload1.c:658 alter_reg(i,-1) 8-byte slot in regno order = right after the three param slots (ghost1 reproducer vars=8, no code). The caller-save-area hypothesis (S83 HYPOTHESIS.md) is REFUTED: order_regs_for_reload (reload1.c:3606-3700) picks zero-use regs first so a pseudo homed in $t0 makes $t1 the spill reg (+30 rows); an area needs caller_save_needed (global.c:1085-1091) and a pseudo kept in a call-used reg with save/restore at every live call (caller-save.c:264, 349-470). The only ghost species from a memory value is the SIGN_EXTEND narrow-load split (combine.c:1887-1930) whose signature IS lh; a jump-target second promotion is folded by cse follow-jumps (n0a/b/c: vars 56, +86 rows); a fall-through one needs a register sign_extend MIPS lacks; the generic two-SETs split (combine.c:1963-2020) has no candidate (cse pre-folds constant offsets). Inert: expA/expB, n16 (2 ghosts), n0a/n0b/n0c. 402k tokens, 23 min", "session": "491895ad"} {"fn": "func_800CF3E8", "binary": "md_MAIN_003", "arm": "fable", "status": "MATCH", "closeness": 0, "compiles": true, "draft_path": ".run/P32/t5x/fable/func_800CF3E8.c", "note": "27 -> MATCH 469/469; three passes each owned one defect: (1) sched1 birthing boost on the tag load (sched.c:2507/2469) killed with a SECOND LIVE SET of the loaded variable `tag6 = *(u32*)p6; ... tag6 &= 0xFF000000;` (reg_n_sets=2, zero bytes); (2) the S83 +1 nop was the phantom `__asm__(\"\" :: \"r\"(ot))` USE filling the load-delay slot in sched2's model only — removed, plus the fence after the tpage store removed so `lui m24` reaches slot 378 via its $a2 anti-dep; (3) local-alloc qty_compare had mhi out-ranking m24 for $a2 — spelling prims 5..1's OT link as libgpu's P_TAG bitfield adds store_fixed_bit_field's redundant 0xFFFFFF re-mask (folded by combine, counted by flow: m24 13 -> 18 refs) so m24 wins $a2, mhi -> $t0, tag -> $t2; last 2 rows = p5 x0/y0 in natural source order. Ablations: non-compound tag 89; phantom re-added 70@470; fence re-added 8; manual masks on all six prims 74. Coordinator rtu MATCH 469/469; bank.sh byte-identical", "session": "491895ad"} +{"fn": "func_800CD92C", "binary": "md_MAIN_009", "arm": "fable", "status": "MATCH", "closeness": 0, "compiles": true, "draft_path": ".run/P32/t5x/fable/func_800CD92C.c", "note": "MATCH 247/247, ZERO register pins. (1) m24 takes $t1 by REF COUNT: local-alloc qty_compare uses flow's reg_n_refs (pre-combine, combine.c:56); the libgpu P_TAG bitfield store's must_and re-mask (expmed.c:608) leaves a combine-foldable (and (and ot m24) m24) (combine.c:3140-3170) so m24 keeps 19 refs vs la's 13 -> spelled (ot & m24) & m24, unpinned. (2) tp8D/tp8F float to the top when the TAG LOAD is an in-place multi-set pseudo (bitfield RMW shape t=*p; t&=FF00; t|=v; *p=t): sched1 splits large consts (sched.c:4826) and update_n_sets kills their birthing boost, so they are pri-1 floaters eaten only by the lhu->sll latency stall of each RMW chain; a single-set tag load is boosted and glued to its and, a multi-set one fills those stalls -> local-alloc gives $16..$19 in the target order. Sub-levers: the mask temp v must be a FRESH expression (in-place v&=m24 steals $2); v (OT read) precedes t&=FF00; plain scalar D_800BAE22 (struct/array/cast spellings force one shared la); tag store non-/s *(u32*)p; TU spelling extern u8 *D_800A71D0. Coordinator rtu MATCH 247/247; bank.sh d270f695. 509k tokens, 39 min", "session": "491895ad"} diff --git a/docs/backlog.md b/docs/backlog.md index 0d835f1de..91a089435 100644 --- a/docs/backlog.md +++ b/docs/backlog.md @@ -2,16 +2,15 @@ > 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:** 9 · by status {'near': 8, 'failed': 1} · by class {'WALL-CANDIDATE': 1, 'WALL-PROVED': 1, 'SCHED': 4, 'REGALLOC': 1, 'FRAME': 1, None: 1} +**Open near-misses:** 8 · by status {'near': 7, 'failed': 1} · by class {'WALL-CANDIDATE': 1, 'WALL-PROVED': 1, 'REGALLOC': 1, 'SCHED': 3, '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_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` | -| 3 | 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` | -| 4 | 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` | -| 5 | 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` | -| 6 | 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` | -| 7 | 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` | -| 8 | 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` | -| 9 | func_80062144 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | | +| 3 | 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` | +| 4 | 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` | +| 5 | 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` | +| 6 | 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` | +| 7 | 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` | +| 8 | func_80062144 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | |