Commit Graph

92 Commits

Author SHA1 Message Date
Christopher Williams b0ed17d494 phase11: merge 60 + cookbook 181-182 — 601 bodies / 610 regions
Worker F's 0x8002622C (44 B) — A RECORDED NEGATIVE OVERTURNED, with a new class.

The old record said 'cc1 folds it, unreachable' and tried FOUR ALGEBRAIC re-spellings. All four
were doomed: the fold is at RTL combine, not in the front end, so no re-spelling can avoid it.
Only LIVENESS can. Same body with 'return 0' is 32 B LENGTH-MISMATCH; with 'return n' (the
difference live past the addition) it is 44/0/MATCH. Diagnostic that proves the pass: cc1 -da
shows the minus present in the .flow dump and gone in the .combine dump, while cse/cse2/jump/
loop/sched/sched2 all still contain it.

181: when an original keeps an arithmetically-cancelling pair (subu+addu, x-c+c), the intermediate
is LIVE PAST the second operation — find the later reader.

182: a negative with a NAMED mechanism is overturnable; one without is not. 'cc1 folds it' is not
a classification; 'RTL combine cancels it, and algebraic re-spelling cannot reach combine' is,
and it immediately implies the liveness lever.
2026-09-24 11:42:17 -04:00
Christopher Williams 3519afe441 phase11: tools/sf3_free + cookbook 179-180 — the EIGHTH rule defect, and the token table
179: a rule every worker must follow belongs in a TRACKED tool, not a copied script. The registry
free-check lived in a worker's staging dir and the orchestrator told everyone to copy it. It was
WRONG -- it reported TAKEN if ANY ledger row for the address was not 'released', so a row that was
wip and later released stayed blocked FOREVER. Worker E found it and measured 13 released rows
reading as taken, several of them the cheapest rows left, and the same stale pattern existed for
workers A and D too. Fixed and promoted to tools/sf3_free (tracked, docstring explains the bug).
A copied script cannot be fixed for the people who already copied it.

180: worker E's maspsx=epilogue token table, MEASURED not inferred -- 5 rows REQUIRED, 3 HARMFUL
or NO-OP, 2 HARMFUL-but-unmatched. Three of E's fourteen claims sit on that list and TWO would
have failed outright if the token had been applied by shape. The cheap read: '4 bytes SHORT with
the token on' means the token was unnecessary.
2026-09-24 11:39:45 -04:00
Christopher Williams bec90acd31 phase11: cookbook 175-178 — mask chains, CSE store-forwarding, OR reassociation, and 170's constant variant
175: mask chains must be SEPARATE STATEMENTS -- one expression folds to a single and; three
statements emit the original's lw/and/and/and/sw. cc1 does not fold constants across statements.

176: a MECHANISM, not a tip. Three separate RMW statements give one lw, three ands and ONE sw
(cse forwards each load from the previous store within a block); an intervening early return makes
that store land in the beq delay slot and the tail's store stays alive because its load is
forwarded from a store in the PREVIOUS block. A local chain loses the delay-slot store (100 B);
volatile keeps both stores but flips the entry branch (100 B).

177: fold REASSOCIATES | -- one statement becomes v | (C1 | X), a 17-byte residual; two statements
give the original (v | C1) | X.

178: finding 170 has a CONSTANT-clobber variant -- the same entry-block copies arise because mask
constants are materialised into the parameters' own homes, with no call involved. The rule
generalises: a redundant entry copy means the value is live when its home is clobbered, whether by
a call's argument setup OR by constant materialisation.
2026-09-24 11:34:23 -04:00
Christopher Williams 773cb88dcf phase11: cookbook 172-174 — a missing sign bias, a second swapped-subtraction, and when to decline a row
172: a MISSING sign bias is evidence of a shift, not a division -- the values are non-negative in
the source but cc1 cannot know that after a conditional, so the absence of the addiu is the
diagnostic. Finding 97 read backwards.

173: the absolute value is a SWAPPED SUBTRACTION (subu with operands exchanged), not negu -- the
natural -x is the trap. Second instance of finding 101.

174: the idiom-redundant-by-construction class, and the discipline of declining a row. Worker E
decoded 0x800FECF8 -- one of the highest-scoring fresh small rows -- and RELEASED it without
attempting it, because it is a magic-division row where every division has several equally
plausible spellings. A high redundancy score is not sufficient if the row is in a class known to
be spelling-ambiguous.
2026-09-24 11:31:30 -04:00
Christopher Williams 7a93946795 phase11: merge 57 + cookbook 170-171 — 597 bodies / 606 regions, THREE from the milestone
Worker E's 0x8005E17C and 0x8002FAB8; worker F's first two claims 0x800FBE84 (216 B, FIRST
SPELLING with worker A's derivation) and 0x80026274 (108 B).

170 generalises the argument-evidence levers (157/164) into a mechanism: a redundant ENTRY-BLOCK
copy of an argument means that value is still live at a call whose argument setup CLOBBERS that
same register. The copy is materialised in the entry block because the tie to a0's home is
illegal. The test that nailed it: the same body with a 2-arg call is 104 B LENGTH-MISMATCH; with
the 3-arg call it is 108/0. Two prior corpus instances had the copy AT the call; this is the
hoisted-to-entry variant.

171: worker F confirmed EXHAUSTIVELY that the constant-division divisor is unique per magic --
(n*M)>>(32+s) == n/D has exactly one D. So finding 67's identity is not an approximation.
2026-09-24 11:27:41 -04:00
Christopher Williams 696b7dfbfb phase11: cookbook 169 + sf3_family bug fix — 0.96-0.99 is idiom noise, CONFIRMED by raw-word diff
Worker A calibrated sf3_family by checking two 0.97 entries and finding neither shared its
sibling's body. I have now confirmed that on eight candidates by raw-word diff, which is the
decisive test: 0x8006EBA0 vs 0x80028CE0 differs in 60 of 61 words; 0x800FFFEC vs 0x8007E8B8 in
18 of 19; 0x8005E17C vs 0x800FB54C in 25 of 26. Contrast the genuine sibling 0x800F3DC0 vs
0x800F3E18: 1 of 22 words.

So a high cosine with ratio 1.00 is NOT evidence of a shared body -- at 0.96-0.99 the histogram
matches common IDIOMS. The useful band is ratio 1.000 AND a near-zero raw-word diff.

Tool bug fixed: sf3_family did not exclude already-claimed rows, so its top hit was a row
matching ITSELF. The registry is now the authority and claimed rows are skipped.
2026-09-24 11:24:48 -04:00
Christopher Williams c091483083 phase11: merge 55 + cookbook 123 SOLVED + 167-168 — 592 bodies / 601 regions
Worker E's 0x8002311C (160 B) CLOSES COOKBOOK 123'S OPEN QUESTION. Finding 123 recorded the
branchless MAX0 (x & -(x > 0)) as unreached -- 'no ternary and no bitwise spelling reached it'.
Worker E solved it: the lever is NAMING THE BOOLEAN.

  return s & -(s > 0);        -> BRANCHES
  return s > 0 ? s : 0;       -> branches
  flag = s > 0; return s & -flag;  -> EXACT (slt / negu / and)

Mechanism: naming the comparison forces cc1 to materialise it as a VALUE (slt) rather than a
test feeding a branch. That is finding 44's 'name the boolean' lever applied to the MAX half --
finding 44 previously had only the cond-into-&& direction for this family.

167: a 4-byte store cc1 DELETES means the object's address is never taken -- fold the word into
the array whose address IS taken by a call.

168: s = f(); s += f(); s += f(); loses one instruction vs three named results summed.
2026-09-24 11:22:01 -04:00
Christopher Williams db6022c9f7 phase11: merge 54 + cookbook 166 — 590 bodies / 599 regions
0x800F3DC0 (88 B) — a ONE-WORD sibling of the matched 0x800F3E18, found by worker E via
sf3_family at ratio 1.000 and confirmed by raw-word diff: identical in all 22 words except the
COP2 command field (0x4B70000C vs 0x4B78000C). The route was one copy, two renames and one field
change; every __asm__ and register binding carried over untouched.

166 records it, and notes it is the MIRROR of finding 161: on 0x800F3E18 the field 0x178000c was
the WRONG answer (one byte off, 0x170000c correct); on 0x800F3DC0 0x178000c IS correct. A count
tells you a field is COMMON, not that it is right -- and a ratio-1.000 sibling is the cheapest
place to learn which one a row wants. When the family tool reports one, diff the raw words FIRST.
2026-09-24 11:18:58 -04:00
Christopher Williams ecbe17ad1d phase11: merge 52 + cookbook 163-165 — 589 bodies / 598 regions
Worker E's 0x80107DE8 (128 B, maspsx=epilogue) and 0x8007D5FC (132 B, DEFAULT toolchain).

163: a recurring epilogue-list class WITH A SHAPE TELL -- correct length, identical instruction
multiset, and the residual is where cc1's reorg put the EPILOGUE LOADS relative to the last
gp-relative read-modify-write block. The original's epilogue loads FILL the global load's delay
slot; cc1 emits a #nop instead. Tell: the row's last statement is a gp-relative read-modify-write
immediately before the epilogue. NOT a spelling problem -- worker E probed the maspsx mode split
and the nop is a cc1 #nop, not maspsx, so no option changes it. Classify it: post-pass territory.

164: a register residual can be ARGUMENT EVIDENCE -- when the only residual is a value in an
argument register and there is no argument setup at the jal, try passing it as that argument.

165: finding 147 confirmed a second time -- 0x8007D5FC is on the epilogue list but cc1 fills its
own slot, so the token is a no-op and the row is claimed with '-'. The list was selected on the
ORIGINAL's tail; the token must be decided from the CANDIDATE's.
2026-09-24 11:12:17 -04:00
Christopher Williams a74bc32306 phase11: merge 49 + cookbook 162 — 586 bodies / 595 regions
Worker A's final row 0x8010A6C4 (132 B, first attempt, maspsx=epilogue) -- its ninth epilogue
row and its 46th claim.

162: a callee called with DIFFERENT argument counts needs a NON-PROTOTYPE declaration --
func_8010A444(1) / (2, x) / (3, s1, s0) is only expressible as 'void func_8010A444();', the C89
empty-parameter form, not '(void)'. Same constraint that cost worker A a compile on 0x8002DD14.

Worker A's final totals: 46 claims (33 first-attempt), 95 evidence rows, 39 levers, 3 deferred
rows with derivations, 1 blocked row, 9 rows carrying maspsx=epilogue.
2026-09-24 11:05:36 -04:00
Christopher Williams bec136559a phase11: merge 48 + gtemac lwc2/swc2 + cookbook 159-161 — 585 bodies / 594 regions
Worker D's 0x800F3E18 (88 B) -- THE FIRST GTE/COP2 ROW MATCHED IN THIS PROJECT.

159: lwc2/swc2 move a word straight between MEMORY and COP2, unlike mtc2/mfc2 which move
between a GPR and COP2. The row uses lwc2 $9/$10/$11 and swc2 $25/$26/$27, so a row can use
the IR/MAC registers WITHOUT the IR/MAC macros. Added gte_lwc2IR1/2/3 and gte_swc2MAC1/2/3.

160: register variables PIN the COP2 operand registers -- worker D's entire residual was that
cc1 chose its own cfc2/mfc2 destinations. The GTE analogue of the named-locals family: an
inline-asm row's residual is usually the operand REGISTERS, not the sequence.

161 IS A CORRECTION TO THE COORDINATOR'S OWN ADVICE. I broadcast the command-field values with
their occurrence counts as if they were a lookup table. They are a DISTRIBUTION, not a per-row
answer: worker D wrote 0x178000c (counted 51x) into the row and it came out ONE BYTE wrong; the
correct field is 0x170000c. The low bits carry the shift/matrix/vector selectors, so two commands
differing only there are different instructions. Read the field off the ORIGINAL WORD.
2026-09-24 11:03:04 -04:00
Christopher Williams f27691f6c3 phase11: merge 47 + cookbook 158 — 584 bodies / 593 regions
Worker A's 0x800F4B88 (128 B, first attempt) -- its eighth epilogue-class row and its last.

158: two type views over the same halfwords are DELIBERATE. The first helper call loads with lh
(signed) and the second with lhu (unsigned) over the SAME pointer, so the source declared a
short* view for one expression and an unsigned short* view for the other. Writing the whole row
as short* gives lh for the second call too and changes the bytes. When one function reads the
same field both ways, the mixed lh/lhu pair over one pointer is the evidence.
2026-09-24 11:01:49 -04:00
Christopher Williams eb4b23b219 phase11: merge 46 + cookbook 155-157 — 584 bodies / 593 regions
Worker A's three epilogue rows (0x800F452C, 0x800F6DD0, 0x800F6E50).

155 is a DISPATCH finding: the epilogue list is ALSO a family list. 0x800F6DD0 and 0x800F6E50 are
siblings differing in exactly two ways, and worker A read one and got the second for free, both
first try. Adjacent pairs already identified: 0x800F6DD0/0x800F6E50, 0x800F42AC/0x800F452C,
0x800FFFEC/0x80100038. A worker taking an epilogue row should read its NEIGHBOURS first -- the
class was selected on a TAIL SHAPE, and tail shape correlates with the translation-unit layout
that makes neighbours siblings. Generalised: any class selected by a structural feature clusters
its results by address.

156: the three writes are ASSIGNMENTS not accumulations -- the original never loads the old
destination value, so writing += adds three loads.

157: fewer argument registers set than parameters means the source passes its OWN LIVE parameters
directly. Now confirmed on three rows.
2026-09-24 11:00:24 -04:00
Christopher Williams bc05792bcb phase11: merge 45 + cookbook 154 — 581 bodies / 590 regions
Worker A's 0x800F452C (112 B, maspsx=epilogue, second attempt) -- a sibling of its own
0x800F4098, matched with the mid-function-branch-target lever applied first try.

Worker A asked FIVE TIMES for the lui-page rule to be prominent, having made the mistake five
times. It is now cookbook 154 and the FIRST of the five things the workflow doc tells a new
worker, with all five instances tabulated. The fifth instance added the missing half: the
immediate is a SIGNED DISPLACEMENT, and the signature of the error is 'a residual of ONE
differing byte whose only difference is a lui or addiu immediate'.

Also confirmed from worker A's side: the shape A/B correction works -- 0x800F452C is a shape-B
row and closed with the single token, so the tail filter is obsolete and A has dropped it.
2026-09-24 10:56:40 -04:00
Christopher Williams 57c1cd22f2 phase11: merge 44 + cookbook 151-153 — 580 bodies / 589 regions
Worker A's 0x800F4098 and worker D's 0x800FB54C (104 B, first attempt, maspsx=epilogue).

151: the 2^k-1 add-back rule is CONFIRMED on two independent divisors -- worker C derived it
from 63 (0x800FEE3C) and worker D found it again on 127 (0x800FB54C, magic 0x81024409). Same
structure, two divisors, so finding 67's decision table is complete and not hypothesised.

152: FIVE finders each produced bodies over worker D's 20 -- redundancy rank 6, size rank 5,
adjacency 4, epilogue class 2, constant-division census 1, family 1. No single finder dominates.
This broadens finding 109: 'five different finders each produced bodies, and the price was set
by the LEVER, not the finder.' The tools cover different parts of the population, so keep every
finder running rather than consolidating onto the current best.

153: a saved register can force a local to be SMALLER than the data written through it, and
enlarging it to fix that breaks the frame.
2026-09-24 10:55:29 -04:00
Christopher Williams 290baa2a17 phase11: merge 43 + cookbook 147-150 — 578 bodies / 587 regions
Worker E's first four claims (0x80028CE0, 0x80028C34, 0x8009D798, 0x80091674).

147 IS A CORRECTION TO THE COORDINATOR'S OWN BROADCAST. I sent workers a 120-row epilogue list
selected by scanning the ORIGINAL's tail. Worker E showed that is not sufficient: 0x80091674 has
that exact tail shape but cc1 FILLS the slot itself, so the default toolchain matches (104 B) and
--fill-epilogue BREAKS it (100 B LENGTH-MISMATCH). The mode must be decided per row by compiling
and reading the CANDIDATE's tail. Diagnostic: 4 bytes SHORT with the mode on means the candidate
was already correct.

148: order and allocation are SEPARABLE -- the la position and the addu destination are two
independent facts, and the fix is to split the base into its own named local. Three spellings
with exact results.

149: a body 4-8 bytes SHORT with MISSING load-delay nops means a later independent block must
move earlier in the source -- the opposite tell from finding 100.

150: worker E hit a RACE DUPLICATE on 0x80100038 (free.sh read a registry 6 rows stale),
restored HEAD's file verbatim, re-verified it, dropped the row, and reported the incident.
Nothing corrupted because both spellings match -- but it proves the protocol's window is real.
2026-09-24 10:53:50 -04:00
Christopher Williams 150e672b5a phase11: merge 42 + cookbook 144-146 — 574 bodies / 583 regions
Worker D's 0x800FAF84 (104 B), its first maspsx=epilogue match.

144: THE EPILOGUE CLASS NEEDS ONLY ONE TOKEN. Worker A asked for a second one; it does not need
it. The 120 rows split into two shapes -- A) lw $31 immediately before the release, which needs
the release moved AND a nop inserted after lw $31; B) other loads in between, where the release
moves and the trailing nop is DROPPED. My first implementation did A only and left every B row
4 bytes long. Verified on both: 0x800FFBEC (80/0/MATCH) and 0x800F44D0 (92/0/MATCH, a row worker
A had released as unfixable).

145: read the frame arithmetic and the saved-register offsets TOGETHER -- worker D's local had to
be 8 bytes not 12 because the saved s0 sits at sp+24 and the callee writes through sp+16. Third
instance of the size family, first where the constraint came from a saved register.

146: the SAME expression at two divisors produces two unrelated code shapes (/64 branchy bias vs
/63 add-back magic), which is why worker D's divisor sweep missed it.
2026-09-24 10:52:37 -04:00
Christopher Williams d0384a6bca phase11: THE GTE TOKEN SHIPS — include/gtemac.h gains $8-$12, MAC, and a generic gte_cmd()
Finding 122 declared GTE rows a blocked class needing a harness token. The gap was smaller than
it looked: the header already covered $0-$7 and $13-$31 but NOT $8-$12, which is where
IR1/IR2/IR3 ($9/$10/$11) live, and it had no macro for the GTE command instruction itself.

Added gte_ldIR1/2/3, gte_stIR1/2/3, gte_ldMAC1/2/3, gte_stMAC1/2/3, and a GENERIC gte_cmd(field)
so any command whose 25-bit field has been read off the original can be emitted without first
earning a semantic name.

VERIFIED, NOT ASSUMED: the field values are confirmed by counting them over the whole binary
(0x486012 x51, 0x49E012 x11, 0x41E012 x4) and a test compilation emits gte_cmd(0x486012) ->
cop2 0x486012 -> 0x4A486012, exactly the original's word.

Five rows were blocked on this across three workers, all with complete or partial derivations.
The disposition matters as much as the token: three workers independently reached 'no amount of
spelling will find this' and declared it BLOCKED rather than grinding -- which is what made the
gap visible as a TOOLING problem instead of three separate source puzzles.
2026-09-24 10:45:33 -04:00
Christopher Williams 4e4afccdc9 phase11: cookbook 141-142 — a COP2 false positive, and C closes D's open question
141: worker D's own reads_unsaved_saved scanner flagged 0x80103434, D read the row, and the
verdict is NOT a fragment -- the detector treats op 0x12 (COP2) as a GPR use, which for
ctc2/mtc2/mfc2 is wrong. Every COP2 row in that flag list is suspect. That is the THIRD
independent instance of the same lesson: every shape heuristic in this project has needed a
worker to read a flagged row and say 'this is legal, and here is why'.

142: worker C's 2^k-1 add-back rule CLOSES worker D's open question on 0x82082083. D recorded it
as a bounded negative with a named direction; C recognised the answer from an unrelated row.
The third time a worker's finding closed another worker's negative -- the strongest argument for
recording a named open question rather than a vague failure.
2026-09-24 10:44:18 -04:00
Christopher Williams 05be974ce2 phase11: THE EPILOGUE POST-PASS SHIPS (maspsx=epilogue) — 565 bodies / 574 regions
Finding 84 named the transform; it is now implemented and 0x800FFBEC matches (80 B, 0 differing)
where it was 6 differing bytes without it.

IT IS A SWAP, NOT A MOVE, and getting that wrong cost one implementation: the candidate is
lw $31,16(sp) / addiu sp,sp,24 / jr $31 / nop and the original is lw $31 / nop / jr $31 /
addiu sp,sp,24 -- SAME instruction count, two words swapped. My first version moved the release
after the jump and dropped the nop, producing 3 instructions instead of 4 and turning an 80-byte
row into a 76-byte LENGTH-MISMATCH. A 'small mechanical transform' still has to be checked
against the bytes.

SCALE: 120 unclaimed rows have the filled epilogue in the ORIGINAL (scanned every worklist row's
tail for jr $31 followed by a positive addiu sp,sp,N). They are mostly SMALL -- 76, 76, 80, 92,
92, 96, 104 B -- so this is a large class of cheap rows that were blocked on a HARNESS GAP rather
than on source shape. 770 other rows have the unfilled shape and need nothing.

The tracked patch is regenerated and verified to reproduce both modified maspsx files from the
pristine checkout.
2026-09-24 10:42:29 -04:00
Christopher Williams 26a917806a phase11: merge 38 + cookbook 131/138-139 — 564 bodies / 573 regions
Worker D's 0x80025A2C (176 B, 2 spellings) -- the EXACT MIRROR of its own 0x80025ADC.

131 is now THREE instances with an identical mechanism (88->96, 48->56, 56->64, always a clean
8-byte frame deficit with everything else identical, always fixed by an unreferenced array
local). It is a rule with a one-line fix, not a trick.

138: a MIRROR PAIR -- the two rows are inverse conversions, adjacent in the image, both callees
of 0x80031BBC. Finding one made the other a two-spelling row. sf3_family cannot see this relation
because inverses are not similar: their opcode histograms DIFFER (one stores where the other
loads). A pair of inverse functions has a STRUCTURAL signature, not a similarity one.
2026-09-24 10:38:55 -04:00
Christopher Williams 686e906b97 phase11: merge 37 + calibrate sf3_family + cookbook 136-137 — 563 bodies / 572 regions
Worker A's 0x80036F70 (460 B, first attempt, family score 1.000 AND adjacent to its own
0x80036DA4). Its family run finished 7 for 7 with five first-spelling matches.

136: worker A CALIBRATED the family tool. It checked the two 0.97-scoring entries and NEITHER
shares its sibling's body at all -- one is a table-allocation routine, the other a summing
loop. '1.000 is the useful band; below ~0.99 the histogram is matching common idioms, not
bodies.' That is the same false-positive mode as the redundancy ranker (finding 110). The
default threshold is now 0.99.

137: a family's signature can be a CONSTANT TRIPLE -- worker A's 0x80036F70 differs from its
sibling only in six constants, whose signature is (A, A+12, A-58). Searchable in a way no
similarity metric can be, because the shapes are identical and only the immediates differ.
2026-09-24 10:37:35 -04:00
Christopher Williams c423cf12d5 phase11: cookbook 132-135 — a stated-direction layout rule, the family's limit, and a negative
132: worker B found the SECOND independent instance of 'when the original's short path is the
fall-through, INVERT the condition' (30 bytes of layout on 0x800A8984; the same shape as its
own 0x800FCA90). That promotes it from a heuristic to a rule with a stated direction -- and it
is the opposite of the usual instinct to write the guard as an early-exit.

133: worker A's one-byte family residual was a DECLARATION -- 'int i' emits slt where 'unsigned
int i' emits the original's sltiu. The family transfers the SHAPE and the LEVERS; the
declarations must still be re-derived.

134: a family hit is also a hint about the CALLEE -- the relation crosses the call graph, and
sf3_family does not model it. Two of worker A's family rows call rows that are themselves
unclaimed with the same object layout.

135: worker A predicted a fourth family member by pattern; I scanned all 1046 unclaimed rows for
the predicted bases and ZERO reference them. The family has exactly three members. A predicted
member that does not exist is worth recording so nobody re-derives the search.
2026-09-24 10:36:26 -04:00
Christopher Williams 9ff344834c phase11: cookbook 130-131 + document the ranker's size bias
130: worker D found the ranker's top is SIZE-BIASED -- redundancy and size are correlated because
a bigger body has more chances to repeat a 3-gram. Its top was 3288 B at 0.91 while the rows it
was matching sat at 0.64-0.74 in the small tail. The metric is not wrong about rows of equal
size; the raw score just cannot be compared across bands. Since the milestone counts BODIES, a
3288 B row and a 248 B row are worth one body each and the large one costs many times the
context. Worker D's effective filter was redundancy PER UNIT SIZE, now approximated by
--max-size, which is documented in the tool.

131: an unreferenced ARRAY local homes but an unreferenced SCALAR does not -- second independent
instance, identical mechanism, so it is a rule: when the frame is a clean multiple of 8 bytes
short and everything else is identical, add an unreferenced array local of that size.
2026-09-24 10:31:23 -04:00
Christopher Williams bc4c046625 phase11: merge 34 + cookbook 127-129 — 556 bodies / 565 regions
Worker C's 0x8009F4B4 (248 B) and 0x80068874 (156 B), both first attempt.

127 CLOSES WORKER D'S OPEN QUESTION. D left 0x800FEE3C's magic 0x82082083 unexplained; worker C
solved it and the answer is a general rule: the divisor 63 is of the form 2^k-1, which is why
cc1 uses that magic with an ADD-BACK (mfhi; addu; sra 5) instead of a plain shift. An add-back
magic is the tell for a 2^k-1 divisor, NOT for a large one. Finding 67's decision procedure is
now complete: no mflo -> constant division D = 2^(32+s)/M; mfhi+addu+sra -> a 2^k-1 divisor;
mfhi AND mflo -> a genuine 64-bit multiply.

128: worker C classified a division-by-constant row on decode WITHOUT attempting it, because
'every division expression has several equally-plausible spellings, so it is idiom-redundant by
construction'. That characterises the ranker's false-positive class from the SOURCE side for the
first time -- exactly the class finding 110 showed cannot be separated by operand comparison.

129: adjacency is now 9-for-9 across three workers (A 3/3, C 5/5, D 1/1).
2026-09-24 10:30:10 -04:00
Christopher Williams c12d206078 phase11: ledger RULE fix (worker A) + retire the roving list
Worker A found that last-row-wins makes an unconditional 'released' from a worker who never
held the row WRONGLY FREE IT from whoever does. A found two addresses held as wip by worker C
and correctly re-appended C's wip row rather than its own released -- had it not, C's rows
would have been silently released and both workers could have started them.

New rule: only append 'released' for an address you yourself appended 'wip' for. Order is
check (range-aware) -> if free append wip -> work -> append your own released.

Second finding from the same episode: the roving list I gave worker A deliberately overlapped
the other partitions and its first two picks were both already held. A shared queue is only
worth it when the work is NOT already partitioned. Once the partitions were re-ranked on
global redundancy, the roving list was strictly worse than a worker's own slice, so it is
retired. That is the fifth defect found in a coordinator-written rule this phase.
2026-09-24 10:29:04 -04:00
Christopher Williams 81d3ffb5b9 phase11: merge 33 + cookbook 125-126 — 554 bodies / 563 regions
Worker D's 0x8009F890 (248 B, first attempt) -- the THIRD member of a family it had already
matched twice, and the three were found by three different means: the size ranker, adjacency,
and the rebuilt global-redundancy rank. 'The finder varies, the price does not.' The
operational conclusion: families should be SEARCHED for explicitly rather than waited for.

126: worker D withdrew a named direction after checking its own notes and finding it had
already been tested and made the row worse. It declined a fifth spelling on a falsified lever
and corrected the row's record to the honest state. A direction that has been tested and
failed must be struck, or the next worker inherits a false lead.
2026-09-24 10:28:48 -04:00
Christopher Williams 34ffbad9ad phase11: cookbook 123-124 — a counter-intuitive clamp lever, and a confound in my own partition design
123: a 'clamp to zero' written as a BITWISE MASK (x & (x >> 31)) compiles branchlessly while
the same thing as a TERNARY branches -- the opposite of the intuition. Worker B's MIN half now
matches exactly with the bitwise form. The MAX half (branchless slt/negu/and, i.e. x & -(x>0))
remains UNREACHED by any ternary or bitwise spelling, with a plausible SDK min/max macro as the
source. Recorded as a named open question.

124: worker B found that the partition design CONFOUNDED the size/redundancy measurement. The
partitions were rank-interleaved by the original worklist order (tier, size, address), not by
redundancy, so 'my <=200 B hit rate was high because my slice happened to be redundancy-rich,
not because small rows are inherently easy'. The within-worker evidence for 'cost is redundancy'
stands (A: 548 B first-attempt vs 176 B nine failures), but any CROSS-worker band comparison was
measuring the partition, not the rows. Fixed by re-partitioning on global redundancy. General
lesson: when work is divided among workers, any per-worker statistic is contaminated by the
division.
2026-09-24 10:25:21 -04:00
Christopher Williams bac9ab0d89 phase11: merge 30 + cookbook 120-122 — 550 bodies / 559 regions
Worker A's 0x800689DC and worker C's 0x8009F4B4.

120: worker B's justification for why the ranker works -- 'the allocator makes copies
non-identical, so OPCODE repetition survives while WORD repetition does not'. That is exactly
why finding 110's full-word metric failed and why the opcode metric works. A repeated source
block produces the same opcodes with different registers; requiring operands to match destroys
the signal rather than sharpening it.

121: the filled-delay-slot class has TWO sub-cases with DIFFERENT fixes -- reorg fills the slot
(source-shape hunt) versus maspsx mode changing WHICH instruction lands in the slot (a harness
token choice). Same diagnostic, different remedy. Check whether toggling maspsx changes the
fill before hunting a source shape.

122: NEW BLOCKED CLASS -- a GTE coprocessor body needs a harness token, not more spellings.
Worker B's 0x8001FAFC reads mfc2 $12/$13/$14 and branches on t7/s6 which are NOT the o32
argument registers, so the inputs arrive through a non-standard convention. Team rule: if a
body contains mfc2/mtc2, do not spend spellings on it -- these are tooling-blocked rows to be
worked as a batch once a token exists.
2026-09-24 10:24:53 -04:00
Christopher Williams e2bdada67b phase11: merge 29 + cookbook 105/119 — 548 bodies / 557 regions
Worker D's 0x80106AA8 (136 B, first attempt) -- found by the REDUNDANCY filter, not
adjacency, which is the first row where the ranker did the finding alone. Eight stores
through four global pointers, each re-materialised per store.

Cookbook 105's dial now has THREE measured settings: per statement (0x8006BC74 46x and
0x80106AA8 8x, both matched), once per block (matched), once per function (does not match).
So per-statement re-reads are the NORMAL shape, not an extreme.

119: worker D ran the fragment check, called 0x80058BA0 a confirmed fragment, then
SELF-CORRECTED -- it is legal, because in o32 a frameless leaf may both read and write the
caller's outgoing argument area (sp+0..sp+31). All three of D's suspects are legal. Worker B
found the read side, worker D the write side, and both had to read the row to do it: a
heuristic keyed on shape must state its exclusions, and only the worker reading the row can
find them.
2026-09-24 10:23:08 -04:00
Christopher Williams 71aa4a2bc2 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.
2026-09-24 10:20:47 -04:00
Christopher Williams fc7ebc4b2d phase11: merge 28 + cookbook 115 — 547 bodies / 556 regions
Worker B's 0x80050CA8 (120 B, first attempt).

Lever: the status word is masked by TWO separate statements (&= -3; &= -5;), and the original
emits one load, two ands against two different constants, one store. Combining the masks
folds to a single and and LOSES an instruction -- the same principle as finding 81 (a slot
stored twice is two statements) applied to read-modify-write. Companion: the status load is
hoisted above nine halfword clears, so the clears' source order is only observable through
the store order.
2026-09-24 10:20:18 -04:00
Christopher Williams 46c260c252 phase11: worker B's adjudication makes the fragment check DISJOINT — 0 of 555
The first version of the fragment check fired on any nonzero sp offset and flagged 2 of the
555 registered regions. Worker B read its own hit (0x800B704C) before committing and showed
it is a LEGAL FRAMELESS LEAF WITH EIGHT ARGUMENTS: in o32 the callee's sp is unchanged at
entry, so sp+16..sp+28 IS the caller's outgoing area -- arguments 4-7 -- and reading it
before any addiu sp,sp,-N is exactly what a frameless >4-argument leaf looks like. Its
evidence: exactly one jr ra, zero jal, zero addiu sp,sp,-N, zero sw ra/lw ra across all 324
bytes, and no callee-saved register touched.

Excluding the incoming argument area (sp+0..sp+31) and flagging only a negative offset or an
offset beyond the 8-argument area makes the check DISJOINT:
  registered regions flagged:  2 of 555  ->  0 of 555
  suspects across 4 partitions:  5  ->  1
The one remaining suspect is worker A's 0x800C3490.

This is the cleanest example in the phase of a worker ADJUDICATING a tool's output rather
than obeying it -- B was explicitly told 'advisory, do not skip', read the row anyway, and
its adjudication turned a noisy heuristic into a precise one.
2026-09-24 10:18:50 -04:00
Christopher Williams 74199d1ab3 phase11: tools/sf3_rank --fragments + cookbook 114 — worker A's fragment anomaly
Worker A found 0x800C3490 is not a matchable body: it starts mid-expression with sw v0,32(sp)
before any frame setup, and its identical tail also appears at 0x800C3470, so it is a
shared/jump-target block Ghidra promoted to a function -- inside no region, with the code
before it in no worklist, so nobody can match it standalone.

Its generalised rule is narrower than 'first instruction is not prologue-like', because a
function may legally start with beq/sh/move: a row is a FRAGMENT if its first instruction
touches the stack before any addiu sp,sp,-N, reads a stack slot, or uses a callee-saved
register that is never saved.

Implemented as a --fragments scan. Measured: 5 suspects across all four partitions, but 2
false positives across the 555 REGISTERED regions, so it is ADVISORY not an exclusion --
sufficient-but-not-complete like the trapping check. A hit means read before spending a
spelling, never skip.
2026-09-24 10:17:38 -04:00
Christopher Williams e4b6423774 phase11: cookbook 111-113 + range-aware registry check — the third defect in a coordinator rule
111: $sp cannot be moved from C, so a stack switch is INLINE ASM and the statement SPLIT is
byte-load-bearing -- seven separate __asm__ volatile statements with the call between them,
and the nop in each jal's delay slot falls out of the following statement being a compiler
barrier. One asm block, or a register int sp, does not reproduce it.

112: an intermediate that must live in MEMORY (the original reloads it before each of three
calls; a scalar local gets register-allocated and loses 8 bytes of frame); the chained
assignment's store order; and finding 100's then/else diagnostic confirmed on a new row.

113: a region's END address is EXCLUSIVE, so the registry free-check must be a containment
test, not a string match. Worker A was wrongly blocked on 0x8006B7C0 because it is the
exclusive end of 0x8006B778's range. This is the third defect found in a coordinator-written
rule this phase; the workflow doc now requires a range test.
2026-09-24 10:16:34 -04:00
Christopher Williams f14744e76c phase11: merge 27 + cookbook 109-110 — 547 bodies / 556 regions
Worker D's 0x800307FC (92 B) and 0x80031EBC (112 B), both first spelling by adjacency.

109 records worker D's calibration claim -- 'adjacency finds the ROW, redundancy predicts the
PRICE' -- and the harder discipline behind it: D read 0x8006C044, identified it as a
tie-break-dense 3D-maths routine, and RELEASED it in favour of two small adjacent rows that
together cost less context than a first draft and returned two bodies instead of zero-to-one.

110 records a NEGATIVE RESULT from the coordinator. Worker C found a real false positive (the
ranker's top row is tie-break-dense, its score inflated by a repeated multu/mflo/sra idiom)
and proposed comparing full instruction words instead of opcodes. I implemented that and
measured it: it scores two KNOWN matches at ZERO and the known false positive HIGHEST. The
reason is fatal -- a genuine repeated source block does not produce identical instruction
words across copies because the allocator assigns different registers, so 'same opcodes,
different operands' describes a repeated block and a repeated idiom equally well. They are
indistinguishable at the instruction level. The opcode metric stays.
2026-09-24 10:16:20 -04:00
Christopher Williams 17e3b4496f phase11: pin the ranker's statistic + cookbook 107-108
Worker B's comparability caution: the redundancy score is the MAXIMUM of the 2/3/4-gram repeat
ratios, so a high score means 'some length scale is very repetitive', not 'repetitive at every
scale'. Any implementation using a mean or a different normalisation gives non-comparable
numbers, which matters because workers were sharing rankings across partitions. Pinned in the
tool's docstring with this tool named as the reference implementation.

107: finding 43's goto lever is NECESSARY BUT NOT SUFFICIENT -- worker B found it overshoots
(152 vs 140) on 0x800FCA90, and this is the second independent instance after worker A's
0x800256F0. Treat it as one attempt, not as the fix.
2026-09-24 10:14:56 -04:00
Christopher Williams 9adcdf5529 phase11: the inflight ledger needs a RELEASE state (worker A's finding)
Worker A appended three rows optimistically, classified them as near-matches, and then had
no way to clear them -- because the ledger was append-only with no terminal state. Every
other worker would have skipped three free rows.

Fixed: a status column (wip / released) where the effective state of an address is its LAST
row, and a rule that a worker must append 'released' when it stops. Worker A's three rows
are released.

The general lesson is recorded in the workflow doc: a write-ahead log needs a TERMINAL
state, not just an opening one, or the log itself becomes the stale data it was meant to
prevent. Any append-only coordination file needs a way to say done.
2026-09-24 10:11:31 -04:00
Christopher Williams f89e46ad88 phase11: cookbook 105-106 — re-read granularity as a tunable; filter determines failure class
105: the pointer re-read granularity is a DIAL, measured in both directions by worker D --
re-read per store (700 B row, 46 times, matched), once per block (276 B row, matched),
per statement (80 bytes too long), and never (does not match). Cause is aliasing. It is the
same property as finding 45's named-locals family but as a COUNT rather than a yes/no.
Plus: a genuinely uninitialised read in the original must be preserved, not corrected.

106: which failure class a row lands in depends on the FILTER, not the band. Worker D's
cheap rows fail on frame/combiner/allocation/batch-shape and never on the branch
diagnostics, so those belong on tie-break-dense rows. Route a diagnostic to the row shape
it matches rather than broadcasting it.
2026-09-24 10:09:16 -04:00
Christopher Williams 6b7239d83d phase11: merge 24 + cookbook 104 + workflow protocol — 542 bodies / 551 regions
Worker A's 0x80033DC8 (360 B) and 0x8006A98C (132 B), plus two gp symbol rows
(D_80122724, D_80122728) that unblock 0x800A4CA8.

PROCESS DEFECT FOUND AND FIXED. Worker C and worker D both matched 0x800320D8
independently and D overwrote C's source file. Nothing corrupted -- both spellings match
and the region still reports 276/0/MATCH -- but one worker's effort was duplicated. The
partitions are genuinely disjoint (273/279/278/271, union 1101 = sum), so there was NO
assignment error: the gap was that no worker could know another had started a row, since
the registry only knows about MERGED claims and both started before either merged. The
root cause is the adjacency rule (cookbook 99, 4-for-4) crossing partition boundaries --
the best dispatch heuristic found so far invalidated the assumption the assignment rested on.

Fix: .run/p11/inflight.tsv (write-ahead log alongside the merge registry's commit log),
with the protocol written up in docs/ORCHESTRATOR_WORKFLOW.md so the next orchestrator
inherits it.
2026-09-24 10:07:56 -04:00
Christopher Williams 73b706e667 phase11: merge 22 + cookbook 99-102 — 538 bodies / 547 regions
Worker A's 0x800556E8 and 0x80055654 (both first/second attempt).

Cookbook 99 is a DISPATCH rule, not a codegen one: take the row ADJACENT to one you just
matched. The binary is laid out by translation unit, so neighbours share the author's habits.
3 for 3, all first or second attempt, and it beat both the size ranker and the LRS ranker.

Cookbook 100 puts the three branch-shaped diagnostics side by side -- each maps a residual
shape to exactly one cause and each is a glance rather than a spelling:
  branch displacement words only -> block NESTING (95)
  first few instructions, right length -> then/else ORDER of a single-statement arm
  whole prologue, same multiset -> declaration vs assignment order
Vector copies are now confirmed on FIVE independent rows.
2026-09-24 09:51:10 -04:00
Christopher Williams 2472e2e2c1 phase11: merge 21 + cookbook 95-98 — 537 bodies / 546 regions
Worker A's two adjacent claims (0x80036B14, 0x80036DA4).

Cookbook 95 is the cleanest diagnostic of the phase: a correct-length candidate whose residual
is a handful of BRANCH WORDS means the block NESTING is wrong, not the code inside the blocks.
Worker A got exactly 656 bytes (correct length) with exactly 2 differing bytes, both branch
displacements, by writing two guards as siblings instead of nested. Residual = 2 bytes at a
branch displacement => go look at your braces.

Also: the project's 4-int vector type is identifiable from the frame (multiple of 16 with
offsets stepping by 16); vector copies are struct assignments (third independent confirmation);
and an OPEN question is recorded -- 'the original spills everything, cc1 promotes' -- with a
request for a recipe from any worker who has solved it.
2026-09-24 09:49:26 -04:00
Christopher Williams a1c41771e7 phase11: merge 19 + cookbook 92-94 — 535 bodies / 544 regions
Worker B's four first-attempt claims (0x800B255C, 0x8004857C, 0x80030858, 0x800909D8).

Cookbook 94 is the strategic one: worker B's failures cluster into exactly TWO mechanical
classes -- reorg slot-fill choice and rare-epilogue fill -- and neither is a shape problem.
Both are the post-pass family, which two workers have now independently arrived at and
stopped on. That is the strongest argument yet for writing the post-pass rather than
grinding these rows with source spellings.
2026-09-24 09:46:48 -04:00
Christopher Williams 2c3f5a33a5 phase11: cookbook 89-91 + gp symbol row D_80122464 — 531 bodies / 540 regions
Worker D's most transferable finding yet: the ADDRESS SYMBOL is what selects the addiu form.
A literal (int)0x8013F9B8 gives lui+ori; &D_8013F9B8 gives lui+addiu. So 'ori where the
original has addiu' means the source used a literal where it should reference the address
symbol -- a 40-byte error that presents as a LENGTH mismatch, which is why it reads like a
codegen problem. Extends findings 4/46.

90: a (gp)-relative access to an unregistered address is a SYMBOL REQUEST, not a source
problem -- the harness derives gp-ness only from config/symbols.tsv and no CLI option adds
it. Worker D verified its row by pointing --symbols at a scratch copy of the registry.

91: a real source-order quirk (two successive call addresses swapped) is preserved in a
match and is not a transcription error.
2026-09-24 09:44:33 -04:00
Christopher Williams e7e1ce9d30 phase11: merge 18 + cookbook 87-88 — 530 bodies / 539 regions
Worker A's 0x8009C904: 548 bytes, matched on the FIRST spelling. Cumulative evidence for the
redundancy ranker is now 548B/1st, 248B/3 spellings, 1232B/2, 700B/3 -- against 176B/9
failures for a tie-break-dense row.

Cookbook 87 is the important negative: cc1 does NOT unroll a constant-trip-count loop (the
for-loop form is 212 B against the original's 780 B), so whenever an original is unrolled the
SOURCE is unrolled too. That explains why the >800 B band is full of cheap rows -- those
bodies are unrolled in the source, and an unrolled repetitive body is exactly what the
ranker scores highest.
2026-09-24 09:43:12 -04:00
Christopher Williams 6862af1d0b phase11: merge 17 + cookbook 84-86 — 526 bodies / 535 regions
Worker B's 0x80069580 (88 B) and 0x8007E7FC (96 B), plus two gp symbol rows
(D_80122168, D_801221D0).

Cookbook 84 is the harness row for the post-pass: worker B isolated the rare-epilogue
transform exactly (move the frame release into the jump slot AND insert the load-delay nop
after lw ra), and established the load-bearing detail that as will NOT perform this fill
because doing so would put jr ra in the lw ra load-delay slot. So a post-pass that merely
moves the release into the slot produces wrong code. Also measured: maspsx=off is WORSE on
this row (72 bytes) because it strips nops from the beqz/jalr slots the original keeps, so
the two mechanisms are not substitutes.

85: cc1 folds SYM+N into a single la and SIX spellings do not defeat it.
86: cc1 cross-jumps identical guards; goto to a shared return label is the named lever.
2026-09-24 09:41:56 -04:00
Christopher Williams 6fdcaf3740 phase11: merge 16 + cookbook 83 — 525 bodies / 534 regions
Worker C's 0x800320D8 (276 B), matched on the FIRST spelling where its sibling 0x80031FC4
took 5 -- the family lever measured, on one family, both ways. Finding 55's limit confirmed
on the same family: a third row calling the same callee is NOT the same body and sits at
+16 instructions. The family transfers the derivation method and the stable positions,
never the body.

Also recorded: an OR nested inside an && chain is observable from the branch DIRECTIONS --
bne to the call block on one test and bnez to the manual-copy block on the other is
if (x == 0 && (a != 6 || b == 0)) call; else manual;
2026-09-24 09:40:40 -04:00
Christopher Williams c22ef879e8 phase11: merge 15 + amend cookbook 67, add 82 — 524 bodies / 533 regions
Worker D's 0x800910BC (280 B), its 8th match.

TWO CORRECTIONS TO THE COORDINATOR'S OWN COOKBOOK ENTRY, both from measurement:
 - 67 was INCOMPLETE and cost worker D a spelling. The magic alone is AMBIGUOUS: D = 2^(32+s)/M
   where s is the shift of the sra after the mfhi. 0x2AAAAAAB is /6 at s=0, /12 at s=1, /24 at
   s=2, and worker D read it as /6 when the shift was 1. The corollary is worth having too: the
   same magic twice in one function is not a contradiction (0x66666667 serves both /10 at s=2
   and /5 at s=1, materialised once into a callee-saved register).
 - The named-local rule is PER-SITE within one function. Naming a result the original consumes
   immediately costs 2 words; naming one the original reuses is free. Apply the decision once
   per VALUE, not once per function.

That is now the fourth correction to coordinator work this phase, and every one came from a
worker measuring something the coordinator had asserted.
2026-09-24 09:39:25 -04:00
Christopher Williams 1a6a00970f phase11: merge 14 + cookbook 79-81 — worker A's redundancy ranker
Worker A built a repetitiveness score (repeated 2/3/4-instruction opcode subsequences,
normalised by body length) and produced the cleanest controlled comparison in the phase:
3 spellings on a 248 B repetitive row vs 9 failures on a 176 B tie-break-dense one. That
converts 'prefer a repetitive body' from a hunch into a sortable number, so size is
deprioritised as the ranking signal.

Also recorded: a transposed temp array is byte-required (int m[3][4] used as m[c][r]) with an
exact diagnostic -- right length + right instruction multiset + residual only on sp-relative
offsets means the frame LAYOUT is wrong, not the code; and when the original stores the same
slot twice, suspect two source statements rather than a scheduler quirk (GCC 2.7.2 has no DSE).
2026-09-24 09:38:05 -04:00
Christopher Williams 61be53994b phase11: merge 13 + cookbook 73-78 — 522 bodies / 531 regions
Worker C's 0x80031FC4 (276 B). Cookbook gains six entries, the most important of which is
worker C's correction of the COORDINATOR: a DEPENDENT row is one you cannot VERIFY, not one
you have MATCHED. C's 0x800A613C and 0x800FD120 had symbol rows outstanding, but
re-verifying against the tracked registry gave byte-identical results to the overlay runs --
both are still near-matches blocked on an ALLOCATION lever. Adding a symbol row unblocks the
verification, not the match; conflating the two would have had a worker stop working a row it
had not solved.

Also recorded: the address-taken value may be a PARAMETER not a local (frame 8 too big with
all offsets shifted by 8 is the tell); address-taken form forces a register; the struct
assignment is what BATCHES the loads where element stores serialise behind maspsx nops; and
the cop2 operand is the 25-bit field (0x486012 -> 0x4A486012).
2026-09-24 09:36:47 -04:00