Files
BFM-decomp/cookbook/C0385.md
T

1.1 KiB

§344 — RAISE A BIV'S global_alloc PRIORITY WITH A ZERO-BYTE REFERENCE INSTEAD OF PINNING IT; PINNING THE COUNTER KILLS LSR ENTIRELY (P31 S67; byte-proven ov_SC03_121/func_80180E64, 222 ins)

Writing the loop in INDEX form makes the pointer an LSR giv, so strength_reduce emits its init AFTER move_movables' hoisted constant — which is the order the target has. That leaves a counter-vs-giv register swap ($a0/$a1), and the obvious fix is wrong:

  • register pin on the counter → kills LSR entirely (the biv stops being a biv).
  • Zero-byte __asm__ __volatile__("" :: "r"(i)) in the loop body → correct. It adds a FIFTH reference to the biv, lifting its global_alloc priority (floor_log2(n_refs)*n_refs/live_length) above the giv's, and costs no instructions.

The general move: when two quantities are competing for a register and one is loop-structural, change its REFERENCE COUNT rather than its assignment. A pin overrides the allocator; an extra reference persuades it, and only the second leaves the loop optimizations intact. Cf. §334, where the same priority formula was moved by changing which pseudo got spilled.