2.5 KiB
§219 — COMPOUND +=, FULL ASSIGNMENT, AND AN EXPLICIT TEMP ARE THREE DIFFERENT SCHEDULES OF ONE READ-MODIFY-WRITE (P31 S58)
THE LAW. When a read-modify-write's schedule is one slot off — or when the value lands in the
wrong register — respell the OPERATOR before touching statement order. x += d, x = x + d and
t = x + d; x = t; are semantically identical and produce three distinct RTL shapes.
| card | binary | what changed | why |
|---|---|---|---|
func_8017FC64 |
ov_SC02_005 | an explicit sum = hw[0x20E] + var temp promoted the sum into $v0 and mis-scheduled; the compound += kept it in $v1 (the load's own register) and emitted addu $v1,$v1,$v0 before sh 0x210 |
the RMW stays glued to its load |
func_801804C0 |
ov_SC03_124 | the plain temp form still picked $a2; expressing the store as compound *ptr += v0 flipped the rematerialised base to $a1 |
the += form changes gcc's operand-order/register preference for a post-call rematerialisation |
func_80188BEC |
ov_SC03_028 | the two adjacent RMWs need DIFFERENT spellings — the first written as a full assignment x = (x + d) & 0xFFF, the second as +=; uniform spelling drifts length by 1 |
cse folds the first reload into the delay-slot store chain differently |
func_80184738 |
ov_SC02_011 | doing the store through a u8 * produced the target's double lhu 0($v1) around the RMW for free; writing the OR through the same u16 lvalue gcc already chose would merge it away |
char-aliasing forces the reload without a register-variable hack |
AND THE INCREMENT OPERATOR IS ITS OWN THIRD FORM (already §165-06 / §164-XX; two more instances
here): func_80186B14 (ov_SC04_002) — the counter MUST be (*p)++ or ++(*p), never += 1 or
*p = *p + 1; the one-insn expand difference shifts sched1's dependence ranking, and on this card it
also decides whether the last copy's sh lands in the jr delay slot.
A FOURTH SPELLING, for a modular decrement. func_8018009C (ov_SC03_011): the halfword op is
addiu -0x71 / andi 0xFFF — a modular 12-bit decrement (x - 0x71) & 0xFFF, not the twin's
additive (x & m) | k bitmask-or. A bitwise form cannot wrap, so the subtraction is forced. Read
the addiu sign before assuming the twin's operator.
BOUNDARY. All four rows are single-function A/Bs against match_one. What generalises is the
procedure (respell the operator, it is free) — not a claim that += is always the winner. On
func_80188BEC the two spellings won on adjacent statements of the same function.