Hello, i’ve noticed a new possible missed optimization while testing more trivial code.
This time it’s not a with a xor but with a multiplication instruction and the example is little bit more involved.
C code:
typedef short t;
t foo(t a, t b)
{
t a4 = a*b;
return a4;
}
argument “a” is passed in R15:R14, argument “b” in R13:R12, the return value is stored in R15:R14.
The mul instruction takes in two 8bit regs and returns a 16bit result in R1:R0, this is handled in the selectionDAG same way as x86 (btw mul is marked as commutable).
Asm code:
mul r12, r15
mov r8, r0
mul r12, r14
mov r9, r0
mov r10, r1
add r10, r8
mul r13, r14
mov r15, r0
add r15, r10
mov r14, r9
This can be tuned further to the following:
mov r8, r14
mov r9, r15
mul r12, r8
mov r14, r0
mov r15, r1
mul r12, r9
add r15, r0
mul r13, r8
add r15, r0
The difference between both versions is that the second has one instruction less and saves a scratch register.
If we start by multiplying the lower parts of both arguments instead of mixing upper and lower parts from a start we can save r8 in the first example and a later move, notice that the second version stores directly the result of a.low*b.low into R15:R14. I’m unsure if this is related to http://llvm.org/bugs/show_bug.cgi?id=8112
I’ve attached a txt file with the regcoalescing output incase it’s useful like requested in the previous emails.
Thanks
reg.txt (5.02 KB)