This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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.

 From gcc/testsuite/gcc.dg/nop.h:

#if defined (__ia64__) || defined (__s390__) || defined (__s390x__)
#define NOP "nop 0"
#elif defined (__MMIX__)
#define NOP "swym 0"
#else
#define NOP "nop"
#endif

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 observable behaviour.


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 for debugging.


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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]