0
votes

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?

2

2 Answers

2
votes

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).
0
votes

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