Consider the following code:
double x(double a,double b) {
return a*(float)b;
}
It does a conversion form double to float than again to double and multiplies.
When I compile it with gcc 9.1 with -O3 on x86/64 I get:
x(double, double):
movapd xmm2, xmm0
pxor xmm0, xmm0
cvtsd2ss xmm1, xmm1
cvtss2sd xmm0, xmm1
mulsd xmm0, xmm2
ret
With clang and older versions of gcc I get this:
x(double, double):
cvtsd2ss xmm1, xmm1
cvtss2sd xmm1, xmm1
mulsd xmm0, xmm1
ret
Here I do not copy xmm0 into xmm2 which seems unnecessary to me.
With gcc 9.1 and -Os I get:
x(double, double):
movapd xmm2, xmm0
cvtsd2ss xmm1, xmm1
cvtss2sd xmm0, xmm1
mulsd xmm0, xmm2
ret
So it just removes the instruction which sets xmm0 to zero but not the moveapd.
I believe all three versions are correct, so could there be a performance benefit from the gcc 9.1 -O3 version? And if yes why? Does the pxor xmm0, xmm0 instruction has any benefit?
The issue is similar to Assembly code redundancy in optimized C code, but I don't think its the same because older versions of gcc do not generate the unnecessary copy.