The optimizer spots the repeat
Write the same subexpression twice and IDO computes it once. This is common subexpression elimination — CSE — and it means the instruction count in the target won't match the operator count in your C. Here's sq(a, b), which returns (a + b) * (a + b):
addu v1, a0, a1 # a + b — ONE addu for two mentions
multu v1, v1 # …times itself
mflo v0
nop
nop
jr ra
nop
Two (a + b)s in the source, one addu in the machine. The shared value parks in v1 and feeds both multu operands. And it works in reverse when you're writing C from assembly: a register used in several places is allowed to be the same subexpression mentioned several times — you don't need a temp variable to make that happen. (You may use one: s32 t = a + b; return t * t; compiles to the identical listing. Pick whichever reads better; the compiler canonicalizes both.)
When you match a target like this, the tell is a register with multiple readers. Find what computed it, and every reader is another mention of that subexpression in your C.
The target computes one combination of its arguments and uses it twice — once raw, once shifted. Spot the shared register, then mind the second hint.
Your task
Write func_801fa5a4 to reproduce the target assembly.