http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46479

           Summary: [4.4/4.5/4.6 Regression] "+m" (*regs) : "a" (regs)
                    doesn't use (%eax) for the MEM
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: ja...@gcc.gnu.org


/* { dg-do compile { target { { i686-*-* x86_64-*-* } && ilp32 } } } */
/* { dg-options "-Os -fno-omit-frame-pointer" } */

struct S { long c[64]; };
int foo (struct S *regs)
{
  int rc;
  asm volatile ("" : "=a" (rc), "+m" (*regs) : "a" (regs) : "ebx", "ecx",
"edx", "esi", "edi", "memory");
  return rc;
}

doesn't compile any longer, starting with 4.4.  Even with smaller register
pressure GCC before IRA used to reuse the register holding the address, wasting
another one is unnecessary.  If there is just "m" (*regs) as input operand even
with IRA the eax register is used as the address for the memory operand.

I guess what is confusing IRA here is that the MEM appears as output operand
and the asm clobbers the %eax register (as it sets it to something else) and so
thinks it must give the output operand an address that is still valid at the
end of the inline asm rather than just start.  But for memory addresses that is
not true, unless there is an earlyclobber - it is enough if the address of the
output MEM is valid at the beginning of the inline asm.

I'd say this is an important bug, not because in this very high register
pressure asm we fail to compile it, but because

int bar (struct S *regs)
{
  int rc;
  asm volatile ("" : "=a" (rc), "+m" (*regs) : "a" (regs));
  return rc;
}

is quite common, the "+m" there is just to tell GCC what side-effects it has,
is never used in the asm and it is desirable that it doesn't introduce runtime
overhead.

Reply via email to