https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63900

            Bug ID: 63900
           Summary: memory constrains needlessly doing memory clobber
           Product: gcc
           Version: 4.9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: inline-asm
          Assignee: unassigned at gcc dot gnu.org
          Reporter: gccbugzilla at limegreensocks dot com

Using a constraint like this:

   "=m" ( *(struct { char __x[BUFSIZE]; } *)b)

only works for very specific sizes of BUFSIZE (1, 2, 4, 8, 16).  All other
sizes (3, 12, 1000, etc) cause gcc to (silently) fall back to doing a full
memory clobber.

---------------------
#include <stdio.h>

#define MYSIZE 8

inline void 
__stosb(unsigned char *Dest, unsigned char Data, size_t Count)
{
   struct _reallybigstruct { char x[MYSIZE]; } 
      *p = (struct _reallybigstruct *)Dest;

   __asm__ __volatile__ ("rep stosb"
      : "+D" (Dest), "+c" (Count), "=m" (*p)
      : [Data] "a" (Data)
      //: "memory"
   );
}

int main()
{
   unsigned char buff[100], buff2[100];

   buff[5] = 'A';
   buff2[5] = 'M';
   asm("#" : : "r" (buff2));

   __stosb(buff, 'B', sizeof(buff));
   printf("%c %c\n", buff[5], buff2[5]);
}
---------------------

Compile this (4.9.0 x86_64-win32-seh-rev2, using -m64 -O2) with MYSIZE 8 and
look at the -S output.  If this is NOT doing a full clobber, gcc should be able
to just print buff2[5] by moving 77 into r8d before calling printf (which it
does).

Change MYSIZE to 3 (or 12, 1000, 0xfffffff, etc) we see the value getting read
from memory before calling printf, indicating the asm performed a full clobber
(affecting buff2) instead of just clobbering buff as was intended.

Reply via email to