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.
This commit is contained in:
+989
-990
File diff suppressed because it is too large
Load Diff
@@ -90,6 +90,7 @@
|
||||
0x80025ADC 0x80025B64 src/func_80025ADC.c
|
||||
0x80026180 0x800261C0 src/func_80026180.c
|
||||
0x800261C0 0x8002622C src/func_800261C0.c
|
||||
0x8002622C 0x80026258 src/func_8002622C.c
|
||||
0x80026258 0x80026264 src/func_80026258.c
|
||||
0x80026264 0x80026274 src/func_80026264.c
|
||||
0x80026274 0x800262E0 src/func_80026274.c
|
||||
|
||||
|
@@ -2928,3 +2928,44 @@ token had been applied by shape.** The cheap read, and the one to remember:
|
||||
|
||||
> **"4 bytes SHORT with the token on" means the token was unnecessary** — that is exactly how
|
||||
> `0x80091674` and `0x801080B8` present.
|
||||
|
||||
### 181. *** AN ARITHMETICALLY-CANCELLING PAIR MEANS THE INTERMEDIATE IS LIVE PAST IT ***
|
||||
|
||||
**Worker F overturned a recorded negative with this, and it is a new class.**
|
||||
|
||||
`0x8002622C` was in `near_match_negatives.tsv` — the earlier record said *"cc1 folds it, unreachable"*
|
||||
and tried **four algebraic re-spellings**. All four were doomed: **the fold is not in the front end,
|
||||
it is at RTL combine, so no re-spelling can ever avoid it. Only LIVENESS can.**
|
||||
|
||||
| spelling | result |
|
||||
|---|---|
|
||||
| same body with `return 0;` | **32 B LENGTH-MISMATCH** — folded to one `la` and four stores of `$4` |
|
||||
| with **`return n;`** (the difference live past the addition) | **44 B / 0 differing / MATCH** |
|
||||
|
||||
**Diagnostic that PROVES the pass:** `cc1 -da` — the `minus` is present in the **`.flow` dump** and
|
||||
**gone in the `.combine` dump**; `cse`, `cse2`, `jump`, `loop`, `sched`, `sched2` all still contain it.
|
||||
|
||||
> **When an original keeps an arithmetically-cancelling pair (`subu`+`addu`, `x − c + c`, a redundant
|
||||
> recomputation), the intermediate is LIVE PAST the second operation — find the later reader.** Here
|
||||
> it is the function's return value, and it costs **zero** instructions because the difference's home
|
||||
> is already the return register `v0`.
|
||||
|
||||
**Two corollaries from the same row:** `D_8015E978` must be a **symbol**
|
||||
(`extern char D_8015E978[];`) or the `la` becomes `lui`+`ori`; and the entry `move v0,a0` exists
|
||||
because `a0` stays live (stored to `D_80121B20`), so the source's `n = a0` cannot coalesce.
|
||||
|
||||
**And the general lesson about NEGATIVES:** a recorded negative is a record of **attempts**, not of
|
||||
impossibility. **This row's four recorded spellings were all algebraic; the answer was in a different
|
||||
dimension.** Worker F took it because the record was old enough to predate the current toolset — and
|
||||
the tools had nothing to do with it. **The lever class had simply never been tried.**
|
||||
|
||||
### 182. A negative with a NAMED mechanism is overturnable; one without is not
|
||||
|
||||
`0x8002622C`'s record said *"cc1 folds it"* — **a mechanism claim, and it was half right**: cc1 does
|
||||
fold it, but the record concluded *unreachable* from that, when the correct conclusion is *only
|
||||
liveness can prevent it*. **Worker F's four attempts failed for the same reason and nobody noticed,
|
||||
because they were all in the same dimension.**
|
||||
|
||||
> **When you classify a row unreachable, state WHICH PASS does the damage and WHAT DIMENSION you
|
||||
> exhausted.** "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.
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* func_8002622C — 44 bytes at 0x8002622C..0x80026258
|
||||
*
|
||||
* Initialises the four `gp`-relative arena globals from the arena base passed in
|
||||
* `a0`, and returns the arena's distance from the fixed data address D_8015E978.
|
||||
*
|
||||
* The observed instructions are:
|
||||
* move v0,a0 n = a0 (n cannot coalesce with a0)
|
||||
* lui v1,0x8016 \
|
||||
* addiu v1,v1,-5768 / v1 = D_8015E978 (a SYMBOL: `la`, not `li`)
|
||||
* sw v0,488(gp) D_80121B20 = n
|
||||
* subu v0,v0,v1 n = n - D_8015E978
|
||||
* sw v1,476(gp) D_80121B14 = D_8015E978
|
||||
* addu v1,v0,v1 x = n + D_8015E978
|
||||
* sw v1,480(gp) D_80121B18 = x
|
||||
* sw v1,484(gp) D_80121B1C = x
|
||||
* jr ra return n;
|
||||
*
|
||||
* THE `subu`/`addu` PAIR IS KEPT ONLY BECAUSE THE DIFFERENCE IS RETURNED.
|
||||
* `(a0 - K) + K` is cancelled by combine's dead-register substitution, and this
|
||||
* row is on the recorded-negative list (`config/near_match_negatives.tsv` line
|
||||
* 47) for exactly that reason. The lever that was missing is LIVENESS, not
|
||||
* algebra: if the difference's live range ends at the addition, combine
|
||||
* substitutes its definition and folds the pair away (probe H3, `return 0;`,
|
||||
* 32 B), while keeping it alive past the addition — here by returning it —
|
||||
* blocks the substitution and reproduces the original 44 B. Diagnostic: with
|
||||
* cc1 `-da` the `minus` is present in the `.flow` dump and gone in `.combine`.
|
||||
* The fold is at the RTL level (combine), NOT in the front end, so no
|
||||
* algebraic re-spelling of the source can avoid it — only liveness can.
|
||||
*
|
||||
* The `move v0,a0` is the source's `n = a0`: `a0` stays live (it is stored to
|
||||
* D_80121B20), so the copy cannot coalesce, and `n`'s home is the return
|
||||
* register v0.
|
||||
*
|
||||
* D_8015E978 MUST be a symbol reference: written as a literal the address
|
||||
* materialises as `lui`+`ori` instead of `lui`+`addiu`. The four globals are
|
||||
* registered `gp` in `config/symbols.tsv`, giving the `%gp_rel` stores.
|
||||
*
|
||||
* LIMITS: the name, the return type, the widths of the four globals and the
|
||||
* meaning of the difference are hypotheses reconstructed from the disassembly;
|
||||
* only the compiled bytes are evidence.
|
||||
*/
|
||||
|
||||
extern int D_80121B14;
|
||||
extern int D_80121B18;
|
||||
extern int D_80121B1C;
|
||||
extern int D_80121B20;
|
||||
extern char D_8015E978[];
|
||||
|
||||
int func_8002622C(int a0) {
|
||||
int n = a0;
|
||||
|
||||
D_80121B20 = n;
|
||||
D_80121B14 = (int)D_8015E978;
|
||||
n = n - (int)D_8015E978;
|
||||
D_80121B18 = n + (int)D_8015E978;
|
||||
D_80121B1C = n + (int)D_8015E978;
|
||||
return n;
|
||||
}
|
||||
Reference in New Issue
Block a user