public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* A question about "memory" clobbers in asm
@ 2004-09-17 15:32 Jamie Lokier
  2004-09-17 15:39 ` Ian Lance Taylor
  2004-09-17 16:07 ` Nathan Sidwell
  0 siblings, 2 replies; 12+ messages in thread
From: Jamie Lokier @ 2004-09-17 15:32 UTC (permalink / raw)
  To: gcc

I'm having trouble understand when it's appropriate to use a "memory"
clobber, when to use volatile, and when to use both.  The manual is
unclear to me.  Although I see that someone has tried to clarify it
since I last read it, it's still not obvious how "memory" is different
from `volatile'.

GCC 3.3.4 manual, "Extended Asm" says:

   If your assembler instructions access memory in an unpredictable
   fashion, add `memory' to the list of clobbered registers.  This will
   cause GCC to not keep memory values cached in registers across the
   assembler instruction and not optimize stores or loads to that memory.
   You will also want to add the `volatile' keyword if the memory affected
   is not listed in the inputs or outputs of the `asm', as the
   `memory' clobber does not count as a side-effect of the `asm'.

This says the `memory' clobber doesn't count as a side-effect.
What is the difference between a clobber and a side-effect?

More precisely, the text says:

   You will also want to add the `volatile' keyword if the memory affected
   is not listed in the inputs or outputs of the `asm'...

but the subsequent example explains that if the affected memory _is_
listed in the inputs or outputs of the `asm', then you don't use "memory".

   If you know how large the accessed memory is, you can add it as
   input or output but if this is not known, you should add `memory'.
   As an example, if you access ten bytes of a string, you can use a
   memory input like:

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

The text logically says: if the code affects memory which _is_ listed
in the inputs and outputs, then don't use "memory".  If the code
affects memory which _isn't_ listed, then use `volatile'.

Does this mean that the following three propositions are true?:

  1. The only valid use for "memory" is in conjunction with `volatile'.
  2. "memory" without `volatile' doesn't mean anything useful.
  3. `volatile' by itself means the asm should not be eliminated just
     because it's outputs are unused, but it is safe for GCC to cache
     memory values across the asm.

Thanks,
-- Jamie

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: A question about "memory" clobbers in asm
  2004-09-17 15:32 A question about "memory" clobbers in asm Jamie Lokier
@ 2004-09-17 15:39 ` Ian Lance Taylor
  2004-09-17 15:50   ` Jamie Lokier
  2004-09-17 16:07 ` Nathan Sidwell
  1 sibling, 1 reply; 12+ messages in thread
From: Ian Lance Taylor @ 2004-09-17 15:39 UTC (permalink / raw)
  To: Jamie Lokier; +Cc: gcc

Jamie Lokier <jamie@shareable.org> writes:

Should this be on gcc-help?

> I'm having trouble understand when it's appropriate to use a "memory"
> clobber, when to use volatile, and when to use both.  The manual is
> unclear to me.  Although I see that someone has tried to clarify it
> since I last read it, it's still not obvious how "memory" is different
> from `volatile'.

Volatile means that the assembler instruction can not be deleted, even
if it appears to be useless.

Marking the instruction as clobbering memory means that if the
instruction is executed, then memory is clobbered in some undescribed
way.  However, that clobbering is not important to proper execution of
the program, and the instruction can be deleted if the specified
side-effects turn out to be unnecessary.

At least, that is my understanding.

Ian

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: A question about "memory" clobbers in asm
  2004-09-17 15:39 ` Ian Lance Taylor
@ 2004-09-17 15:50   ` Jamie Lokier
  0 siblings, 0 replies; 12+ messages in thread
From: Jamie Lokier @ 2004-09-17 15:50 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc

Ian Lance Taylor wrote:
> Should this be on gcc-help?

No, because I think it's a documentation bug.

> > I'm having trouble understand when it's appropriate to use a "memory"
> > clobber, when to use volatile, and when to use both.  The manual is
> > unclear to me.  Although I see that someone has tried to clarify it
> > since I last read it, it's still not obvious how "memory" is different
> > from `volatile'.
> 
> Volatile means that the assembler instruction can not be deleted, even
> if it appears to be useless.
> 
> Marking the instruction as clobbering memory means that if the
> instruction is executed, then memory is clobbered in some undescribed
> way.  However, that clobbering is not important to proper execution of
> the program, and the instruction can be deleted if the specified
> side-effects turn out to be unnecessary.

If correct, I find your explanation very well phrased - much clearer
than the manual.

Take a look at this sentence from the manual:

   You will also want to add the `volatile' keyword if the memory affected
   is not listed in the inputs or outputs of the `asm', as the `memory'
   clobber does not count as a side-effect of the `asm'.

Because "memory" isn't needed when the affected memory is listed in
the inputs or outputs, as it goes on to show in the example, the above
sentence implies that you should always use `volatile' any time that
you would use "memory".

That is the source of confusion, as that is found in the only
paragraph which describes what "memory" means.  The paragraph starts
by saying when to use "memory", then goes on to say when you would use
`volatile' in addition to "memory", but gives a condition which is
always true any time you would use "memory" according to the next bit.
("You _will_ also... if..."  <condition which is always true when you
would use "memory">).

Breaking down that paragraph, remember it's the only paragraph which
mentions "memory" so it is really the definition of "memory", it says:

   1. Use "memory" when memory is accessed unpredictably.
   2. Use `volatile' when access is to memory not mention in operands.
   3. Don't use "memory" when access is to memory mentioned in operands.

The only logical result which fits is "Use `volatile' whenever you
have reason to use "memory"".

Yet, if you take the fact that the sentence "You will also..." is
conditional as implying that sometimes you don't want to add the
`volatile' keyword, then the paragraph is in contradiction with itself.

In practice it means I don't know when it's appropriate to use
"memory" by itself.  I don't know what code doing that would mean or
if it's correct - at least, not by reading the GCC manual.

A quick check of Linux kernel's x86 code shows that it always uses
`volatile' whenever it uses "memory" - so no ambiguity there.

If your understand is correct, then I think it is quite well phrased
and something like it should go in the manual.

-- Jamie

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: A question about "memory" clobbers in asm
  2004-09-17 15:32 A question about "memory" clobbers in asm Jamie Lokier
  2004-09-17 15:39 ` Ian Lance Taylor
@ 2004-09-17 16:07 ` Nathan Sidwell
  2004-09-17 18:02   ` Jamie Lokier
  2004-09-20  7:37   ` tm_gccmail
  1 sibling, 2 replies; 12+ messages in thread
From: Nathan Sidwell @ 2004-09-17 16:07 UTC (permalink / raw)
  To: Jamie Lokier; +Cc: gcc

Jamie Lokier wrote:
> I'm having trouble understand when it's appropriate to use a "memory"
> clobber, when to use volatile, and when to use both.  The manual is
> unclear to me.  Although I see that someone has tried to clarify it
> since I last read it, it's still not obvious how "memory" is different
> from `volatile'.

my understanding is

* volatile asm says something to the effect 'this changes state that you
(the compiler) don't know about' -- such as writing to an IO port.

* memory clobber says 'this asm will change memory, so don't cache anything
across this asm'.

So,

   asm volatile ("pokeIOport");
   v = *ptr;

could hoist the load before the asm, but the asm will never be deleted
from the code sequence.  Whereas

   asm ("readsomething %0" :"=r" (v2) :: "memory");
   v = *ptr;

would do no such hoisting, but would delete the asm, if V2 was never
subsequently used.

nathan

-- 
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: A question about "memory" clobbers in asm
  2004-09-17 16:07 ` Nathan Sidwell
@ 2004-09-17 18:02   ` Jamie Lokier
  2004-09-18  1:52     ` Giovanni Bajo
  2004-09-20  7:37   ` tm_gccmail
  1 sibling, 1 reply; 12+ messages in thread
From: Jamie Lokier @ 2004-09-17 18:02 UTC (permalink / raw)
  To: Nathan Sidwell; +Cc: gcc

Nathan Sidwell wrote:
> my understanding is
> 
> * volatile asm says something to the effect 'this changes state that you
> (the compiler) don't know about' -- such as writing to an IO port.
> 
> * memory clobber says 'this asm will change memory, so don't cache anything
> across this asm'.

You and Ian agree, and that makes sense to me.

So I think the semantics are fine, but the documentation is unclear.

You have both explained the semantics in clear and concise language, so
my only issue is with the documentation.

Specifically, "You will also want to add the `volatile' keyword if the
memory affected is not listed in the inpus or outputs of the `asm'" is
misleading.

How about changing:

   If your assembler instructions access memory in an unpredictable
   fashion, add `memory' to the list of clobbered registers.  This will
   cause GCC to not keep memory values cached in registers across the
   assembler instruction and not optimize stores or loads to that memory.
   You will also want to add the `volatile' keyword if the memory affected
   is not listed in the inputs or outputs of the `asm', as the `memory'
   clobber does not count as a side-effect of the `asm'.  If you know how
   large the accessed memory is, you can add it as input or output but if
   this is not known, you should add `memory'.  As an example, if you
   access ten bytes of a string, you can use a memory input like:

to:

   If your assembler instruction loads from memory which is not listed
   in the inputs of the `asm', or stores to memory which is not listed
   in the outputs, add `memory' to the list of clobbered registers.
   This will cause GCC to not keep memory values cached in registers
   across the assembler instruction and not optimize stores or loads
   to that memory.

and later add:

   When to clobber `memory' and when to use `volatile'
   ...................................................

   Clobbering `memory' is independent of `volatile', although it is
   usually the case that if you clobber `memory' then you want
   `volatile' as well.

   Putting `memory' in the list of clobbered registers tells the
   compiler to not keep memory values cached acress the `asm'
   instruction, and not make other assumptions about the contents of
   memory.  (This is sometimes called a compiler memory barrier).  The
   compiler may still cache local variables whose addresses have not
   been taken.  Unless `volatile' is also specified, the `asm' can
   still be deleted, moved, or two combined if they're a common
   subexpression.

   Writing the `volatile' keyword after `asm' tells the compiler not
   to delete or significantly move the `asm' instruction, or combine
   two of them if they're a common subexpression.  Unless `memory' is
   clobbered as well, the compiler is permitted to cache memory values
   across an `asm volatile'.

How about that?

-- Jamie

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: A question about "memory" clobbers in asm
  2004-09-17 18:02   ` Jamie Lokier
@ 2004-09-18  1:52     ` Giovanni Bajo
  2004-09-18 17:10       ` Jamie Lokier
  0 siblings, 1 reply; 12+ messages in thread
From: Giovanni Bajo @ 2004-09-18  1:52 UTC (permalink / raw)
  To: Jamie Lokier; +Cc: gcc

Jamie Lokier wrote:

> How about that?

Looks fine to me. Why don't you submit a proper doc patch?

Giovanni Bajo


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: A question about "memory" clobbers in asm
  2004-09-18  1:52     ` Giovanni Bajo
@ 2004-09-18 17:10       ` Jamie Lokier
  2004-09-18 20:48         ` Giovanni Bajo
  0 siblings, 1 reply; 12+ messages in thread
From: Jamie Lokier @ 2004-09-18 17:10 UTC (permalink / raw)
  To: Giovanni Bajo; +Cc: gcc

Giovanni Bajo wrote:
> Looks fine to me. Why don't you submit a proper doc patch?

I'd like to but I don't have the time to prepare a source patch, and
then get it through the lengthy submission procedure at
http://gcc.gnu.org/contribute.html.

It is only a small documentation change, so I think it would take
someone who is often submits GCC patches a few minutes, given the text
is written.

But I think it would take me several hours to check out full source
from CVS over my 40k modem, get the tools to test the change, and then
configure and build GCC to test it as the submission prodedure asks.

Would you prepare a doc patch and submit it for me?  I'm happy to
proofread any change, and if necessary I'm happy to sign the
appropriate forms.

Thanks,
-- Jamie

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: A question about "memory" clobbers in asm
  2004-09-18 17:10       ` Jamie Lokier
@ 2004-09-18 20:48         ` Giovanni Bajo
  0 siblings, 0 replies; 12+ messages in thread
From: Giovanni Bajo @ 2004-09-18 20:48 UTC (permalink / raw)
  To: Jamie Lokier; +Cc: gcc

Jamie Lokier wrote:

> Would you prepare a doc patch and submit it for me?  I'm happy to
> proofread any change, and if necessary I'm happy to sign the
> appropriate forms.

OK. You should compile this form:
http://gcc.gnu.org/ml/gcc/2003-06/msg02298.html and send it to assign@gnu.org.
They will send you papers which you need to return signed. When you are done,
get back to us.

In the meantime, if you have time to fetch doc/*.texi from CVS, you can prepare
a proper patch. I can send you a tarball with just the docs (600k) if
downloading is the problem. Otherwise, I'll take care of it when your copyright
assignment is in place.

> But I think it would take me several hours to check out full source
> from CVS over my 40k modem, get the tools to test the change, and then
> configure and build GCC to test it as the submission prodedure asks.

Testing a doc patch is as easy as rebuilding the texi source, you do not need
to rebuild and test GCC itself.

Thanks!
Giovanni Bajo


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: A question about "memory" clobbers in asm
  2004-09-17 16:07 ` Nathan Sidwell
  2004-09-17 18:02   ` Jamie Lokier
@ 2004-09-20  7:37   ` tm_gccmail
  2004-09-20 13:57     ` Paul Koning
  2004-09-20 15:16     ` Dave Korn
  1 sibling, 2 replies; 12+ messages in thread
From: tm_gccmail @ 2004-09-20  7:37 UTC (permalink / raw)
  To: Nathan Sidwell; +Cc: Jamie Lokier, gcc

On Fri, 17 Sep 2004, Nathan Sidwell wrote:

> Jamie Lokier wrote:
> > I'm having trouble understand when it's appropriate to use a "memory"
> > clobber, when to use volatile, and when to use both.  The manual is
> > unclear to me.  Although I see that someone has tried to clarify it
> > since I last read it, it's still not obvious how "memory" is different
> > from `volatile'.
> 
> my understanding is
> 
> * volatile asm says something to the effect 'this changes state that you
> (the compiler) don't know about' -- such as writing to an IO port.
> 
> * memory clobber says 'this asm will change memory, so don't cache anything
> across this asm'.

This definition of memory clobbers is incomplete.

A memory clobber is required when the inline assembly either reads from or
writes to arbitrary memory or both. Not just "writes to".

I've seen cases like this:

	*ptr = 5;


	/* basically result = (*ptr == 5) */
	__asm__ volatile ("mov.l @%1,%0; mov #5,%2; cmp/eq %1,%2;
			   movt %0"
			   : "r" (result), "r" (temp)
			   : "r" (ptr));

	
	if (!result) {
		...
	}

If the memory clobber is omitted, then the scheduler can move *ptr = 5
AFTER the inline assembly fragment, which will result in the incorrect
result.

So if the inline assembly reads arbitrary memory, then it needs a memory
clobber regardless of whether it writes to memory.

Toshi




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: A question about "memory" clobbers in asm
  2004-09-20  7:37   ` tm_gccmail
@ 2004-09-20 13:57     ` Paul Koning
  2004-09-20 15:16     ` Dave Korn
  1 sibling, 0 replies; 12+ messages in thread
From: Paul Koning @ 2004-09-20 13:57 UTC (permalink / raw)
  To: tm_gccmail; +Cc: nathan, jamie, gcc

>>>>> "tm" == tm gccmail <tm_gccmail@kloo.net> writes:

 tm> On Fri, 17 Sep 2004, Nathan Sidwell wrote:
 >> Jamie Lokier wrote: > I'm having trouble understand when it's
 >> appropriate to use a "memory" > clobber, when to use volatile, and
 >> when to use both.  The manual is > unclear to me.  Although I see
 >> that someone has tried to clarify it > since I last read it, it's
 >> still not obvious how "memory" is different > from `volatile'.
 >> 
 >> my understanding is
 >> 
 >> * volatile asm says something to the effect 'this changes state
 >> that you (the compiler) don't know about' -- such as writing to an
 >> IO port.
 >> 
 >> * memory clobber says 'this asm will change memory, so don't cache
 >> anything across this asm'.

 tm> This definition of memory clobbers is incomplete.

 tm> A memory clobber is required when the inline assembly either
 tm> reads from or writes to arbitrary memory or both. Not just
 tm> "writes to".

This means that the term "clobber" should be removed from the
description because it is seriously misleading.

	    paul

^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: A question about "memory" clobbers in asm
  2004-09-20  7:37   ` tm_gccmail
  2004-09-20 13:57     ` Paul Koning
@ 2004-09-20 15:16     ` Dave Korn
  2004-09-20 15:39       ` Nathan Sidwell
  1 sibling, 1 reply; 12+ messages in thread
From: Dave Korn @ 2004-09-20 15:16 UTC (permalink / raw)
  To: tm_gccmail, 'Nathan Sidwell'; +Cc: 'Jamie Lokier', gcc

> -----Original Message-----
> From: gcc-owner On Behalf Of tm_gccmail
> Sent: 20 September 2004 06:30

> I've seen cases like this:
> 
> 	*ptr = 5;
> 
> 
> 	/* basically result = (*ptr == 5) */
> 	__asm__ volatile ("mov.l @%1,%0; mov #5,%2; cmp/eq %1,%2;
> 			   movt %0"
> 			   : "r" (result), "r" (temp)
> 			   : "r" (ptr));
> 
> 	
> 	if (!result) {
> 		...
> 	}
> 
> If the memory clobber is omitted, then the scheduler can move *ptr = 5
> AFTER the inline assembly fragment, which will result in the incorrect
> result.

  That should be considered a bug, shouldn't it?  I mean, the compiler knows
that ptr is an input to the asm, so it should no more move "*ptr = 5" to
after the asm than it should if there was a function call in the same
place...

   *ptr = 5;
   result = foo (ptr);
   if (!result) {
           ...
   }

  IMO it would be obviously invalid to move the assignment past the function
call in this case, and by analogy I don't think it should be valid in the
asm case either.  Is there something I'm not getting here?

[  In fact, even if foo didn't take ptr as an argument, it still shouldn't
be moving that assignment past the call to foo without having first done
some fairly hefty alias analysis.... ]

    cheers, 
      DaveK
-- 
Can't think of a witty .sigline today....

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: A question about "memory" clobbers in asm
  2004-09-20 15:16     ` Dave Korn
@ 2004-09-20 15:39       ` Nathan Sidwell
  0 siblings, 0 replies; 12+ messages in thread
From: Nathan Sidwell @ 2004-09-20 15:39 UTC (permalink / raw)
  To: Dave Korn; +Cc: tm_gccmail, 'Jamie Lokier', gcc

Dave Korn wrote:
>>-----Original Message-----

>   That should be considered a bug, shouldn't it?  I mean, the compiler knows
> that ptr is an input to the asm, so it should no more move "*ptr = 5" to
> after the asm than it should if there was a function call in the same
> place...
> 
>    *ptr = 5;
>    result = foo (ptr);
>    if (!result) {
>            ...
>    }
> 
>   IMO it would be obviously invalid to move the assignment past the function
> call in this case, and by analogy I don't think it should be valid in the
> asm case either.  Is there something I'm not getting here?
Yes, asms are not like function calls. The above asm is indistiguishable to
   *ptr = 5;
   result = ptr;
from a data-flow POV.

BTW, the asm
 > __asm__ volatile ("mov.l @%1,%0; mov #5,%2; cmp/eq %1,%2;
 > 			   movt %0"
 > 			   : "r" (result), "r" (temp)
 > 			   : "r" (ptr));
contains an error, in that it writes to the outputs before reading
the input.  The outputs should be marked as early clobbers.

> [  In fact, even if foo didn't take ptr as an argument, it still shouldn't
> be moving that assignment past the call to foo without having first done
> some fairly hefty alias analysis.... ]
yes, but not important in this case.

nathan

-- 
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2004-09-20 13:57 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-09-17 15:32 A question about "memory" clobbers in asm Jamie Lokier
2004-09-17 15:39 ` Ian Lance Taylor
2004-09-17 15:50   ` Jamie Lokier
2004-09-17 16:07 ` Nathan Sidwell
2004-09-17 18:02   ` Jamie Lokier
2004-09-18  1:52     ` Giovanni Bajo
2004-09-18 17:10       ` Jamie Lokier
2004-09-18 20:48         ` Giovanni Bajo
2004-09-20  7:37   ` tm_gccmail
2004-09-20 13:57     ` Paul Koning
2004-09-20 15:16     ` Dave Korn
2004-09-20 15:39       ` Nathan Sidwell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).