phase11: cookbook 116-118 — the ranker's blind spot, a new failure signature, and two negatives

116: worker A's hypothesis that the ranker cannot see LIVE RANGES (its conversion rate went to
zero over three consecutive rows, all failing on register allocation with the structure fully
confirmed). I tried to make it computable -- callee-saved registers saved and s-registers per
call -- and the proxy FAILED: matches span 0.00-2.00 s/call and failures span 0.17-1.33, with
a matched row having the HIGHEST s-register count and another matched row having 16 calls and
0 saved registers. The hypothesis is not refuted; the proxy is just not a good
operationalisation of 'live range'. Recorded as an open axis.

117: worker C's new signature -- correct control flow, +3 instructions, all three being j/jr
delay slots. DISTINCT from a nesting error (both give a small residual, but nesting moves
branch displacements while this moves instructions ACROSS a jump). Belongs with the post-pass
family.

118: call COUNT does not separate a real block from a call chain -- worker C's matched
0x80058CE8 is four loops that each call, and its false positive has zero calls. Fails in both
directions; recorded so nobody re-derives it.
This commit is contained in:
Christopher Williams
2026-09-24 10:20:47 -04:00
parent fc7ebc4b2d
commit 71aa4a2bc2
+78
View File
@@ -1840,3 +1840,81 @@ mask writes to the same field are two source statements, not one — the same pr
Companion: the status **load is hoisted above nine halfword clears** by the scheduler, so the clears'
source order is only observable through the **store order**.
### 116. A SECOND FAILURE AXIS exists — but the cheap proxy for it FAILS (worker A + coordinator)
**Worker A's hypothesis, which is the most valuable thing said about the ranker's limits:** its
conversion rate went to **zero over three consecutive rows**, and all three failed for the same
reason — **register allocation, not source shape**. Its framing:
> Every row I have **matched** has a **data-movement** shape — copies, table walks, repetitive call
> sequences. Every row I have **failed** has a **live-range** shape: a flag whose value is known at
> the return, two parameters that are interchangeable, a pointer reloaded per use.
> **The ranker measures the instruction stream, not the live ranges, so it cannot see this.**
Worker A's proposed discriminator: *does the body keep any value live across a call that is not a
pointer or an array? If yes, expect an allocator residual; if no, the redundancy score is
trustworthy.*
**I TRIED TO MAKE THAT COMPUTABLE AND THE PROXY FAILED.** Proxy: the number of callee-saved
registers the body saves (values the allocator decided must survive a call), and s-registers per
call.
| row | outcome | redundancy | s-regs saved | calls | s/call |
|---|---|---|---|---|---|
| `0x8009C904` | MATCH | 0.81 | 2 | 3 | 0.67 |
| `0x80036DA4` | MATCH | 0.77 | **6** | 3 | **2.00** |
| `0x800556E8` | MATCH | 0.67 | 1 | 1 | 1.00 |
| `0x80068910` | MATCH | 0.82 | 0 | 0 | 0.00 |
| `0x800914E4` | MATCH | 0.81 | 3 | 10 | 0.30 |
| `0x8006B7C0` | MATCH | 0.80 | 0 | 16 | 0.00 |
| `0x8009F264` | **FAIL** | 0.67 | 4 | 3 | 1.33 |
| `0x8007F774` | **FAIL** | 0.70 | 1 | 1 | 1.00 |
| `0x80017C6C` | **FAIL** | 0.33 | 2 | 2 | 1.00 |
| `0x800B7264` | **FAIL** | 0.77 | 5 | 10 | 0.50 |
| `0x80058DEC` | **FAIL** | 0.69 | 5 | 4 | 1.25 |
| `0x800FE878` | **FAIL** | 0.39 | 1 | 6 | 0.17 |
**The ranges overlap completely** — matches span 0.00–2.00 s/call, failures span 0.17–1.33. **The
proxy does not separate them.** Note in particular that a *matched* row has the **highest**
s-register count (6) and another matched row has **16 calls and 0 saved registers**.
**So the hypothesis is not refuted — the proxy is simply not a good operationalisation of "live
range".** Worker A's description is about *which values* stay live and *whether the allocator has a
choice*, not about how many registers are spilled. Recording it as an open axis: **the ranker has a
known blind spot and no cheap proxy for it yet.** Anyone who finds one should say so.
### 117. "Correct control flow, +3 instructions, all three `j`/`jr` delay slots" is its OWN signature (worker C)
Worker C's `0x80103544` (696 B, 6 attempts): candidate **708 vs 696 (+12)**, and **the control flow
is structurally identical** — all 15 branches, same relative targets, same arm order, one back edge,
four exits. The entire residual is **three delay slots the original's reorg filled and the candidate
left as nops:**
A2 arm: j end with sw a2,28(s2) IN the slot
A3 arm: j end with sw a1,28(s2) IN the slot
epilogue: jr ra with addiu sp,sp,32 IN the slot (candidate: addiu; jr ra; nop)
All three are the same shape: *the instruction immediately preceding the jump moved after it.*
**This is a DISTINCT signature from a nesting error (finding 95)** — both produce a small residual at
correct-ish length, but nesting errors move *branch displacements* while this moves *instructions
across a jump*. Worker C notes its own matched `0x80031FC4` **does** have a filled delay
(`j join1; sw v0,32(sp)`), so cc1 fills when the source is right; the trigger here is not any of the
five shapes it tried (nesting order, arm order, `tbl`-first declaration, `goto`-instead-of-`break`,
splitting `V8`). **So it is a source-shape hunt, not a brace hunt** — and it belongs with the
post-pass family, since the fill is what the original's assembler did.
### 118. Call COUNT does not separate a real block from a call chain — measured, both directions (worker C)
Worker C tried "a long run with few calls is a real block, a long run with many calls is a call
chain" as a discriminator and **it fails in both directions:**
- Worker C's **matched** `0x80058CE8` is **four loops that each call** `0x80012D8C` — many calls,
and a genuine repeated block.
- Its **false positive** (`0x8001C8AC`) has **zero calls**.
**So call count does not separate them either.** Recorded as a negative so nobody re-derives it. The
one weak signal in worker C's table: its false positive sits at a structurally-repeated run of
**10** and the run is exactly the `multu`/`mflo`/`sra` chain, while rows above run **18** are
plausibly real blocks — **but that is a guess from one false positive, not a measurement.**