On 02/12/15 12:34, Bernd Edlinger wrote: > Hi, > >> Surely in code like that, you would make "x" volatile? Memory clobbers >> are not a substitute for correct use of volatile accesses. > > No, > > It is as I wrote, a memory clobber is the only way to guarantee that > the asm statement is not move somewhere else. > > I changed the example to use volatile and compiled it > with gcc-Version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) > > volatile int x; > void > test() > { > x = 1; > asm volatile("nop"); > x = 0; > } > > gcc -S -O2 test.c gives: > > > test: > .LFB0: > .cfi_startproc > movl $1, x(%rip) > movl $0, x(%rip) > #APP > # 6 "test.c" 1 > nop > # 0 "" 2 > #NO_APP > ret > .cfi_endproc > > > While it works with asm volatile("nop" ::: "memory"). > Likewise for "cli" and "sti" if you try to implement critical sections. > Although, these instructions do not touch any memory, we > need the memory clobber to prevent code motion. >
That is clearly a bug in gcc, and not one that I see on my system (gcc 4.5 or gcc 4.9 on amd64). The compiler is not allowed to re-arrange the order of volatile accesses with respect to each other, and "asm volatile" counts as a volatile access. The compiler /is/ allowed to re-arrange volatile and non-volatile accesses, which is why you need volatiles in the right place (or the sledgehammer approach, a memory clobber). It is common to put memory clobbers with instructions like "cli" and "sti" for critical sections, but that is to help people who don't always get their "volatile" right (or for those that understand it fine, but choose memory clobbers as a neater alternative for the code in question).