Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When can a volatile variable be optimized away completely?

Consider this code example:

int main(void)
{
  volatile int a;
  static volatile int b;

  volatile int c;
  c = 20;
  static volatile int d;
  d = 30;

  volatile int e = 40;
  static volatile int f = 50;

  return 0;
}

Without volatile a compiler could optimize away all the variables since they are never read from.

I think a and b can be optimized away since they are completely unused, see unused volatile variable.

I think c and d can not be removed since they are written to, and writes to volatile variables must actually happen. e should be equivalent to c.

GCC does not optimize away f, but it also does not emit any instruction to write to it. 50 is set in a data section. LLVM (clang) removes f completely.

Are these statements true?

  1. A volatile variable can be optimized away if it is never accessed.
  2. Initialization of a static or global variable does not count as access.
like image 226
Tor Klingberg Avatar asked Jan 07 '15 09:01

Tor Klingberg


2 Answers

Writes to volatile variables (even automatic ones) count as observable behaviour.

C11 (N1570) 5.1.2.3/6:

The least requirements on a conforming implementation are:

— Accesses to volatile objects are evaluated strictly according to the rules of the abstract machine.

— At program termination, all data written into files shall be identical to the result that execution of the program according to the abstract semantics would have produced.

— The input and output dynamics of interactive devices shall take place as specified in 7.21.3. The intent of these requirements is that unbuffered or line-buffered output appear as soon as possible, to ensure that prompting messages actually appear prior to a program waiting for input.

This is the observable behavior of the program.

The question is: does initialization (e, f) count as an "access"? As pointed out by Sander de Dycker, 6.7.3 says:

What constitutes an access to an object that has volatile-qualified type is implementation-defined.

which means it's up to the compiler whether or not e and f can be optimized away - but this must be documented!

like image 192
M.M Avatar answered Oct 05 '22 23:10

M.M


Strictly speaking any volatile variable that is accessed (read or written to) cannot be optimized out according to the C Standard. The Standard says that an access to a volatile object may have unknown side-effects and that accesses to volatile object has to follow the rules of the C abstract machine (where all expressions are evaluated as specified by their semantics).

From the mighty Standard (emphasis mine):

(C11, 6.7.3p7) "An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2.3."

Following that even a simple initialization of a variable should be considered as an access. Remember the static specifier also causes the object to be initialized (to 0) and thus accessed.

Now compilers are known to behave differently with the volatile qualifier, and I guess a lot of them will just optimize out most of the volatile objects of your example program except the ones with the explicit assignment (=).

like image 42
ouah Avatar answered Oct 06 '22 00:10

ouah