2.9 KiB
§392 ★★★ — THE SONNET-WAVE HARVEST (P31 S69): SEVEN TYPE/ORDER LEVERS THAT EACH CLOSED A MATCH
Seven overlay waves (105 agents, 57 MATCHes) produced these. Each is byte-proven by the named function and each is a SPELLING change, not a pin or a barrier.
(a) A same-address DUAL-SIGN read is fixed by ORDER, not by casts (ov_SC03_094/func_8017E254).
When one address is read both lh (signed, loop-invariant) and lhu (unsigned, store source),
gcc-2.7.2's cse merges both into lhu + sll + sra for EVERY spelling tried (volatile load, volatile
store, struct component-ref, asm re-tie — all identical output). The lever is source order: emit the
UNSIGNED store-source read BEFORE the signed assignment, so the intervening store consumes the cse
quantity first and forces a genuine separate lh.
(b) A narrow temp picks the narrow load (ov_SC03_028/func_8018568C,
ov_SC05_001/func_801809B8). Declaring a temp s16 vs s32 decides lh vs lhu: a 16-bit-ONLY
use needs no sign-extension, so gcc picks lhu. Widen the temp to s32 and it must sign-extend →
lh. The mirror case: a post-decrement zero-test temp declared signed yields the bare sll 16
zero-test; unsigned yields andi 0xFFFF — while the memory access stays lhu/sh either way.
(c) Fold the index, or force the subtract — the subscript decides (md_MAIN_045/func_800CCB28).
Writing tbl[idx - 2] lets gcc fold -2*4 = -8 into the lw offset (no runtime subtract). Hoisting
it — i = idx - 2; tbl[i] — forces the real addiu. The target's standalone addiu is the tell.
(d) Identical switch arms must be SEPARATE case blocks (ov_SC06_025/func_80182170). Cases with
identical bodies written comma-grouped (case 4: case 5:) merge too much (52 of 62 ins). The target
DUPLICATES the argument setup per case and cross-jump-merges only the shared jal+epilogue tail —
so write each case as its own block with its own call and return.
(e) Distinct pseudos per repeated copy (ov_SC03_031/func_8017F728). Two identical inline copies
(here rand()%160 + a field load) sharing ONE pseudo pair biases sched1's tie-break for the FIRST
copy only — copy 2 matches, copy 1 emits sra/lh swapped. Give each copy its own locals
(b1/r1, b2/r2) to remove the cross-copy WAW/anti-dependence.
(f) Split the widen to move it off a pinned register (ov_SC04_004/func_80182014). A sign-extend
chain will reuse a DYING pinned register as its own scratch. Writing wide = x << 16; x = wide >> 16;
as two statements forces the sll's target off the pinned register.
(g) The RETURN TYPE alone can close a schedule residual (ov_SC04_002/func_80182CBC). A
warm-start plateaued at SCHEDULE-REORDER/7 (arg-eval order + a delay-slot constant hoist). Changing
only s32 → void — matching the same-TU twin's declaration, parameters untouched — closed all
seven. Check the TU's own forward declaration before assuming the warm-start's return type.