------- Additional Comments From das at FreeBSD dot ORG 2005-01-14 21:34 ------- Here's another test case that shows that gcc 3.4.2 on i386 will reschedule other instructions (in particular, other asms that are not volatile) across a volatile asm:
#include <sys/types.h> #define __fldenv(env) __asm __volatile("fldenv %0" : : "m" (env)) #define __fnstsw(__sw) __asm("fnstsw %0" : "=am" (*(__sw))) #define __ldmxcsr(csr) __asm __volatile("ldmxcsr %0" : : "m" (csr)) #define __stmxcsr(csr) __asm("stmxcsr %0" : "=m" (*(csr))) typedef struct { struct { uint32_t control; uint32_t status; uint32_t tag; char other[16]; } x87; uint32_t mxcsr; } fenv_t; int feraiseexcept(int __excepts); int feupdateenv(const fenv_t *envp) { int mxcsr, status; __fnstsw(&status); __stmxcsr(&mxcsr); __fldenv(envp->x87); /* volatile */ __ldmxcsr(envp->mxcsr); /* volatile */ feraiseexcept((mxcsr | status) & 0x3f); return (0); } The code generated at -O2 is as follows: feupdateenv: pushl %ebp movl %esp, %ebp subl $20, %esp movl 8(%ebp), %eax #APP fnstsw -4(%ebp) stmxcsr -8(%ebp) fldenv (%eax) ldmxcsr 28(%eax) fnstsw %eax <--- should be movl -4(%ebp), %eax #NO_APP orl -8(%ebp), %eax andl $63, %eax pushl %eax call feraiseexcept xorl %eax, %eax leave ret The fnstsw is moved (duplicated, actually) across the fldenv and ldmxcsr, which are volatile. At -O1, gcc gets this "right". My vote is to fix the code rather than the documentation; if volatile asms don't act as sequence points, then in code such as the above, it becomes necessary to apply the sledgehammer of marking *all* asms volatile. This is because there's no way to express to gcc that an asm reads from a hard register such as the FPSR. If the instructions that write the FPSR (already marked volatile in the example) acted as sequence points, we would be guaranteed that instructions that read the FPSR could not be moved past them, without having to make the latter volatile. Note that even if you don't go with my idea, the following proposal isn't quite accurate: > From this it appears that the only effect of 'asm volatile' that users > can safely rely on is that such an instruction will not be deleted. It is also true (hopefully) that volatile asms cannot be reordered with respect to each other, w.r.t. function calls, etc. This is not true of ordinary asms, as seen above. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17884