I happen to dig into C and lock free programming. Fiddling with it I wonder what guarantee gcc can give me that a program is executed the exact same way I write it down and no register optimization is performed in a certain step and no operation is changed in its ordering.
As I currently understand it, it guarantees that memory operations happen in the very same order and that method calls happen in the same order along with themself and memory operations. In between reordering might ocure.
The register optimization can be switched off by using the volatile keyword.
Are there any additional guarantees or corner cases that C and especially gcc has implied?
A compiler is only required to not change the meaning of a program.
The meaning of a program is given by the semantic of its C statements, for example thevolatile qualifier is a way to reificate at the semantic level the interaction with external agents.
volatile alone however is useless when it comes to threads synchronization, it has local effects only.
So you should only imply what the standard of C implies, if the standard given no ordering semantic to a statement nor any side effect, then there is none.
In order to optimize out some code the compiler has to prove that the optimization doesn't change the meaning.
This is in general an hard (or even undecidable) problem, so it is done only in simple context.
Consider
#include <stdio.h>
int simple(const int a, const int b)
{
int c = a + b; //3x Memory operation?
int d = c*c; //2x Memory operation?
return d+d; //Memory operation?
}
int main()
{
int a = 0; //Memory operation?
int b = 0; //Memory operation?
a = simple(2, 3); //Function call + Memory operation?
b = simple(3, 4); //Function call + Memory operation?
printf("%d %d\n", a, b); //Function call + 3x Memory operation?
return 0;
}
The C standard dictates that a = simple(2, 3); is executed before b = simple(3, 4); as the end of an expression is a sequence point.
This is the code generated by gcc with full optimization
lea 0x18f0(%rip),%rcx # 0x100403030, "%d %d\n"
mov $0x62,%r8d
mov $0x32,%edx
callq 0x100401110 <printf>
I used cygwin, so the ABI is Windows's one. This is equivalent to
printf("%d %d\n", 50, 98);
This is an ad hoc example, the function simple is pure and takes compile time constant expressions, so the result is known at compile time.
This is the proof that gcc needed to optimized out the calls.
In writing lock free code you shouldn't worry about compiler optimizations at all as long as you use the correct semantic (e.g. volatile for having read-write accesses as side effects for the sake of optimization only).
What you really should be worried about is memory ordering as pointed out in my comment.
C11 finally reificates all this in its memory model.
If your code depends on not reordering the operations and do not any other optimization it is simply "undefined behavior".
If you search for such guarantees you simply search for a guarantee that you write a broken program which executes correct. You should use the semantic which is represented by your used language. If you need assumptions on how the language implements the actions on a given os and machine, you are totally on the wrong path!
If you actually have some kind of guarantee for a actual compiler version and a used underlaying os this will not be guaranteed in the feature! So the wording "guarantee" is also not really true. If it must the simple answer is: There is no guarantee at all! The language have a semantic and the compiler guarantee to implement it. Not more at all!.
Ordering guarantees between threads in C are only achievable with stdatomic.h from C11 or compiler-specific extensions. In all other cases the only thing that the compiler needs to guarantee is that the externally visible behavior of the program (this could be roughly translated to: function calls and references to memory not under the compilers control) is the same as interpreted according to the standard. Before C11 threads didn't exist from the point of view of the C standard, so it didn't concern itself with threaded behavior.