diff --git a/docs/cookbook-index.md b/docs/cookbook-index.md index 8aee72c9c..84faf32e9 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 / 1096 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 / 1097 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. @@ -34,7 +34,7 @@ ## By symptom -### delay slots & branches (66) +### delay slots & branches (67) - **§3-T4** — Branch polarity: invert the source condition to flip gcc's chosen branch L90 - **§5a** — Cross-jump tail-merge — gcc collapses two byte-identical blocks the original kept separate (FIX FOUND) L211 @@ -102,8 +102,9 @@ - **§370** — ★★ — A **HARD BOUND** FROM sched.c, AND THE reorg SLOT-STEAL DIAGNOSTIC (P31 S68; main/func_8001BC6C, 69 ins, NOT closed — 33 → 28 over ~45 measured compiles) L31838 - **§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) L32818 - **§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) L33950 +- **§428a** — ★★ — THE FENCE↔OVER-MERGE COUPLING: WHY A CROSS-JUMP BARRIER CAN COST YOU A REGALLOC WIN (P31 S72, `main/func_8001B0D4`; AGENT-MEASURED, not yet byte-proven) L33988 -### instruction scheduling (88) +### instruction scheduling (89) - **§3-T2** — Source statement order drives instruction scheduling L78 - **§3** — When a diff is pure scheduling → decomp-permuter (harness built, Phase 6) L107 @@ -193,8 +194,9 @@ - **§3-B.** — THE SCHEDULER DIALS (the dominant residual family this wave) L33108 - **§424** — ★★★ — EQUAL-PRIORITY STORES COME OUT **REVERSED**: sched1's LUID tie picks the LAST statement first (P31 S71; byte-proven `ov_SC07_006/func_801890FC`, 387 ins) L33807 - **§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) L33950 +- **§428a** — ★★ — THE FENCE↔OVER-MERGE COUPLING: WHY A CROSS-JUMP BARRIER CAN COST YOU A REGALLOC WIN (P31 S72, `main/func_8001B0D4`; AGENT-MEASURED, not yet byte-proven) L33988 -### register allocation & pins (131) +### register allocation & pins (132) - **§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 @@ -327,6 +329,7 @@ - **§410** — ★★★ — COPY THEN ACCUMULATE ON THE COPY: resolving the birthing-boost vs register-allocation dilemma (P31 S71; byte-proven `ov_SC04_015/func_8017EB78`, 98 ins) L33353 - **§417** — ★★★ — A REGISTER PIN CAN BLOCK `jump.c`'s SELECT COLLAPSE, AND UNPINNING THEN EXPOSES A `cse` SKIP-BLOCKS MERGE (P31 S71; byte-proven `ov_SC03_013/func_8017E6F4`, 182 ins) L33605 - **§419** — ★★★ — WHEN A PIN IS IMPOSSIBLE, WIN THE local-alloc DENSITY CONTEST INSTEAD (P31 S71; byte-proven `ov_SC01_000/func_8017DD04`, 297 ins) L33658 +- **§428a** — ★★ — THE FENCE↔OVER-MERGE COUPLING: WHY A CROSS-JUMP BARRIER CAN COST YOU A REGALLOC WIN (P31 S72, `main/func_8001B0D4`; AGENT-MEASURED, not yet byte-proven) L33988 ### CSE / redundancy / rematerialization (45) @@ -1223,7 +1226,7 @@ - **§426** — ★★★ — main's SWITCH FUNCTIONS WERE NEVER A CODEGEN WALL: ONE RODATA CARVE HAD BEEN MISSING SINCE PHASE 7 (P31 S72; 3 of the 11 "PROVEN gate-rejects" banked byte-identical in 14 s) L33855 - **§427** — ★★ — A HASH IS A CORRECTNESS ORACLE WITH ZERO DIAGNOSTIC CONTENT; PRESERVE THE RED ARTIFACT BEFORE ANYTHING REBUILDS OVER IT (P31 S72) L33931 -### process, measurement & doctrine (132) +### process, measurement & doctrine (133) - **§8e** — The jtbl ALIGNMENT LAW + the pad-spec filter — multi-table .rodata spans (Phase 29, byte-proven; `.run/probe_jtbl/verdict.md`) L549 - **§3-The** — mechanism: game-code dedup is SOURCE-LEVEL, not an object swap (R-D1, the key lesson) L945 @@ -1357,6 +1360,7 @@ - **§3-E.** — WHAT THE AGENTS REFUTED L33148 - **§408** — ★★★ — §406 REFUTED AS A SWEEP: THE SHAPE IS THE FAMILY, THE DISAGREEMENT IS THE DEFECT (P31 S71; 0 MATCH / 14 applied, 0 / 210) L33209 - **§411** — ★★★ — THE PACK MUST CARRY THAT FUNCTION'S OWN HISTORY (P31 S71; measured 38/39 vs 124/131) L33386 +- **§428a** — ★★ — THE FENCE↔OVER-MERGE COUPLING: WHY A CROSS-JUMP BARRIER CAN COST YOU A REGALLOC WIN (P31 S72, `main/func_8001B0D4`; AGENT-MEASURED, not yet byte-proven) L33988 ### (unbucketed — title matched no symptom vocabulary) (325) @@ -2785,6 +2789,7 @@ - **§426** — ★★★ — main's SWITCH FUNCTIONS WERE NEVER A CODEGEN WALL: ONE RODATA CARVE HAD BEEN MISSING SINCE PHASE 7 (P31 S72; 3 of the 11 "PROVEN gate-rejects" banked byte-identical in 14 s) L33855 - **§427** — ★★ — A HASH IS A CORRECTNESS ORACLE WITH ZERO DIAGNOSTIC CONTENT; PRESERVE THE RED ARTIFACT BEFORE ANYTHING REBUILDS OVER IT (P31 S72) L33931 - **§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) L33950 +- **§428a** — ★★ — THE FENCE↔OVER-MERGE COUPLING: WHY A CROSS-JUMP BARRIER CAN COST YOU A REGALLOC WIN (P31 S72, `main/func_8001B0D4`; AGENT-MEASURED, not yet byte-proven) L33988 --- @@ -3893,3 +3898,4 @@ Notes routinely quote that as a section id. This table resolves it. Grep bait: ` | L33855 | §426 | ★★★ — main's SWITCH FUNCTIONS WERE NEVER A CODEGEN WALL: ONE RODATA CARVE HAD BEEN MISSING | | L33931 | §427 | ★★ — A HASH IS A CORRECTNESS ORACLE WITH ZERO DIAGNOSTIC CONTENT; PRESERVE THE RED ARTIFAC | | L33950 | §428 | ★★★ — A ZERO-BYTE CROSS-JUMP BARRIER: ADVANCE THE POINTER INSIDE EACH SWITCH ARM (P31 S72; | +| L33988 | §428a | ★★ — THE FENCE↔OVER-MERGE COUPLING: WHY A CROSS-JUMP BARRIER CAN COST YOU A REGALLOC WIN ( | diff --git a/docs/matching-cookbook.md b/docs/matching-cookbook.md index 36f56b6d2..24cff3c12 100644 --- a/docs/matching-cookbook.md +++ b/docs/matching-cookbook.md @@ -33984,3 +33984,33 @@ optimizer cannot look up. byte-identical against `jtbl_80072BFC`, plus 6 `jal` relocs at their exact offsets and 11 `D_800A5E60` hi/lo pairs, before calling it done. **That verification happened because the pack carried the §426 carve note telling it to.** Journal fuel earned its keep here. + +## §428a ★★ — THE FENCE↔OVER-MERGE COUPLING: WHY A CROSS-JUMP BARRIER CAN COST YOU A REGALLOC WIN (P31 S72, `main/func_8001B0D4`; AGENT-MEASURED, not yet byte-proven) + +**Status flag first (R14):** this is one agent's report over 12+ A/Bs at closeness 53 with length +EXACT (86/86) and the jtbl structure byte-verified. It is a strong observation, not a byte-proof, and +the §428 resolution below is a PREDICTION under test — do not cite it as settled. + +**The observation.** On a function whose residual is a gcc-2.7.2 regalloc **double-hop** +(`$2 → $a0 → $v1`) inside two nested switch dispatchers, every lever that reliably kills the +double-hop — scoping, inline-assign, goto-shared-tail, and **§5a `volatile __asm__` cross-jump +barriers** — re-enables a **2-instruction cross-jump OVER-merge** elsewhere (case 0's own +`D_800747E4` reload folds into the shared tail). The two residuals are in direct tension: each fence +that fixes one re-creates the other, which is why ~20 variants across two attempts all landed at a +similar closeness instead of converging. + +**Why this is a class, not a one-off.** A `volatile __asm__` barrier is a scheduling AND allocation +event, not just a cross-jump one: it forces values live across the barrier and changes the merge +depth of every tail that reaches it. So "add a fence" is never a local edit on a function whose +remaining residual is allocation-shaped — it moves both variables at once, and a two-variable search +driven one fence at a time does not converge. + +**The predicted resolution — §428.** Use the barrier that is NOT a fence: advance the cursor inside +each switch arm so the converging insn becomes a `cross_jump`-created label with +`INSN_UID >= max_uid`, which shuts off `jump.c:1988`'s minimum=2 search with **zero bytes and no +liveness change**. That removes the over-merge half without touching allocation, leaving the +double-hop lever free to act alone. **If you are reading this and the escalation landed, promote this +section to byte-proven and say which lever finally moved `$v1`.** + +**The general habit:** when two residuals move in opposite directions under every lever you try, stop +searching and ask which lever changes only ONE of them.