mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-10-08 01:34:14 -04:00
1.7 KiB
1.7 KiB
§398b ★★ — NAMING A SUB-EXPRESSION IN A LOCAL CHANGES WHICH PSEUDO SURVIVES; INLINE IT AT BOTH USE SITES (P31 S69; byte-proven ov_SC03_028/func_80183264, 93 ins)
Writing a repeated computation inline at both use sites and writing it once into a named local are not equivalent, and the difference is visible in the register file:
f( (v1 * 104) / 1024, ... ); /* inline at BOTH sites — cse builds the CSE itself */
s32 t = (v1 * 104) / 1024; /* named — expmed.c:2986 copy_to_mode_reg's temp */
Naming it lets expmed.c's copy_to_mode_reg temp coalesce with the product (an in-place
addiu/sra) and moves the surviving divide-copy onto the /16. Letting cse construct the common
subexpression itself keeps the temp a separate pseudo — which is what the target shows.
Two companions from the same crack:
- An
s16local's cse quantity differs from ans32one, and that difference alone is why anaddu $s3,$s2,$zerocopy survives. Rewriting ass32 t+ an(s16)cast letst.i.csefold three regs into one and the function loses two saved registers and two copies. The declared width is a cse-quantity dial, not just a codegen one (compare §392b). - The §136d-1
zrtrick needs to be applied to BOTH copies, not one.arg = ang;alone iscanon_reg'd away;arg = ang + zr;on both copies lets cse merge the two identicalang+$0expressions into one, reproducing the target's pair.
Banking caveat: a register … __asm__("$0") pin fails dedup_propagate.compiles_standalone
(§37), so a function cracked this way banks ×1 and never propagates to siblings. Prefer a
width/inlining lever over a $0 pin when the function has cousins.