From 3371e57ed0af375c2b446bdd013f3007995af0dd Mon Sep 17 00:00:00 2001 From: Drew T <50529377+Druthulu@users.noreply.github.com> Date: Tue, 28 Jul 2026 15:02:51 -0600 Subject: [PATCH] =?UTF-8?q?docs(phase-29):=20regalloc.md=20=C2=A7H=20?= =?UTF-8?q?=E2=80=94=20the=20swap=20oracle's=20two=20unstated=20PRECONDITI?= =?UTF-8?q?ONS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit §H sold the reg_renumber-swap oracle as THE one-gdb-run discriminator between RC-6 (allocation) and S3 (scheduling). It has two preconditions it never stated, and both failed silently on the first real use after the audit: 1. reg_renumber maps PSEUDOS ONLY (index >= FIRST_PSEUDO_REGISTER = 68 on MIPS, mips.h:1179). A contested register that is already HARD at .greg time — an incoming parameter reg, a pin, or a local-alloc reuse — is structurally unreachable. Check the .greg RTL first: (reg/v:SI 6 a2) with 6 < 68 does not qualify; only (reg:SI 130)-style operands do. 2. The contest must be NARROW. The swap is global across reg_renumber, so if the pair serves many pseudos it destroys the allocations that were already correct. Byte-measured on func_80176734, baseline 13: control 1<->1 -> 13 (harness validated); <-> moved 17 pseudos -> 345; <-> moved 31 -> 97. The .greg read then showed the destination was (reg/v:SI 6 a2) — hard, a reused incoming parameter register — so the true class was local-alloc TYING (K8/RC-4), not RC-6, and the lever is C-level lifetime shaping. Harness + negative control preserved at tools/oracle/reg_renumber_swap.sh. --- docs/gcc-2.7.2-map/regalloc.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/gcc-2.7.2-map/regalloc.md b/docs/gcc-2.7.2-map/regalloc.md index 141b9db5e2..bff8c946d1 100644 --- a/docs/gcc-2.7.2-map/regalloc.md +++ b/docs/gcc-2.7.2-map/regalloc.md @@ -256,6 +256,24 @@ A compare/arith result qty whose insn kills a HARD (pinned) input records `qty_p Three seed cracks (`.run/giants/{func_8014D820,func_801670E4,func_8016CBC0}.fable.md`) continuing the §F/§G theme — an "RC-6 intrinsic" verdict is usually map-incompleteness. The durable output is one **diagnostic** and two **levers**. ### THE reg_renumber-SWAP ORACLE — discriminate RC-6 (allocation) from S3 (scheduling) in ONE gdb run +> **[A23] PRECONDITION — CHECK `.greg` FIRST, or this oracle will hand you a confident wrong answer.** +> `reg_renumber` maps **PSEUDOS ONLY** (index ≥ `FIRST_PSEUDO_REGISTER`, which is **68** on MIPS — +> `config/mips/mips.h:1179`). If the diff's contested registers are already **hard** at `.greg` time +> they are structurally unreachable here, and a swap returns a large number that *looks* like a +> verdict and is not one. +> **The check:** grep the `.greg` RTL for the contested instruction. `(reg/v:SI 6 a2)` with `6 < 68` +> is a HARD register — an incoming parameter reg, a `register __asm__` pin, or a local-alloc reuse — +> **not** something this oracle can move. Only `(reg:SI 130)`-style operands qualify. +> **Second precondition — the contest must be NARROW.** The swap is global across `reg_renumber`, so +> if the two registers serve many pseudos it destroys the allocations that were already right. +> Count them first; the harness prints the number it moved. +> **Byte-measured on `func_80176734` (2026-07-28), baseline 13 mismatches:** control swap `$31↔$31` +> reproduced **13** ✓ · `$a0↔$a2` moved 17 pseudos → **345** · `$v1↔$a1` moved 31 pseudos → **97**. +> The `.greg` read then showed the destination was `(reg/v:SI 6 a2)` — hard, a reused incoming +> parameter register — so the true class was **local-alloc tying (K8/RC-4), not RC-6 global +> allocation**, and the lever is C-level lifetime shaping. Both preconditions failed silently. +> **Mechanized harness (with its negative control): `tools/oracle/reg_renumber_swap.sh`.** + The single highest-value tool of the wave. When a residual is "register identity AND an instruction reordering" you cannot tell from the diff whether the reorder is a *scheduling* decision (S3, C often can't move it) or a mere *consequence* of the register grant (fix the regs and the schedule follows). Test it directly: break at `reload` entry, patch `reg_renumber` (a `short*`; find its address in the cc1 map) to swap the two contested hard regs, let compilation finish, and diff. **If the block goes byte-exact (schedule included), the residual is 100% ALLOCATION** — the reorder was a consequence, route to the density/lifetime levers, NOT to a scheduling lever or the permuter's schedule mode. (`func_801670E4`: the seed called its dominant residual an S3 `sched.c` priority wall — "C cannot lower a priority"; the swap oracle emitted the store-before-load target byte-exact, proving it was pure register 2-coloring. Generalizable: **store-before-load reordering is often a CONSEQUENCE of register identity, not a scheduling cause — swap-oracle it before invoking S3/S4.**) ### RC-14 — reused-load-temp SERIALIZATION (the MERGE pole; pin-free, cheap-Opus-applicable)