Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the compiler allowed to constant-fold a local volatile?

Tags:

Consider this simple code:

void g();  void foo() {     volatile bool x = false;     if (x)         g(); } 

https://godbolt.org/z/I2kBY7

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.

like image 471
Max Langhof Avatar asked Oct 16 '19 12:10

Max Langhof


1 Answers

I think [intro.execution] (paragraph number vary) could be used to explain MSVC behavior:

An instance of each object with automatic storage duration is associated with each entry into its block. Such an object exists and retains its last-stored value during the execution of the block and while the block is suspended...

The standard does not permit elimination of a read through a volatile glvalue, but the paragraph above could be interpreted as allowing to predict the value false.


BTW, the C Standard (N1570 6.2.4/2) says that

An object exists, has a constant address, and retains its last-stored value throughout its lifetime.34


34) In the case of a volatile object, the last store need not be explicit in the program.

It is unclear if there could be a non-explicit store into an object with automatic storage duration in C memory/object model.

like image 84
Language Lawyer Avatar answered Oct 07 '22 09:10

Language Lawyer