This is the mail archive of the
mailing list for the GCC project.
Re: How to avoid code elimination
On 27/11/2017 23:12, Segher Boessenkool wrote:
On Mon, Nov 27, 2017 at 12:32:28PM +0100, David Brown wrote:
doing an asm("nop") seems to do the job for gcc, and I guess (not
verified) would be portable across architectures, so for gcc/gdb combo
I will do this.
Most targets have a "nop" instruction, but not all.
#if defined (__ia64__) || defined (__s390__) || defined (__s390x__)
#define NOP "nop 0"
#elif defined (__MMIX__)
#define NOP "swym 0"
#define NOP "nop"
I would recommend you use:
asm volatile ("nop" ::: "memory");
The "volatile" limits re-ordering somewhat
No, it doesn't: to start with, this asm *always* is volatile (it has no
outputs, asms without outputs are always volatile).
Yes, the "volatile" here is for clarity rather than being a requirement.
But it /does/ limit reordering (whether it is explicit or implicit).
A non-volatile asm statement can be re-ordered with respect to
observable behaviour such as other volatile accesses - it can even be
omitted altogether. A volatile asm statement is ordered with respect to
Just use asm("nop"); unless you really really really need something
else (and then you *know* you do, instead of cargo-culting something).
The memory clobber is not "cargo-culting" - it is a very useful tool in
some circumstances, and can be particularly useful in cases like this
and ensures it is "executed"
at that point in the code. The memory clobber tells gcc to write out
the values of any variables in memory before the instruction, and read
them in again after the instruction - this will make your variable view
in the debugger more accurate (since the compiler won't move variable
changes across the breakpoint).
That is misleading. The compiler is perfectly free to keep variables
in registers (unless those variables are *also* volatile, or have their
address taken, etc.)
I can see how my wording here could be misunderstood. If a variable is
allocated in memory, then any writes to it must be flushed to memory
when the memory clobber is reached - the compiler cannot hold the value
in a register. And any memory variables that had previously had cached
values in registers must be re-read after the clobber. But local
variables that live solely within registers will remain there.
If you want easier debugging, use -O0 or -Og.
-Og is good (and usually the best choice for debugging) - but if you are
interested in looking at the generated assembly, then I advise against
-O0. -O1 gives code that is easier to follow than -O0. Also note that
with -O0, you have less static analysis for warning messages.