4

Say, I have this code:

int f() {
  volatile int c;
  c=34;
  return abc();
}

The volatile int c is never read. But it is marked as volatile, can the compiler eliminate it altogether? My testing in Visual C++ 2010 shows contradictory results. In VC++, if I enable optimization (maximizing speed) the above function contains a local variable called c (by looking at the generated assembly listing). But, instead of using assignment operator, I also tried to initialize the variable by a compiler intrinsic function like memset() (and enable using compiler intrinsic functions), the variable is eliminated.

int f() {
  volatile int c;
  memset((void*)&c,34, 1); 
  return abc();
}

So according to the C++ standard, can compiler eliminate the volatile int c? I'm thinking probably there is some inconsistent behaviour in VC++ related to how intrinsic functions optimize volatile variable.

JavaMan
  • 4,954
  • 4
  • 41
  • 69
  • How do you perform the initialisation with memset? What does the code look like (`memset(&c, 34, 1)` should not compile!). – R. Martinho Fernandes May 24 '13 at 10:50
  • memset((void*)&c,34, 1); probably c is considered void *, no longer volatile – JavaMan May 24 '13 at 11:18
  • 3
    For Finagle's sake *don't use casts as hammers*. – R. Martinho Fernandes May 24 '13 at 11:22
  • 2
    The "inconsistent" behavior is simply that "if you don't tell the function that it is operating on volatile memory (by casting away volatile-ness), then it won't know that it is operating on volatile memory". Also, undefined behavior and evil casts. – jalf May 24 '13 at 11:32
  • 1
    See my own question: http://stackoverflow.com/questions/15538366/can-memset-function-call-be-removed-by-compiler - it's `memset` that gets optimized-out. After that is done, there is nothing accessing volatile variable, so compiler is free to remove it. – j_kubik Aug 22 '13 at 02:54

2 Answers2

7

memset((void*)&c,34, 1); has undefined behaviour (§7.1.6.1/6). The compiler is therefore allowed to produce any result.

If an attempt is made to refer to an object defined with a volatile-qualified type through the use of a glvalue with a non-volatile-qualified type, the program behavior is undefined.

Please, do not use casts like that, much less C-style casts. When one does not know what the correct C++ cast is for a certain situation, it is likely a situation where one should not be casting anything.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
4

So according to the C++ standard, can compiler eliminates the volatile int c?

No. volatile-qualified objects are used for reading from or writing to the hardware, and the side-effects of assigning a volatile object are observable.

Therefore, in compliance with the constraints on optimizations placed by the so-called "as-if" rule, conforming implementations are not allowed to optimize away c. The "as-if" rule is formally introduced in Paragraph 1.9/1 of the C++11 Standard:

The semantic descriptions in this International Standard define a parameterized nondeterministic abstract machine. This International Standard places no requirement on the structure of conforming implementations. In particular, they need not copy or emulate the structure of the abstract machine. Rather, conforming implementations are required to emulate (only) the observable behavior of the abstract machine as explained below

And the concept of "observable behavior" is defined in paragraph 1.9/8:

The least requirements on a conforming implementation are:

Access 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 one of the possible results that execution of the program according to the abstract semantics would have produced.

— The input and output dynamics of interactive devices shall take place in such a fashion that prompting output is actually delivered before a program waits for input. What constitutes an interactive device is implementation-defined.

These collectively are referred to as the observable behavior of the program. [...]

Since access to volatile objects must be evaluated strictly according to the rules of the abstract machine, compilers are not allowed to optimize away c and the corresponding assignment operation.

Community
  • 1
  • 1
Andy Prowl
  • 124,023
  • 23
  • 387
  • 451