From 8a19b3ca52dcbd041b2abf16512de9e92a2fe746 Mon Sep 17 00:00:00 2001
From: Drew T <50529377+Druthulu@users.noreply.github.com>
Date: Tue, 1 Sep 2026 15:01:06 -0600
Subject: [PATCH] =?UTF-8?q?docs(cookbook):=20=C2=A7398b=20=E2=80=94=20nami?=
=?UTF-8?q?ng=20a=20sub-expression=20changes=20which=20pseudo=20survives;?=
=?UTF-8?q?=20inline=20it=20at=20both=20use=20sites?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docs/cookbook-index.md | 7 +++++--
docs/matching-cookbook.md | 27 +++++++++++++++++++++++++++
2 files changed, 32 insertions(+), 2 deletions(-)
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.