------- 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

Reply via email to