Reputation: 107
Given below code, will CPU reorder STORE a and STORE b ? From code logic, a and b are independent.
int* __attribute__ ((noinline)) GetMemAddr(int index) {
static int data[10];
return &data[0];
}
void fun() {
int *a=GetMemAddr(1); //use different args to get same address to avoid optimiztion
int *b=GetMemAddr(2);
*a=1;
*b=3;
}
Upvotes: 0
Views: 128
Reputation: 182761
The CPU can re-order the two stores so long as it doesn't violate any guarantee that the CPU has to provide. It's the compiler's job to generate code for the CPU that doesn't allow it to make optimizations that cause the generated code to violate the C standard. To put it another way, a C compiler takes code that it promises will run according to the rules of the C standard and turns it in to assembly code that will in fact run according to the rules of the C standard by relying on the CPU to run according to the rules of its architecture specification.
So if those two stores happen to be to the same memory location, no "optimization" is possible that permits the wrong result to be observed from that very same thread. That would violate the C standard, so a non-broken compiler will generate whatever code it takes for a non-broken CPU to not do that. However, nothing prevents optimizations that might cause other threads to see strange intermediary results unless your platform's threading standard says something different (and none that I know of do).
If you want cross-thread guarantees, you have to use atomic operations, mutexes, or whatever else your platform provides for that. If you just want code that happens to work, you'll need platform-specific knowledge about what optimizations your platform is actually capable of and what methods there are to disable them on that platform (volatile
, compiler flags, whatever).
Upvotes: 1
Reputation: 133919
Your question is pretty much pointless as it is now.
int* __attribute__ ((noinline)) GetMemAddr(int index) {
static int data[10];
return &data[0];
}
void fun() {
int *a=GetMemAddr(1); //use different args to get same address to avoid optimiztion
int *b=GetMemAddr(2);
*a=1;
*b=3;
}
this compiled with GCC 7.3 and -O3
elides the first call to GetMemAddr
completely because it doesn't have side effects. It elides the assignment *a=1
too. noinline
means that the function must not be inlined. It doesn't mean that it needs to be called at all.
The only proper way to actually avoid elision is to declare a
and b
as volatile int *
s. That way the stores are also to be kept in order. However, it is still not in any way guaranteed that these stores be atomic, so another thread can see funny things happening - for those you need to use the C11 atomic features, or a compiler extension/guarantee.
Upvotes: 3