https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127871
Bug ID: 127871
Summary: FRE replaces x87 load from double with VIEW_CONVERT
from integer, RTL expansion turns VIEW_CONVERT_EXPR
into mutating x87 load
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Keywords: missed-optimization, wrong-code
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: rguenth at gcc dot gnu.org
Target Milestone: ---
Target: i?86-*-*
double y;
double foo (unsigned long long *x)
{
__builtin_memcpy (&y, x, sizeof (double));
return y;
}
with -O2 -m32 -mno-sse RTL expands from
double foo (long long unsigned int * x)
{
unsigned long long _1;
double _5;
<bb 2> [local count: 1073741824]:
_1 = MEM <unsigned long long> [(char * {ref-all})x_3(D)];
MEM <unsigned long long> [(char * {ref-all})&y] = _1;
_5 = VIEW_CONVERT_EXPR<double>(_1);
return _5;
where you can see the originally canonicalizing load (fldl) is replaced by
a VIEW_CONVERT_EXRP from an uint64_t register.
That is then RTL expanded wrongly to a canonicalizing load (fldl), so we
get
movl 16(%esp), %eax
movl 4(%eax), %edx
movl (%eax), %eax
movl %edx, 4(%esp)
movl %eax, (%esp)
fldl (%esp)
movl %eax, y
movl %edx, y+4
where the end result is "correct". IIRC x87 has no way to load a value
bitwise (or to store a value or move it to a GPR). A full fp80 (long long
double) store or load transfer bit patterns exactly, so a VIEW_CONVERT_EXPR
to float/double should expand to bit-twiddling to the 80bit FP layout
in memory and a fldt to load that into the x87 stack. So it's definitely
worth avoiding creating such VIEW_CONVERT_EXPRs at all cost.