Michael Matz wrote:
Don't you need the barrier before. This is to ensure it completed the
condition test completely first before it then processed the assignment
expression.
if(condition) {
somebarrier();
*p = value;
}
The issue is not that the store is done too late, but that a
write-access is done too early.
No. The initial cause for this needless thread was that a store was moved
down, out of its control region. Of course it doesn't help when people
keep shifting their point of focus in such discussions. Now it already
moved to fear that GCC would somehow introduce new traps. Without the
people discussing about that fear even bothering to check if that really
happens :-(
No the initial problem was that the store was done when the code
execution path clearly indicates no store should be performed. The
store was a re-write of the same and existing value in *p.
The optimizer tried to interleave the compare/test with the load from
memory. By inserting the barrier between the test and assignment that
would stop that interleave from taking place, since it can't optimize
across the barrier, it must perform the test and branch first, before it
stores to memory.
It may optionally interleave the 'load from memory into register for
"value" variable'. This is would be a speculative load and this would
be safe, as the value or 'value' may go unused (thrown away) if the
branch is taken to skip the store to *p.
Now the original case was show as a simple function with just the
if(condition) {
*v = 1
}
I would agree with you that a barrier() afterwards would be needed if
there was any statement beyond that close brace of the test within the
same function. This is to ensure the store is not deferred any later,
that maybe accessed via another alias to the same memory for which the
compiler could not see at compile time.
But there isn't, there is a function return, which does the trick nicely.
A purist perspective this makes it:
void foo(int value) {
if(condition) {
somebarrier();
*v = value;
somebarrier();
}
// more statements here that may access *v
// if you don't have any statements here, then you can omit the 2nd
somebarrier() call
return;
}
Darryl