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.
This commit is contained in:
@@ -2158,3 +2158,67 @@ is a rule, not a trick:
|
||||
> **When the frame is a clean multiple of 8 bytes short and everything else is identical, add an
|
||||
> unreferenced ARRAY local of that size.** cc1 homes an unreferenced *array* but not an unreferenced
|
||||
> *scalar*.
|
||||
|
||||
### 132. When the original's SHORT path is the fall-through, INVERT the condition — 2 independent instances (worker B)
|
||||
|
||||
Worker B's `0x800A8984` (188 B, a table-slot release helper) was **30 bytes off** on layout alone:
|
||||
|
||||
if (a0 < 8) s0 = table + a0*24; else s0 = 0; -> 30 bytes of wrong layout
|
||||
if (a0 >= 8) s0 = 0; else s0 = <table>; -> residual drops to 3 bytes
|
||||
|
||||
**The original BRANCHES INTO the table path and falls through to the zero path.** Worker B notes this
|
||||
is the *same* shape as its `0x800FCA90` (where the original branched into the body). **Two independent
|
||||
instances, both fixed the same way:**
|
||||
|
||||
> **When the original's short path is the fall-through and the long path is the branch target, invert
|
||||
> the condition in the source.**
|
||||
|
||||
This is the mirrored-layout family (findings 28/43/100) with a **stated direction** rather than a
|
||||
"try inverting it" heuristic. Note it is the *opposite* of the usual instinct, which is to write the
|
||||
guard as the early-exit.
|
||||
|
||||
**And worker B's second residual was exactly one register** — the loaded pointer in **a1** in the
|
||||
original versus **a0** in the candidate. Introducing an explicit `int *p` local to change the pseudo
|
||||
order had **no effect**, so it classified after two spellings. That is the allocator class, correctly
|
||||
identified and correctly abandoned.
|
||||
|
||||
### 133. A FAMILY GIVES YOU THE SHAPE, NOT THE DECLARATIONS (worker A)
|
||||
|
||||
Worker A's `0x800506E4` was **one byte wrong**: the sibling's source shape matched, `int i = 0` was
|
||||
kept, and cc1 still emitted `sltiu` — but **for this row the signed form emits `slt`.** Declaring
|
||||
`unsigned int i` reproduces the original's `sltiu`, and the next row (`0x80050548`) then matched
|
||||
**first try with that declaration inherited.**
|
||||
|
||||
> **When a family row is one byte off on a comparison opcode, try `unsigned` on the induction
|
||||
> variable before anything else.**
|
||||
|
||||
**The family transfers the SHAPE and the LEVERS; the DECLARATIONS must still be re-derived.** That is
|
||||
finding 55's limit stated precisely: the family gives you a 90% draft and you must still check the
|
||||
types.
|
||||
|
||||
### 134. A family hit is also a hint about the CALLEE, and the search does not model it (worker A)
|
||||
|
||||
Worker A observed that the family relation **crosses the call graph in both directions**:
|
||||
|
||||
- `0x8006B2D4` (a family row) **calls** `0x800C022C` — a row worker A had already classified, sharing
|
||||
the sub-object layout `mid+352` / `mid+396`.
|
||||
- `0x8003022C` (a family row) **calls** `0x8002FE3C`, which is itself on the unclaimed worklist.
|
||||
|
||||
**So a family hit is also a hint about its callees:** when a row's sibling calls a function you have
|
||||
already seen, check whether the callee is an unclaimed row with the same object layout. **That is a
|
||||
second row from one reading**, and `tools/sf3_family` does not model it — it compares bodies, not
|
||||
call edges.
|
||||
|
||||
### 135. A predicted family member that does NOT exist is a result (coordinator, negative)
|
||||
|
||||
Worker A mapped a **four-member family** completely and predicted the fourth by pattern — bases
|
||||
stepping by −0xD8 and −0x300, so `src = 0x80116DD0`, `dst = 0x8012FADC`, with the finaliser argument
|
||||
continuing 6, 2, 0, …
|
||||
|
||||
**I scanned all 1046 unclaimed worklist rows for `lui`/`addiu` pairs producing either predicted base:
|
||||
ZERO rows reference them.** So the family has exactly three members, and the pattern extrapolation
|
||||
does not continue.
|
||||
|
||||
**That is a useful negative**: it bounds the family, and it means no worker should spend time looking
|
||||
for the fourth. **A predicted member that does not exist is worth recording**, because the next
|
||||
worker will otherwise re-derive the prediction and repeat the search.
|
||||
|
||||
Reference in New Issue
Block a user