5.1 KiB
§456 — The lever-removal move catalog: what the S104 agents found under ~205 pins, barriers and launders (Phase 36 T7)
Every entry below was byte-proven on at least one banked body in S104 (the agent, the pass and the file:line are in that
pack's mechanism.md under .run/P36/agents/<alias>__<fn>/; METHOD_S103.md steps 12–16 carry the same list with the ids).
The pattern across the session: a decompiler-shaped body forces a lever because of ONE spelling decision; the original's
natural C removes it. Try these in order on a residual before any register lever.
Register residuals (local-alloc / global.c).
- One value per temp: a local that dies in several places is refused by local-alloc (
local-alloc.c:472) and goes global — substitute in place, split, or declare per block / per switch case (generators R23, R29). The INVERSE also closes: two locals the tree pins to one register are one variable (R28), a late local reusing an earlier-dead one lands in its register (R34). - Call-result temps of one type across cases → one function-scope variable (many refs, short live length outrank the self pointer).
- A block with exactly THREE quantities is allocated in BIRTH order, not sorted (
local-alloc.c:1486-1507;tools/localalloc_sim.pymodels it): add or remove a quantity (a compound assignment, an inlined re-read) to flip it (R32). - An integer-truncated
allocno_compareTIE (global.c:594-607, ties by allocno number;tools/alloc_table.pyflagsTIE): duplicate the statement after an if/else join into both arms — one insn of live length splits it and cross-jump re-merges (R39). - A parameter copy
T x = argN;deleted (R35) or moved to a later plain statement;return ++i;for a counter's refs (R40); a call passed at its REAL arity (the extra arg costs 0 bytes — jump2 deletes the no-op copy,jump.c:425-462) (R19). - Widths: an
s16/u16/u8local for a value used narrow keeps a SUBREG copy cse cannot fold (cse.c:7440-7474); a cast at ONE shift,(s16)t >> N(R31); joint widths on several locals at once. - A walked pointer stepped alongside another → indexed by the counter (
record_givloop.c:4341,combine_givs:5494); a load split from its updateT = LOAD; … P = T + X;; a twice-set pointerp = &D; p += x;as one expression (R36 — the frame-only residual: combine leaves the ref count, reload gives a slot,combine.c:2305-2337,reload1.c:2327-2352). - A named derived pointer
q = p - kthat cse keeps as a REGISTER address (find_best_addr,cse.c:2656-2721) — thelalever.
Order / count residuals (cse, sched, jump, reorg).
- A goto chain → structured C (if/else,
||,switch,forwithbreak/continue, a shared tail written out per site): a label between a store and its tail blocks jump1's if-conversion (jump.c:805/:1019), cross-jump re-merges duplicated tails (jump.c:2371) at zero bytes, a rotated loop'sNOTE_INSN_LOOP_VTOPflips reorg'smostly_true_jump(reorg.c:1364-1372). The reverse exists too: a do-while as a backward goto loop when the target shows NO loop optimisation (loop.c:352-361). x = a; if (c) x = f(a);→ if/else with the non-simple value in the ELSE arm (jump1 re-merges a reg/const else,jump.c:739-741) (R33).- A result local
r = 0; if (A) r = (B); return r;→if (A && B) return 1; return 0;(jump1's store-flag on the hard$v0) (R37). - A store in EACH arm when the target reloads a global after it (cse forwards only within a block,
cse.c:7358-7369,:8039) or when sched1 treats two symbols as non-aliasing; each arm's store BEFORE its counter; the if/else arms swapped for reorg's delay-slot steal (R41); a statement moved several positions down its block (R42). - A sign test whose arms set/clear bit 31 →
& 0x80000000(the mask'sluifills the slot,reorg.c:2799; the dead AND's slot is what a pad faked) (R43). A hand-expandedif (v < 0) v += 2^k-1; v >>= k;isv / 2^k(R38);(b << k) - bisb * (2^k-1). - Set counts steer three passes: a second identical assignment demotes sched1's birthing boost (
sched.c:2469-2545), keeps a constant off REG_EQUIV's doubled live length (local-alloc.c:1016-1064), and keeps loop.c from hoisting (loop.c:705). - Struct/array spelling decides sched's alias test (
expr.c:4568-4577→sched.c:817-861): a cast byte-offset store is scalar, an indexed/field access is aggregate — pick per access group; GTE scratch words gathered into one local struct; a 16-byte copy loop as ONE struct assignment (expand_block_move,mips.c:2330ff). - Sony's GTE macros replace hand-flattened GTE asm blocks; parameters straight into the macros (reload's spill register).
Signals that a close is NOT plain C (park it, structs phase): a (void) function whose first act reads a pinned $a0–$a3
takes a parameter; a void function whose final keepalive reads v0 returns it; a narrow parameter the bytes use as s32 is
s32; a store through another symbol of the same address is identical only after LINKING. Refused as closes: an invented
always-false condition, a dead store kept only to steer a pass, a pointer alias invented only to dodge cse.