diff --git a/docs/cookbook-index.md b/docs/cookbook-index.md index aafdb9873..5d711d8ac 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 / 1059 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 / 1060 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. @@ -1323,7 +1323,7 @@ - **§378b** — ★★★ — THE FOUR VARIANTS OF THE DECL BLOCKER, AND THE TWO PLACES §378 DOES **NOT** APPLY (P31 S69, all four measured the same day) L32572 - **§398** — ★★★ — `family_remap` CARRIES THE **SOURCE** TU's DECL ENVIRONMENT INTO A DESTINATION THAT ALREADY OWNS THOSE NAMES (P31 S69; measured 3 banked of 22) L32835 -### (unbucketed — title matched no symptom vocabulary) (312) +### (unbucketed — title matched no symptom vocabulary) (313) - **§3-How** — to use this L30 - **§1** — Idiom catalog (asm pattern → C that produces it) L39 @@ -1637,6 +1637,7 @@ - **§394** — ★★ — TWO ALIGN-1 ACCESSES IN ONE FUNCTION RESERVE A PHANTOM STACK SLOT (P31 S69; ov_SC02_005/func_80180610) L32560 - **§314b** — ★★ — TWO ABS-RANGE GUARDS IN ONE FUNCTION NEED **DIFFERENT SPELLINGS** (P31 S69; byte-proven ov_SC04_002/func_8018691C, 111 ins) L32645 - **§397** — ★★★ — RE-RUN THE TWIN SCAN AFTER EVERY EXEMPLAR BANK; A CLUSTER SIBLING IS FREE THE MOMENT ITS EXEMPLAR LANDS (P31 S69; ~250k tokens spent proving it the expensive way) L32785 +- **§398b** — ★★ — NAMING A SUB-EXPRESSION IN A LOCAL CHANGES WHICH PSEUDO SURVIVES; INLINE IT AT BOTH USE SITES (P31 S69; byte-proven ov_SC03_028/func_80183264, 93 ins) L32865 ## All sections, in order @@ -2700,6 +2701,7 @@ - **§397** — ★★★ — RE-RUN THE TWIN SCAN AFTER EVERY EXEMPLAR BANK; A CLUSTER SIBLING IS FREE THE MOMENT ITS EXEMPLAR LANDS (P31 S69; ~250k tokens spent proving it the expensive way) L32785 - **§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 - **§398** — ★★★ — `family_remap` CARRIES THE **SOURCE** TU's DECL ENVIRONMENT INTO A DESTINATION THAT ALREADY OWNS THOSE NAMES (P31 S69; measured 3 banked of 22) L32835 +- **§398b** — ★★ — NAMING A SUB-EXPRESSION IN A LOCAL CHANGES WHICH PSEUDO SURVIVES; INLINE IT AT BOTH USE SITES (P31 S69; byte-proven ov_SC03_028/func_80183264, 93 ins) L32865 --- @@ -3771,3 +3773,4 @@ Notes routinely quote that as a section id. This table resolves it. Grep bait: ` | L32785 | §397 | ★★★ — RE-RUN THE TWIN SCAN AFTER EVERY EXEMPLAR BANK; A CLUSTER SIBLING IS FREE THE MOMENT | | L32818 | §396g | ★★ — A GUARD LADDER'S RUNGS MUST STAY SYMMETRIC OR `reorg.c` LOSES ITS BRANCH REDIRECT (P3 | | L32835 | §398 | ★★★ — `family_remap` CARRIES THE **SOURCE** TU's DECL ENVIRONMENT INTO A DESTINATION THAT | +| L32865 | §398b | ★★ — NAMING A SUB-EXPRESSION IN A LOCAL CHANGES WHICH PSEUDO SURVIVES; INLINE IT AT BOTH U | diff --git a/docs/matching-cookbook.md b/docs/matching-cookbook.md index 495c63286..560ad5b2a 100644 --- a/docs/matching-cookbook.md +++ b/docs/matching-cookbook.md @@ -32861,3 +32861,30 @@ environment — the information exists (`decl_prior` already computes it for car `cast_self_callers`/`fix_arity_callers` already edit it). Until it does, the remap lane's realistic yield is ~15% straight-through and ~50% after integration, not the 76–88% the PURE-class rate suggests. **Quote the straight-through number when planning, not the class rate.** + +## §398b ★★ — NAMING A SUB-EXPRESSION IN A LOCAL CHANGES WHICH PSEUDO SURVIVES; INLINE IT AT BOTH USE SITES (P31 S69; byte-proven ov_SC03_028/func_80183264, 93 ins) + +Writing a repeated computation **inline at both use sites** and writing it **once into a named local** +are not equivalent, and the difference is visible in the register file: + +```c + f( (v1 * 104) / 1024, ... ); /* inline at BOTH sites — cse builds the CSE itself */ + s32 t = (v1 * 104) / 1024; /* named — expmed.c:2986 copy_to_mode_reg's temp */ +``` + +Naming it lets `expmed.c`'s `copy_to_mode_reg` temp **coalesce with the product** (an in-place +`addiu`/`sra`) and moves the surviving divide-copy onto the `/16`. Letting cse construct the common +subexpression itself keeps the temp a **separate pseudo** — which is what the target shows. + +**Two companions from the same crack:** +* **An `s16` local's cse quantity differs from an `s32` one**, and that difference alone is why an + `addu $s3,$s2,$zero` copy survives. Rewriting as `s32 t` + an `(s16)` cast lets `t.i.cse` fold + three regs into one and the function loses two saved registers and two copies. **The declared width + is a cse-quantity dial, not just a codegen one** (compare §392b). +* **The §136d-1 `zr` trick needs to be applied to BOTH copies, not one.** `arg = ang;` alone is + `canon_reg`'d away; `arg = ang + zr;` on both copies lets cse merge the two identical `ang+$0` + expressions into one, reproducing the target's pair. + +**Banking caveat:** a `register … __asm__("$0")` pin fails `dedup_propagate.compiles_standalone` +(§37), so a function cracked this way banks ×1 and never propagates to siblings. Prefer a +width/inlining lever over a `$0` pin when the function has cousins.