GCC 11.2 (-O3) compiles this
#include <stdint.h>
float flt_abs(float x) {
return *(float *)&(uint32_t){*(uint32_t *)&x & INT32_MAX};
}
float f(float x) {
return flt_abs(x - (int)x) * 4;
}
to this
flt_abs:
movd eax, xmm0
and eax, 2147483647
movd xmm0, eax
ret
f:
cvttss2si eax, xmm0
pxor xmm1, xmm1
cvtsi2ss xmm1, eax
mov eax, 2147483647
subss xmm0, xmm1
movd DWORD PTR [rsp-4], xmm0
and eax, DWORD PTR [rsp-4]
movd xmm0, eax
mulss xmm0, DWORD PTR .LC0[rip]
ret
.LC0:
.long 1082130432
(I know it's better to use fabsf here, but just for a test.)
There are plenty of clobber registers left in f, but GCC isn't using any of them but pushing the value to memory for some reason.
Is this a bug in GCC, or an intended result?
If it is intended, what makes it better to push to the stack rather than to use a clobber register.
If it is a bug, how should I file this? I mean,
- Is there a mailing list, or some website for filing bugs?
- What kind of problem is this? Is there a known or related bug? I want to be more specific about the problem.
The question is about 64-bit, but it would still apply on 32-bit because ecx and edx is usable without push/pop in f.
I've just found that the problem is gone in the "trunk" version of GCC in Godbolt. The devs seems to have noticed the problem beforehand and fixed it.