0

Is the compiler allowed to optimize the code flow by moving statements (not parts of an expression) from before a volatile access to afterwards, or from after a volatile access to before it.

In reference to my answer to SO : is volatile required for synchronous ISR access

Objections to my answer has suggested that the use of volatile does not cause the generalized machine for C++ (and C) to ensure that all operations before hand are completed.

My reading of cppreference : const volatile

that is, within a single thread of execution, volatile accesses cannot be optimized out or reordered with another visible side effect that is sequenced-before or sequenced-after the volatile access. This makes volatile objects suitable for communication with a signal handler, but not with another thread of execution

Is that for the case in my answer - single core operation the following should be true.

  • The results are visible as fast as possible - there may be a point where a change to a volatile hasn't been written, but if it is written, then the single core would see it in a signal handler, (or an ISR).
  • A compliant C++ compiler would not be able to re-order operations around the volatile write as it is a visible side effect.

My answer on this thread assumed the particular case was a single core CPU, and that C++11 was not applicable, so I would prefer answers within that scope.

mksteve
  • 12,614
  • 3
  • 28
  • 50
  • Compiler can reorder everything as long as sequenced observable side-effects (including volatile accesses) occur in program order - see [intro.execution] – Cubbi Oct 02 '17 at 22:19
  • @Cubbi Almost nobody actually understands the standard to be saying that. For example, most x86 compilers permit volatile writes to be re-ordered. (Look at the generated assembly, there will be no memory barriers. So the writes can take place in any order.) – David Schwartz Oct 10 '17 at 17:31
  • @DavidSchwartz the x86 compilers are doing their job correctly and treating volatile accesses as observable side effects. – Cubbi Oct 10 '17 at 17:37
  • @Cubbi Agreed. But they don't ensure they occur in program order. It would take memory barriers to do that, and compilers don't produce them. They allow the writes to occur in any order, even though they treat them as observable side effects. – David Schwartz Oct 10 '17 at 17:40
  • @DavidSchwartz why do you expect a barrier? If does nothing here. There is no inter-thread synchronization. (more on topic, there is also no compiler barrier - for that OP needs a std::atomic_signal_fence) – Cubbi Oct 10 '17 at 17:49
  • @Cubbi I don't expect a barrier. I fully understand that compilers are not required to ensure that writes to `volatile`s occur in program order. You're the one who said that that the writes had to occur in program order -- I'm the one who said that you're wrong about that. – David Schwartz Oct 10 '17 at 18:02
  • @DavidSchwartz it is program order. Or, if you prefer standardese, "strictly according to the rules of the abstract machine". If the program says sequenced-before, the access will be sequenced before, or very real equipment will fail. – Cubbi Oct 10 '17 at 18:37
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/156385/discussion-between-david-schwartz-and-cubbi). – David Schwartz Oct 10 '17 at 18:39

1 Answers1

1

The C++ standard does not distinguish between what the code flow says and what the code does. So this, and all questions about code flow rather than observable behavior, is a platform-specific question.

A compliant C++ compiler would not be able to re-order operations around the volatile write as it is a visible side effect.

Nobody understands the standard to say that. This is why x86 compilers do not put memory barriers around volatile operations and do permit re-ordering by the CPU.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • A memory barrier relates to multi-core behavior. I am asking about the behavior of a single core machine, and whether a compiler can re-order a =f(x); b = g(y); when one of the variables (a,b,x,y) is volatile. – mksteve Oct 01 '17 at 23:22
  • You seem to have answered a different question to I asked. I asked whether the compiler can re-order statements. Your statement, talks about whether the CPU can re-order the instructions. I accept the CPU is able to re-order instructions, but only if it gets the right result. – mksteve Oct 01 '17 at 23:40
  • @mksteve A memory barrier relates to multi-core behavior, sure, but it also relates to single-core behavior. A memory barrier between two writes, for example, assures that those two writes actually take place in order. (And the "as a visible side effect" is also platform-specific because there is no platform-neutral notion of write visibility.) – David Schwartz Oct 01 '17 at 23:41
  • 1
    @mksteve As I said, that's platform-specific. the C++ standard doesn't distinguish between what the compiler can do and what the CPU could do. How could it? It only says what has to happen and doesn't care what components accomplish it or how they do so. What the *compiler* can do, as distinct from what the CPU can do, is a platform and implementation-specific question. The end result must follow the standard, but which part has what responsibility to achieve that result is platform-specific. – David Schwartz Oct 01 '17 at 23:42