Files
BFM-decomp/cookbook/C0263.md
T

2.0 KiB
Raw Blame History

§242 — *k vs <<n, AND /2^n vs >>n: EXPRESSION SPELLING OWNS THE LOAD WIDTH AND THE ROUNDING CHAIN (P31 S58b)

Two semantically identical spellings, two different instruction streams. Both cost a card apiece.

1. * 4 KEEPS A DEAD SIGN-EXTENSION ALIVE THAT << 2 LETS GCC DELETE. func_8017F300 (ov_SC06_029, 12/12): with the natural << 2 spelling gcc emitted lhu 0x100($a0) where the target has lh — the sign extension is semantically dead under the later sh, so extend-propagation weakened the load. Spelling the scale as a multiply (* 4) keeps SIGN_EXTEND alive through expand — gcc-2.7.2 does not run the dead-high-bits analysis through MULT — and the load emits as lh. Nearest prior art (§164-46/§164-47, §162k1) covers dead compares and declared-local width, not expression-spelling-driven lh/lhu selection.

2. /512 KEEPS THE ROUNDING CHAIN THAT >>9 FOLDS AWAY. func_8017FCBC (ov_SC03_030, 230/230): *0x50 >> 9 folded to srl 5; the target wants expand_divmod's bgez / addiu 0x1FF / sra 9 round-toward-zero chain, which only survives when written as * 0x50 / 512. Same for /256. Complementary card func_8017F470 (ov_SC04_002) runs the dial the other way: the target has a bare sra ,2, so the source is >> 2; writing /4 expands to bgez+addiu -3 fixup chains (+7 ins).

THE RULE. Read the fixup chain first. Bias addiu 2^k−1 present ⇒ the source divided (/2^k). Bias absent ⇒ the source shifted (>>k). Scale on the left of a narrow load ⇒ prefer *k if the target shows lh; prefer <<n if it shows lhu.

RELATED SPELLING TRIGGERS FROM THE SAME HARVEST. A folded multiplier survives where its decomposition does not: *341/*11 written as single constants emit the target's shift-add chains, while hand-written sll/addu/sll/subu or *5*68 decompositions get re-folded to li 736 (func_80185520, ov_SC06_000). x*2/3 emits sll v0,1 before the mult; plain /3 costs a slot (func_80182CA0).