On 09/24/2014 12:31 PM, Richard Biener wrote:
On Wed, Sep 24, 2014 at 9:43 AM, David Wohlferd <d...@limegreensocks.com> wrote:
Hans-Peter Nilsson: I should have listened to you back when you raised
concerns about this.  My apologies for ever doubting you.

In summary:

- The "trick" in the docs for using an arbitrarily sized struct to force
register flushes for inline asm does not work.
- Placing the inline asm in a separate routine can sometimes mask the
problem with the trick not working.
- The sample that has been in the docs forever performs an unhelpful,
unexpected, and probably unwanted stack allocation + memcpy.

Details:

Here is the text from the docs:

-----------
One trick to avoid [using the "memory" clobber] is available if the size of
the memory being accessed is known at compile time. For example, if
accessing ten bytes of a string, use a memory input like:

     "m"( ({ struct { char x[10]; } *p = (void *)ptr ; *p; }) )

Well - this can't work because you essentially are using a _value_
here (looking at the GIMPLE - I'm not sure if a statement expression
evaluates to an lvalue.

It should work if you simply do this without a stmt expression:

   "m" (*(struct { char x[10]; } *)ptr)

because that's clearly an lvalue (and the GIMPLE correctly says so):

   <bb 2>:
   c.a = 1;
   c.b = 2;
   __asm__ __volatile__("rep; stosb" : "=D" Dest_4, "=c" Count_5 : "0"
&c, "a" 0, "m" MEM[(struct foo *)&c], "1" 8);
   printf ("%u %u\n", 1, 2);

note that we still constant propagated 1 and 2 for the reason that
the asm didn't get any VDEF.  That's because you do not have any
memory output!  So while it keeps 'c' live it doesn't consider it
modified by the asm.  You'd still need to clobber the memory,
but "m" clobbers are not supported, only "memory".

Thus fixed asm:


       __asm__ __volatile__ ("rep; stosb"
            : "=D" (Dest), "+c" (Count)
            : "0" (&c), "a" (0),
            "m" (*( struct foo { char x[8]; } *)&c)
            : "memory"
       );

where I'm not 100% sure if the "m" input is now pointless (that is,
if a "memory" clobber also constitutes a use of all memory).

Or maybe even
  __asm__ __volatile__ ("rep; stosb"
       : "=D" (Dest), "+c" (Count), "+m" (*(struct foo { char x[8]; } *)&c)
       : "0" (&c), "a" (0)
  );
to avoid the big-hammer memory clobber?

-Y

Reply via email to