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.

Reply via email to