0

In GCC inline assembly, there are two ways to prevent from being optimized-out: __volatile__ keyword and inserting "memory" into clobber registers list.

My question is what is difference from __volatile__ and "memory" - It seems that they're the same... However, today I faced the strange situation, which shows they're definitely different! (My program had a bug in port I/O functions when I used "memory", but it becomes fine when I used __volatile__.)

What's the difference?

ikh
  • 10,119
  • 1
  • 31
  • 70

2 Answers2

2

My reading of the GCC documentation is that the __volatile__ keyword is for assembly that has side-effects: that is, it does something other than produce inputs from outputs. In your case, I imagine "port I/O functions" would cause side-effects.

The "memory" clobber is just for assembly that reads/writes memory other than the input/output operands. While this is a side-effect, not all side-effects involve memory.

From the manual:

The typical use of Extended asm statements is to manipulate input values to produce output values. However, your asm statements may also produce side effects. If so, you may need to use the volatile qualifier to disable certain optimizations.

and

The "memory" clobber tells the compiler that the assembly code performs memory reads or writes to items other than those listed in the input and output operands (for example accessing the memory pointed to by one of the input parameters).
Michael Rawson
  • 1,905
  • 1
  • 15
  • 25
  • Subset? Umm.. then, is there any case which should be `__volatile__`, while `"memory"` isn't needed? Could you tell me one of them? – ikh Jun 05 '14 at 14:06
  • Assuming I understand the manual okay, loading a time from the system clock (apparently the `rdtsc` instruction) would be one of those cases. Does that help? – Michael Rawson Jun 05 '14 at 14:23
  • Subset is not correct. That implies that volatile also performs a memory clobber (which it doesn't). It's also important that "memory" doesn't just mean that you read/write memory. It's that you read/write memory "other than those listed in the input and output operands." For example if you are just updating an output parameter ("+m"), you don't (necessarily) need the memory clobber. But if you just pass a void pointer to the asm (for example to do a memset), then gcc can't figure out how much memory you might change. Using the memory clobber tells it to assume you change everything. – David Wohlferd Jun 06 '14 at 06:15
  • Thanks you, Michael and David! I seem to understand. – ikh Jun 06 '14 at 06:49
  • @DavidWohlferd However, Isn't memory clobber a kind of *side-effect*..? – ikh Jun 06 '14 at 06:51
  • I'm not sure how you could see "memory" as a side effect. It is an explicit instruction to the compiler to perform a specific action. This action is not taken automatically for all asm instructions, and it doesn't "just happen" if you specify "volatile" or an output parameter that is in memory. Consider my memset example. If right before you call an asm that does memset on a struct, you assign a value to a member of the struct, what happens? Without the memory clobber, the value may not get written to memory until AFTER the asm (due to optimization). Obviously not what you intended. – David Wohlferd Jun 06 '14 at 08:40
  • @DavidWohlferd but doesn't volatile prevent such optimization because compiler doesn't know whether your volatile asm touches the memory or not? Or does the compiler treat volatile asm as "any side effects may occur except memory ones"? – Dan M. Jul 21 '23 at 13:52
0

Using __volatile__ you warrant that the value is always retrieved from RAM baypassing the CPU cache. This, as stated in the answer by Michael Rawson, produces side effects but in the sense that the normal optimization through CPU cache is "disabled" and nothing else.

In your case a value readed from an I/O port (and stored in a variabile) can be updated faster than the CPU cache invalidation so you may read an "old" value. Using __volatile__ you read always the non cached value.

You can also see: this post (I don't know if your architecture is ARM but te concept is the same).

Community
  • 1
  • 1
Marco Sacchi
  • 712
  • 6
  • 21