Consider this simple code:
void g();
void foo()
{
volatile bool x = false;
if (x)
g();
}
You can see that neither gcc
nor clang
optimize out the potential call to g
. This is correct in my understanding: The abstract machine is to assume that volatile
variables may change at any moment (due to being e.g. hardware-mapped), so constant-folding the false
initialization into the if
check would be wrong.
But MSVC eliminates the call to g
entirely (keeping the reads and writes to the volatile
though!). Is this standard-compliant behavior?
Background: I occasionally use this kind of construct to be able to turn on/off debugging output on-the-fly: The compiler has to always read the value from memory, so changing that variable/memory during debugging should modify the control flow accordingly. The MSVC output does re-read the value but ignores it (presumably due to constant folding and/or dead code elimination), which of course defeats my intentions here.
Edits:
The elimination of the reads and writes to
volatile
is discussed here: Is it allowed for a compiler to optimize away a local volatile variable? (thanks Nathan!). I think the standard is abundantly clear that those reads and writes must happen. But that discussion does not cover whether it is legal for the compiler to take the results of those reads for granted and optimize based on that. I suppose this is under-/unspecified in the standard, but I'd be happy if someone proved me wrong.I can of course make
x
a non-local variable to side-step the issue. This question is more out of curiosity.
volatile
and their consequences (doesvolatile
prevent e.g. escape analysis?) and whether there is some wiggle room in the standard to sanction MSVC's behavior here. – Intricacyvolatile
was meant to support memory-mapped I/O registers. Read them five times in a row, get five different values. – Cretinismg()
gets used. – Histaminex
even though result isn't used and it believes it knows the result of that read... :) – Histaminex
value isn't going to change, like passing address ofx
to unknown function, or taking an address. Even though in latter case optimizer obviously failed. – Histamineg()
. So, perhaps optimizing the second part, when you already know what the prvalue is going to be, is legal. – Pressworkvolatile
can be optimized on the reflectors a couple months back. – Narcotismvolatile
keyword than dictated by the standard. It is important to know exactly which compiler flags you're using to build this. In particular:/volatile
. – Scurrility/volatile:iso
and/volatile:ms
though. – Intricacy