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.