From 1e314e7208b69e493581ff3c86d11efdbd813000 Mon Sep 17 00:00:00 2001
From: Drew T <50529377+Druthulu@users.noreply.github.com>
Date: Wed, 2 Sep 2026 10:22:16 -0600
Subject: [PATCH] =?UTF-8?q?docs(cookbook):=20=C2=A7424=20-=20equal-priorit?=
=?UTF-8?q?y=20stores=20emit=20REVERSED=20(sched1=20LUID=20tie=20picks=20t?=
=?UTF-8?q?he=20last=20statement)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Byte-proven on ov_SC07_006/func_801890FC (387 ins). For two stores at equal priority,
sched1's LUID tie picks the LAST statement's store first; regalloc then gives the other
load $v0, where it sits behind its own $v0 predecessors, and sched2 pins that chain last.
Each equal-priority pair therefore appears reversed: source FE;E-=0x40;A-=0xEE;88;8A;8C
emits as E,88,A,8C,8A.
This is why "statement order is inert" is such a common wrong conclusion here - the
mapping is not identity, so trying orders at random explores the wrong space. Compute the
intended emission order, then invert each equal-priority pair.
Companion (§193-E): the prior draft left no different-address store between `sh 0xA` and
its re-read, so cse forwarded it as `andi 0xffff`. A store to a different address between
the two re-seeds cse - §416's "re-read the store" seen from the failure side.
---
docs/cookbook-index.md | 7 +++++--
docs/matching-cookbook.md | 22 ++++++++++++++++++++++
2 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/docs/cookbook-index.md b/docs/cookbook-index.md
index 02d05352dd..eb32816382 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 / 1091 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 / 1092 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.
@@ -102,7 +102,7 @@
- **§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
-### instruction scheduling (86)
+### instruction scheduling (87)
- **§3-T2** — Source statement order drives instruction scheduling L78
- **§3** — When a diff is pure scheduling → decomp-permuter (harness built, Phase 6) L107
@@ -190,6 +190,7 @@
- **§385** — ★★★ — THE **SCHED2 PRIORITY-DONOR ASM**: closing the "hoisted-invariant vs IV-init preheader swap" class (P31 S69; byte-proven main/func_80038A58, 347 ins, fable escalation 2 → 0) L32309
- **§393** — ★★ — THE **BIRTHING BOOST**: A SINGLE-SET LOCAL IS SCHEDULED LAST; GIVE IT A SECOND SET (P31 S69; byte-proven ov_SC02_017/func_8017FCFC) L32543
- **§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
### register allocation & pins (131)
@@ -2772,6 +2773,7 @@
- **§421** — ★★★ — A `la $tN` + `addiu` PAIR CAN BE A **RELOAD** ARTIFACT THAT NO C SPELLING REACHES (P31 S71; byte-proven `md_SC07_003/func_801A293C`, 313 ins, 6 → 0) L33729
- **§422** — ★★ — QImode ARITHMETIC VIA `(u8)(x - K)`, AND `flag ^ 1` NEEDS ITS OWN TEMP (P31 S71; byte-proven `resident/func_800D06E8`, 344 ins) L33760
- **§423** — ★★★ — "MATCH IN ISOLATION + GATE REJECTS + CAUSE NOT DETERMINED" ⇒ GREP THE TU FOR A FILE-SCOPE TYPEDEF THE DRAFT ALSO CARRIES (P31 S71; byte-proven `ov_SC03_092/func_8017FA74`) L33780
+- **§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
---
@@ -3875,3 +3877,4 @@ Notes routinely quote that as a section id. This table resolves it. Grep bait: `
| L33729 | §421 | ★★★ — A `la $tN` + `addiu` PAIR CAN BE A **RELOAD** ARTIFACT THAT NO C SPELLING REACHES (P |
| L33760 | §422 | ★★ — QImode ARITHMETIC VIA `(u8)(x - K)`, AND `flag ^ 1` NEEDS ITS OWN TEMP (P31 S71; byte |
| L33780 | §423 | ★★★ — "MATCH IN ISOLATION + GATE REJECTS + CAUSE NOT DETERMINED" ⇒ GREP THE TU FOR A FILE- |
+| L33807 | §424 | ★★★ — EQUAL-PRIORITY STORES COME OUT **REVERSED**: sched1's LUID tie picks the LAST statem |
diff --git a/docs/matching-cookbook.md b/docs/matching-cookbook.md
index af3cf880d5..fbdcc5c614 100644
--- a/docs/matching-cookbook.md
+++ b/docs/matching-cookbook.md
@@ -33803,3 +33803,25 @@ the TU defines that name.**
exits 1 on its relative `"../shared/engine_core.h"` — and then **every variant "passes" identically**,
which is a silent all-green instrument. Negative-control any TU-splice harness against an unmodified
copy before believing a single verdict from it.
+
+## §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)
+
+**The symptom.** A run of same-shape halfword stores appears in the asm in an order that looks
+scrambled relative to any source order you try — and statement reordering seems to do nothing useful,
+because every order you try is wrong in the same way.
+
+**The mechanism, read off `-dS`/`-dR` against `docs/gcc-2.7.2-map/sched.md`.** For a pair of stores at
+EQUAL priority, sched1's LUID tie picks the **last statement's** store first. Regalloc then hands the
+OTHER load `$v0` — where it is stuck behind its own `$v0` predecessors — and sched2 pins that chain
+last. Net effect: **each equal-priority pair appears reversed in the output.** Measured here, source
+order `FE ; E-=0x40 ; A-=0xEE ; 0x88= ; 0x8A= ; 0x8C=` emits as `E, 88, A, 8C, 8A`.
+
+**So write the source in the order that INVERTS pairwise**, rather than the order you want to read in
+the asm. This is why "statement order is inert" is such a common (and wrong) conclusion on these
+functions: the mapping is not identity, so trying orders at random explores the wrong space. Compute
+the intended emission order, then invert each equal-priority pair.
+
+**The companion defect on the same function (§193-E).** The prior draft's temps left **no
+different-address store between `sh 0xA` and its re-read**, so cse forwarded the value and emitted
+`andi 0xffff` instead of the reload. A store to a different address between the two is what re-seeds
+cse — the same lever as §416's "re-read the store", seen from the failure side.