docs(cookbook): §373 — the dead-reset cse-breaker, the anti-dep pin, and pri(asm)=1

From the fable escalation that closed ov_SC06_010/func_8017E764 (8 -> 0, BOTH
clusters), and it is three findings not one:

1. DEAD-RESET CSE-BREAKER. To stop cse merging two computations of the same
   expression WITHOUT an asm's scheduling footprint: name it, use it, then
   'p = 0;' immediately after. cse invalidates at the second set and flow deletes
   the dead set BEFORE sched1 -- zero bytes, zero LUID disturbance. An empty-asm
   re-tie by contrast is a REAL pre-call insn whose def->asm->arg chain fronts that
   argument's addiu, and on this function that WAS the second residual cluster
   (§361 confirmed: the lever caused the bug it was later blamed on). Removing the
   dead-reset costs +2 ins / +8 frame bytes, so it is load-bearing.

2. A REGISTER PIN THAT DELETES A sched2 ANTI-DEP. sched1's birthing boost sinks a
   single-set 'la' to its consumer, local-alloc reuses the freed scratch, and
   sched2 is then walled by store-reads-$v0 -> la-writes-$v0. A pin on the address
   pointer deletes the anti-dep. Note this is where a pin is RIGHT, against §368
   where pins measured worse -- the discriminator is breaking a false
   anti-dependence (works) vs out-arguing local-alloc about an allocation (fails).

3. HARD FACT: gcc-2.7.2 insn_cost (sched.c:1363) sets LINK_COST_FREE on any dep
   whose consumer is unrecognizable (INSN_CODE<0 = every inline asm), so
   pri(asm)=1 ALWAYS. An asm can never inherit a load's latency into its priority.
   That closes off a whole family of plausible levers.

Also cross-referenced §370: this run was briefed to test that bound FIRST and
reported it did NOT explain the residual. §370's claim is unchanged and still
narrow; the transferable habit is checking whether a recorded bound covers your
case before declaring a residual unreachable.
This commit is contained in:
Drew T
2026-08-31 19:20:46 -06:00
parent 30caa67127
commit c42b3dbc35
2 changed files with 72 additions and 5 deletions
+23 -5
View File
@@ -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 / 1023 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 / 1028 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.
@@ -101,7 +101,7 @@
- **§346** — `c ? X : -X` TAKES expand_expr's COND_EXPR **SINGLETON** PATH (copy, then negate IN PLACE) — AN if/else STATEMENT GIVES THE TWO-ARM FORM (P31 S67; byte-proven ov_SC03_102/func_80180C38, closed the last instruction) <sub>L31322</sub>
- **§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) <sub>L31838</sub>
### instruction scheduling (78)
### instruction scheduling (81)
- **§3-T2** — Source statement order drives instruction scheduling <sub>L78</sub>
- **§3** — When a diff is pure scheduling → decomp-permuter (harness built, Phase 6) <sub>L107</sub>
@@ -181,8 +181,11 @@
- **§352** — ⚠ TWO IDENTICAL `__asm__ __volatile__("")` BARRIERS **MERGE WITH EACH OTHER** — SPELL THE SECOND ONE DIFFERENTLY (P31 S67; byte-proven resident/func_800D128C, measured closeness 105 when they merged) <sub>L31486</sub>
- **§361** — ★ — A LOOP-TAIL BYTE SIGNATURE THAT NAMES ITS SOURCE SHAPE — AND THE LAW THAT A "SCHEDULING TIE" MAY BE YOUR OWN EARLIER LEVER (P31 S68; byte-proven main/func_800241C0, fable escalation, 19 → 0 in 3 iterations) <sub>L31637</sub>
- **§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) <sub>L31838</sub>
- **§373** — ★★★ — THE **DEAD-RESET CSE-BREAKER**, THE PIN THAT BREAKS A sched2 ANTI-DEP, AND WHY AN `asm` CAN NEVER RAISE PRIORITY (P31 S68; byte-proven ov_SC06_010/func_8017E764, 438 ins, fable escalation closed 8 → 0) <sub>L31977</sub>
- **§3-2.** — A REGISTER PIN THAT DELETES A sched2 ANTI-DEPENDENCE <sub>L31997</sub>
- **§3-3.** — HARD FACT FOR THE SCHEDULING MAP — an `asm` ALWAYS has priority 1 <sub>L32010</sub>
### register allocation & pins (123)
### register allocation & pins (125)
- **§10** — Closing the regalloc/scheduling hard tail by hand (LZSS, Phase 7 session F — the full close) <sub>L854</sub>
- **Residual** — A — commutative `|`/`&`/`+` result lands in the wrong source-operand register <sub>L875</sub>
@@ -307,8 +310,10 @@
- **§347** — LOOP REGISTER ASSIGNMENT IS A **DECLARATION-ORDER + LIVE-RANGE** DIAL: FIVE COMPOSABLE LEVERS, 178 -> 0 (P31 S67; byte-proven ov_SC06_029/func_8017EF34, 243 ins) <sub>L31342</sub>
- **§365** — PIN **BOTH** MASKS OR NEITHER (P31 S68; ov_SC01_000/func_8017E594, 357 ins) <sub>L31748</sub>
- **§368** — ★★★ — THE **RELOAD-REMAT CONSTANT**: REACH A REGISTER NO PIN CAN REACH (P31 S68; ov_SC03_105/func_80187A30, 339 ins, fable escalation closed 8 → 0 in ONE edit) <sub>L31792</sub>
- **§373** — ★★★ — THE **DEAD-RESET CSE-BREAKER**, THE PIN THAT BREAKS A sched2 ANTI-DEP, AND WHY AN `asm` CAN NEVER RAISE PRIORITY (P31 S68; byte-proven ov_SC06_010/func_8017E764, 438 ins, fable escalation closed 8 → 0) <sub>L31977</sub>
- **§3-2.** — A REGISTER PIN THAT DELETES A sched2 ANTI-DEPENDENCE <sub>L31997</sub>
### CSE / redundancy / rematerialization (41)
### CSE / redundancy / rematerialization (43)
- **§46** — The `func_80178D40` crack (890 ins ×134, the heaviest core in the game): four LOOP-STRUCTURE levers cheap-Opus found by reading loop.c/jump.c/cse.c (Phase 26 session 8, 2026-07-13) <sub>L3347</sub>
- **§83d** — CSE's quantity budget is WHOLE-FUNCTION, so a local rewrite cannot fix a local symptom <sub>L6486</sub>
@@ -351,6 +356,8 @@
- **§351** — `/s` (MEM_IN_STRUCT_P) IS A DIAL YOU CHOOSE PER ACCESS: A COMPONENT_REF GRANTS IT AND LETS cse KEEP AN INDEX ACROSS THE STORE; A PLAIN CAST DENIES IT (P31 S67; ov_SC01_000/func_8017DD04, 186 -> 5) <sub>L31456</sub>
- **§352** — ⚠ TWO IDENTICAL `__asm__ __volatile__("")` BARRIERS **MERGE WITH EACH OTHER** — SPELL THE SECOND ONE DIFFERENTLY (P31 S67; byte-proven resident/func_800D128C, measured closeness 105 when they merged) <sub>L31486</sub>
- **§368** — ★★★ — THE **RELOAD-REMAT CONSTANT**: REACH A REGISTER NO PIN CAN REACH (P31 S68; ov_SC03_105/func_80187A30, 339 ins, fable escalation closed 8 → 0 in ONE edit) <sub>L31792</sub>
- **§373** — ★★★ — THE **DEAD-RESET CSE-BREAKER**, THE PIN THAT BREAKS A sched2 ANTI-DEP, AND WHY AN `asm` CAN NEVER RAISE PRIORITY (P31 S68; byte-proven ov_SC06_010/func_8017E764, 438 ins, fable escalation closed 8 → 0) <sub>L31977</sub>
- **§3-1.** — DEAD-RESET CSE-BREAKER — the zero-footprint replacement for a §195-I asm re-tie <sub>L31979</sub>
### loops & induction variables (43)
@@ -1276,7 +1283,7 @@
- **§361** — ★ — A LOOP-TAIL BYTE SIGNATURE THAT NAMES ITS SOURCE SHAPE — AND THE LAW THAT A "SCHEDULING TIE" MAY BE YOUR OWN EARLIER LEVER (P31 S68; byte-proven main/func_800241C0, fable escalation, 19 → 0 in 3 iterations) <sub>L31637</sub>
- **§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) <sub>L31838</sub>
### (unbucketed — title matched no symptom vocabulary) (303)
### (unbucketed — title matched no symptom vocabulary) (304)
- **§3-How** — to use this <sub>L30</sub>
- **§1** — Idiom catalog (asm pattern → C that produces it) <sub>L39</sub>
@@ -1581,6 +1588,7 @@
- **§363** — ★★ — THE OVERLAY-LAYOUT ASSUMPTION IS A SYSTEMIC BUG CLASS, AND `main` IS THE EXCEPTION THAT FINDS IT (P31 S68; six instances, four of them in one session) <sub>L31705</sub>
- **§369** — REUSE THE **COMPARE CONSTANT'S OWN VARIABLE** FOR A MASK THAT KEEPS COALESCING (P31 S68; md_SC07_004/func_801AEC38, 365 ins) <sub>L31822</sub>
- **§372** — ★★★ — THE **COPY-CAPTURE PAIR**, AND THE ONE ZERO-BYTE EDIT THAT DEFEATS BOTH (P31 S68; byte-proven main/func_8003491C, 78 ins, fable escalation closed 5 → 0) <sub>L31939</sub>
- **CROSS-REFERENCE** — TO §370 — checked and found INAPPLICABLE here, which is the point <sub>L32018</sub>
## All sections, in order
@@ -2608,6 +2616,11 @@
- **§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) <sub>L31838</sub>
- **§371** — ★★ — CARVING A **SINGLE-OBJECT MODULE BINARY**, AND THE spimdisasm RODATA-MIGRATION TRAP THAT FOLLOWS (P31 S68; byte-proven md_MAIN_003, func_800D0D6C 345 ins) <sub>L31890</sub>
- **§372** — ★★★ — THE **COPY-CAPTURE PAIR**, AND THE ONE ZERO-BYTE EDIT THAT DEFEATS BOTH (P31 S68; byte-proven main/func_8003491C, 78 ins, fable escalation closed 5 → 0) <sub>L31939</sub>
- **§373** — ★★★ — THE **DEAD-RESET CSE-BREAKER**, THE PIN THAT BREAKS A sched2 ANTI-DEP, AND WHY AN `asm` CAN NEVER RAISE PRIORITY (P31 S68; byte-proven ov_SC06_010/func_8017E764, 438 ins, fable escalation closed 8 → 0) <sub>L31977</sub>
- **§3-1.** — DEAD-RESET CSE-BREAKER — the zero-footprint replacement for a §195-I asm re-tie <sub>L31979</sub>
- **§3-2.** — A REGISTER PIN THAT DELETES A sched2 ANTI-DEPENDENCE <sub>L31997</sub>
- **§3-3.** — HARD FACT FOR THE SCHEDULING MAP — an `asm` ALWAYS has priority 1 <sub>L32010</sub>
- **CROSS-REFERENCE** — TO §370 — checked and found INAPPLICABLE here, which is the point <sub>L32018</sub>
---
@@ -3643,3 +3656,8 @@ Notes routinely quote that as a section id. This table resolves it. Grep bait: `
| L31838 | §370 | ★★ — A **HARD BOUND** FROM sched.c, AND THE reorg SLOT-STEAL DIAGNOSTIC (P31 S68; main/fun |
| L31890 | §371 | ★★ — CARVING A **SINGLE-OBJECT MODULE BINARY**, AND THE spimdisasm RODATA-MIGRATION TRAP T |
| L31939 | §372 | ★★★ — THE **COPY-CAPTURE PAIR**, AND THE ONE ZERO-BYTE EDIT THAT DEFEATS BOTH (P31 S68; by |
| L31977 | §373 | ★★★ — THE **DEAD-RESET CSE-BREAKER**, THE PIN THAT BREAKS A sched2 ANTI-DEP, AND WHY AN `a |
| L31979 | §3-1. | DEAD-RESET CSE-BREAKER — the zero-footprint replacement for a §195-I asm re-tie |
| L31997 | §3-2. | A REGISTER PIN THAT DELETES A sched2 ANTI-DEPENDENCE |
| L32010 | §3-3. | HARD FACT FOR THE SCHEDULING MAP — an `asm` ALWAYS has priority 1 |
| L32018 | CROSS-REFERENCE | TO §370 — checked and found INAPPLICABLE here, which is the point |
+49
View File
@@ -31973,3 +31973,52 @@ through reload. Here the rows are pure shift/`slti` with no commutative operands
hold, and the RTL dumps named copy-capture instead. **The escalation was told to CHECK whether §368's
tell applied rather than assume it, reported that it did not, and found the real cause** — which is
the procedure §361 asks for, working as intended.
## §373 ★★★ — THE **DEAD-RESET CSE-BREAKER**, THE PIN THAT BREAKS A sched2 ANTI-DEP, AND WHY AN `asm` CAN NEVER RAISE PRIORITY (P31 S68; byte-proven ov_SC06_010/func_8017E764, 438 ins, fable escalation closed 8 → 0)
### 1. DEAD-RESET CSE-BREAKER — the zero-footprint replacement for a §195-I asm re-tie
To stop cse merging two computations of the same address/expression (the classic case: `&local`
passed to two calls) **without** an asm's scheduling footprint:
p = expr; /* name it */
f(..., p); /* use it */
p = 0; /* DEAD-RESET, immediately after */
cse's forward scan invalidates the equivalence at the second set, and `flow` deletes the dead set
**before sched1** — so it costs **zero bytes and zero LUID/priority disturbance**.
**Why this beats the asm re-tie:** an empty-asm re-tie is a REAL pre-call insn whose
`def -> asm -> arg` chain has an early LUID and therefore FRONTS that argument's `addiu` over its
siblings. That is a scheduling side effect, and on this function it *was* the second residual
cluster — §361 confirmed, the lever caused the bug it was later blamed on.
Proof the dead-reset is load-bearing rather than cosmetic: removing it costs **+2 instructions and
+8 frame bytes**.
### 2. A REGISTER PIN THAT DELETES A sched2 ANTI-DEPENDENCE
**Symptom:** the target interleaves an address materialization (an `la` pair) between an unrelated
load and its store; yours emits load / store / `la` serially **in the same register**.
**Cause chain, in order:** sched1's birthing boost sinks the single-set `la` to its consumer →
local-alloc reuses the just-freed scratch (`$v0`) → **sched2 is then walled by the
store-reads-`$v0` → `la`-writes-`$v0` ANTI-dependence**.
**Fix:** a `register __asm__` pin on the address pointer to the TARGET's register deletes that
anti-dep, and sched2 reproduces the interleave. Pair it with splitting the deref from its `+K`
consumer around the neighbouring statement to set LUID fill order.
Note this is a case where a pin is exactly right — contrast §368, where pins were measured WORSE.
The discriminator is WHAT the pin is for: breaking a false anti-dependence (works) versus trying to
out-argue local-alloc about an allocation (fails).
### 3. HARD FACT FOR THE SCHEDULING MAP — an `asm` ALWAYS has priority 1
`gcc-2.7.2 insn_cost` (**sched.c:1363**) sets `LINK_COST_FREE` on any dependence whose CONSUMER is
unrecognizable — `INSN_CODE < 0`, which is **every inline asm**. So an asm can never inherit a load's
latency-2 into its priority: **`pri(asm) = 1`, always.**
**Do not try to raise an instruction's priority by feeding a load through an asm.** That closes off a
whole family of plausible-looking levers, which is why it is worth its space next to §370's
`schedule_select` bound.
### CROSS-REFERENCE TO §370 — checked and found INAPPLICABLE here, which is the point
This escalation was briefed to test §370's bound (a ready load always beats an equal-priority ALU
leaf) against cluster 1 FIRST. It reported that the bound did **not** explain this residual — the
cause was the birthing-boost → local-alloc → anti-dep chain above — and then found the real one.
§370's claim is unchanged and still narrow: it applies to *simultaneously-ready same-priority leaves*.
The habit is the transferable part: check whether a recorded bound actually covers your case before
concluding the residual is unreachable.