The below code example is from a Chinese blog which introduces the effect of volatile
. The left side is the C code; the other is the generated assembly code.
// cordering.c gcc -O2 -S -masm=intel cordering.c
int A;
volatile int B;
void foo() mov eax, DWORD PTR B[rip]
{ mov DWORD PTR B[rip], 0
A = B + 1; add eax, 1
B = 0; mov DWORD PTR A[rip], eax
} ret
As we can see in the assembly code, the side-effect of A
is placed after the side-effect of B
, even though B
is volatile
qualified. However, cppreference.com says:
[W]ithin 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.
Here the side-effect of A
is sequenced before B
, so I think it's illegal for the compiler to do this. Am I right?
As a supplement, the blog said if we want to guarantee the sequence between a volatile
and non-volatile
type, we need to make both volatile
:
// cordering.c gcc -O2 -S -masm=intel cordering.c
volatile int A;
volatile int B;
void foo() mov eax, DWORD PTR B[rip]
{ add eax, 1
A = B + 1; mov DWORD PTR A[rip], eax
B = 0; mov DWORD PTR B[rip], 0
} ret