From e69218dc51b037b61d349325e6fca3d4e872325f Mon Sep 17 00:00:00 2001 From: Drew T <50529377+Druthulu@users.noreply.github.com> Date: Fri, 11 Sep 2026 05:50:24 -0600 Subject: [PATCH] =?UTF-8?q?phase-36:=20cookbook=20=C2=A7456=20=E2=80=94=20?= =?UTF-8?q?the=20S104=20lever-removal=20move=20catalog=20(R16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/cookbook-index.md | 15 ++++++++---- docs/matching-cookbook.md | 49 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/docs/cookbook-index.md b/docs/cookbook-index.md index 6d91ae6cea..f59ca4a6b8 100644 --- a/docs/cookbook-index.md +++ b/docs/cookbook-index.md @@ -2,7 +2,7 @@ > **Generated by `tools/cookbook_index.py` — do not hand-edit** (R33). Regenerate after adding a cookbook section. > -> `docs/matching-cookbook.md` is ~716 KB / 1172 sections. Grepping it blind is how three P30 wave-1 agents each "discovered" an idiom that was already written down. **Start here, then read the section.** A section appears under every symptom it addresses. +> `docs/matching-cookbook.md` is ~716 KB / 1174 sections. Grepping it blind is how three P30 wave-1 agents each "discovered" an idiom that was already written down. **Start here, then read the section.** A section appears under every symptom it addresses. **How to use:** name what you SEE in the diff (a stolen delay slot, an extra `la`, a swapped register pair, a `conflicting types` error), find that symptom below, read those sections first. If nothing fits, THEN grind — and add a section when you win. @@ -103,7 +103,7 @@ - **§396g** — ★★ — A GUARD LADDER'S RUNGS MUST STAY SYMMETRIC OR `reorg.c` LOSES ITS BRANCH REDIRECT (P31 S69; byte-proven ov_SC03_028/func_80184C90, 92 ins) L32822 - **§428** — ★★★ — A ZERO-BYTE CROSS-JUMP BARRIER: ADVANCE THE POINTER INSIDE EACH SWITCH ARM (P31 S72; `main/func_80026D64`, 218 ins, MATCH in 2 compiles) L33958 -### instruction scheduling (99) +### instruction scheduling (100) - **§3-T2** — Source statement order drives instruction scheduling L78 - **§3** — When a diff is pure scheduling → decomp-permuter (harness built, Phase 6) L107 @@ -204,8 +204,9 @@ - **§475** — THE `"memory"` FENCE AS A *CSE INVALIDATOR*, AND `(b*3)<<3` INSTEAD OF `b*24` L35585 - **§476** — 🔴 A HARD-REGISTER PIN DESTROYS TWO THINGS COMBINE AND SCHED1 NEED (`func_800226C0`, 670 ins → MATCH) L35616 - **§482** — ★★★ — TWO INDEPENDENT RE-TIES, ORDERED: WHEN ONE BARRIER FIXES ONE RESIDUAL AND CREATES THE OTHER (P31 S77, `main:func_8006252C`, 30 ins → MATCH) L35936 +- **§456** — The lever-removal move catalog: what the S104 agents found under ~205 pins, barriers and launders (Phase 36 T7) L37759 -### register allocation & pins (139) +### register allocation & pins (140) - **§10** — Closing the regalloc/scheduling hard tail by hand (LZSS, Phase 7 session F — the full close) L854 - **Residual** — A — commutative `|`/`&`/`+` result lands in the wrong source-operand register L875 @@ -346,6 +347,7 @@ - **§478** — 🔴 — A VERBATIM DRAFT IS THE STRONGEST *FALSE* SIGNAL YOUR SCOPING TOOL CAN EMIT L35791 - **§499** — ★★★ — A NEVER-ONBOARDED PAYLOAD PINS ITS OWN BASE STATICALLY, AND THE FIRST BUILD CANNOT (P32 T2a/T2b: the parked five onboarded, 213 → 218 binaries, 0 UNCLAIMED) L36752 - **§501** — ★★★ — A LEVER THAT MEASURES WORSE MAY BE A CASCADE: READ THE `.loop` DUMP FOR THE DESIRABILITY FLIP BEFORE DISCARDING IT (P32 T4b, `main:func_800391D4`, a pinned wall banked by a Fable agent) L37151 +- **§456** — The lever-removal move catalog: what the S104 agents found under ~205 pins, barriers and launders (Phase 36 T7) L37759 ### CSE / redundancy / rematerialization (50) @@ -1095,7 +1097,7 @@ - **§496** — ★★ — A CARRIED-TYPE TEST THAT ASSUMES THE OVERLAY INCLUDE SET SILENTLY DROPS A RESIDENT TYPEDEF (P32 T1a; byte-proven, resident `func_800D128C` isolation) L36665 - **§453** — ★★★ — ONE SOURCE PER UNIQUE FUNCTION: THE INCLUDE-AT-SITE SHARE, ITS GATE, AND THE FOUR DEFECTS THAT SHAPED IT (P35 S94–S96) L37555 -### build graph, splat & the harness (218) +### build graph, splat & the harness (219) - **§4** — Flag/toolchain gotchas L190 - **Build** — mechanism — per-file opt override (splat resegmentation) L307 @@ -1315,6 +1317,7 @@ - **§499** — ★★★ — A NEVER-ONBOARDED PAYLOAD PINS ITS OWN BASE STATICALLY, AND THE FIRST BUILD CANNOT (P32 T2a/T2b: the parked five onboarded, 213 → 218 binaries, 0 UNCLAIMED) L36752 - **§500** — ★★★ — THE T3 WAVE HARVEST (P32 T3, 2026-09-05): 31 one-agent-per-function drafters → 20 MATCH / 9 NEAR / 2 FAIL, every closer, two NEW named gcc mechanisms, and the wave-process defects L36793 - **§453** — ★★★ — ONE SOURCE PER UNIQUE FUNCTION: THE INCLUDE-AT-SITE SHARE, ITS GATE, AND THE FOUR DEFECTS THAT SHAPED IT (P35 S94–S96) L37555 +- **§455** — Rung G, the guided search: score the object, classify the residual, compose the moves (Phase 36 S101) L37686 ### process, measurement & doctrine (143) @@ -2978,6 +2981,8 @@ - **§453** — ★★★ — ONE SOURCE PER UNIQUE FUNCTION: THE INCLUDE-AT-SITE SHARE, ITS GATE, AND THE FOUR DEFECTS THAT SHAPED IT (P35 S94–S96) L37555 - **§454** — Rung D and rung R: taking a lever off a body that still has to compile to the same bytes (Phase 36 T6) L37604 - **§454a** — the recipe rung's real shape: replication, not discovery (S99, measured) L37671 +- **§455** — Rung G, the guided search: score the object, classify the residual, compose the moves (Phase 36 S101) L37686 +- **§456** — The lever-removal move catalog: what the S104 agents found under ~205 pins, barriers and launders (Phase 36 T7) L37759 --- @@ -4162,3 +4167,5 @@ Notes routinely quote that as a section id. This table resolves it. Grep bait: ` | L37555 | §453 | ★★★ — ONE SOURCE PER UNIQUE FUNCTION: THE INCLUDE-AT-SITE SHARE, ITS GATE, AND THE FOUR DE | | L37604 | §454 | Rung D and rung R: taking a lever off a body that still has to compile to the same bytes ( | | L37671 | §454a | the recipe rung's real shape: replication, not discovery (S99, measured) | +| L37686 | §455 | Rung G, the guided search: score the object, classify the residual, compose the moves (Pha | +| L37759 | §456 | The lever-removal move catalog: what the S104 agents found under ~205 pins, barriers and l | diff --git a/docs/matching-cookbook.md b/docs/matching-cookbook.md index 0811a77a2e..0b359459a4 100644 --- a/docs/matching-cookbook.md +++ b/docs/matching-cookbook.md @@ -37755,3 +37755,52 @@ register is busy in the original and free in mine, which is a liveness the sourc draws it nor strips those sites from its seed; it had been searching for a reload that the cast it removed produces. And the head is where the number is: after four runs the next 64 classes by copies carry 498 bodies, while the ~65 head classes that did not close hold ~8,000 — each is worth a reading (`--explain --path` on its best moves) and a generator, not a wider tail pass. + +## §456 — The lever-removal move catalog: what the S104 agents found under ~205 pins, barriers and launders (Phase 36 T7) + +Every entry below was byte-proven on at least one banked body in S104 (the agent, the pass and the `file:line` are in that +pack's `mechanism.md` under `.run/P36/agents/__/`; METHOD_S103.md steps 12–16 carry the same list with the ids). +The pattern across the session: a decompiler-shaped body forces a lever because of ONE spelling decision; the original's +natural C removes it. Try these in order on a residual before any register lever. + +**Register residuals (local-alloc / global.c).** +- One value per temp: a local that dies in several places is refused by local-alloc (`local-alloc.c:472`) and goes global — + substitute in place, split, or declare per block / per switch case (generators R23, R29). The INVERSE also closes: two locals + the tree pins to one register are one variable (R28), a late local reusing an earlier-dead one lands in its register (R34). +- Call-result temps of one type across cases → one function-scope variable (many refs, short live length outrank the self pointer). +- A block with exactly THREE quantities is allocated in BIRTH order, not sorted (`local-alloc.c:1486-1507`; `tools/localalloc_sim.py` + models it): add or remove a quantity (a compound assignment, an inlined re-read) to flip it (R32). +- An integer-truncated `allocno_compare` TIE (`global.c:594-607`, ties by allocno number; `tools/alloc_table.py` flags `TIE`): + duplicate the statement after an if/else join into both arms — one insn of live length splits it and cross-jump re-merges (R39). +- A parameter copy `T x = argN;` deleted (R35) or moved to a later plain statement; `return ++i;` for a counter's refs (R40); + a call passed at its REAL arity (the extra arg costs 0 bytes — jump2 deletes the no-op copy, `jump.c:425-462`) (R19). +- Widths: an `s16`/`u16`/`u8` local for a value used narrow keeps a SUBREG copy cse cannot fold (`cse.c:7440-7474`); a cast at + ONE shift, `(s16)t >> N` (R31); joint widths on several locals at once. +- A walked pointer stepped alongside another → indexed by the counter (`record_giv` `loop.c:4341`, `combine_givs` `:5494`); + a load split from its update `T = LOAD; … P = T + X;`; a twice-set pointer `p = &D; p += x;` as one expression (R36 — the + frame-only residual: combine leaves the ref count, reload gives a slot, `combine.c:2305-2337`, `reload1.c:2327-2352`). +- A named derived pointer `q = p - k` that cse keeps as a REGISTER address (`find_best_addr`, `cse.c:2656-2721`) — the `la` lever. + +**Order / count residuals (cse, sched, jump, reorg).** +- A goto chain → structured C (if/else, `||`, `switch`, `for` with `break`/`continue`, a shared tail written out per site): a + label between a store and its tail blocks jump1's if-conversion (`jump.c:805`/`:1019`), cross-jump re-merges duplicated tails + (`jump.c:2371`) at zero bytes, a rotated loop's `NOTE_INSN_LOOP_VTOP` flips reorg's `mostly_true_jump` (`reorg.c:1364-1372`). + The reverse exists too: a do-while as a backward goto loop when the target shows NO loop optimisation (`loop.c:352-361`). +- `x = a; if (c) x = f(a);` → if/else with the non-simple value in the ELSE arm (jump1 re-merges a reg/const else, `jump.c:739-741`) (R33). +- A result local `r = 0; if (A) r = (B); return r;` → `if (A && B) return 1; return 0;` (jump1's store-flag on the hard `$v0`) (R37). +- A store in EACH arm when the target reloads a global after it (cse forwards only within a block, `cse.c:7358-7369`, `:8039`) + or when sched1 treats two symbols as non-aliasing; each arm's store BEFORE its counter; the if/else arms swapped for reorg's + delay-slot steal (R41); a statement moved several positions down its block (R42). +- A sign test whose arms set/clear bit 31 → `& 0x80000000` (the mask's `lui` fills the slot, `reorg.c:2799`; the dead AND's slot + is what a pad faked) (R43). A hand-expanded `if (v < 0) v += 2^k-1; v >>= k;` is `v / 2^k` (R38); `(b << k) - b` is `b * (2^k-1)`. +- Set counts steer three passes: a second identical assignment demotes sched1's birthing boost (`sched.c:2469-2545`), keeps a + constant off REG_EQUIV's doubled live length (`local-alloc.c:1016-1064`), and keeps loop.c from hoisting (`loop.c:705`). +- Struct/array spelling decides sched's alias test (`expr.c:4568-4577` → `sched.c:817-861`): a cast byte-offset store is + scalar, an indexed/field access is aggregate — pick per access group; GTE scratch words gathered into one local struct; a + 16-byte copy loop as ONE struct assignment (`expand_block_move`, `mips.c:2330ff`). +- Sony's GTE macros replace hand-flattened GTE asm blocks; parameters straight into the macros (reload's spill register). + +**Signals that a close is NOT plain C (park it, structs phase):** a `(void)` function whose first act reads a pinned `$a0`–`$a3` +takes a parameter; a `void` function whose final keepalive reads `v0` returns it; a narrow parameter the bytes use as s32 is +s32; a store through another symbol of the same address is identical only after LINKING. Refused as closes: an invented +always-false condition, a dead store kept only to steer a pass, a pointer alias invented only to dodge cse.