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.