assume we have the following code
int test(bool* flag, int* y)
{
if(*y)
{
*flag = false;
else
{
*flag = true;
}
}
note that the compiler can prove here that writing to flag will always happen, so I think the following one is allowed(which I don't think is optimization at all, but just for the example)
int test(bool* flag, int* y)
{
*flag = true;
if(*y)
{
*flag = false;
}
}
so now, we write true to flag also if y!=0
, but from the point of the as-if rule, this looks valid.
but I still think, that this optimization is weird, assume that *y = true
always, so the flag is always false, so if some other thread reads the flag variable, he may see true, although it should never happen, so does it break the as-if rule?
is the optimization valid?
Addition: the case of non-atomic is clear since it's UB, and all bets are off, but if the flag is atomic with relaxed ordering, what then?
The transformation is valid (based only on what the standard(s) define, i.e. assuming strict aliasing).
It is impossible for any other thread to observe the intermediate value, because no thread is allowed to read *flag
while the function executes on another thread.
*flag
isn't an atomic object, the function always writes to *flag
and the other thread reading it unsynchronized therefore causes undefined behavior as it is a data race regardless of the path taken.
If flag
had type (std::)atomic_bool*
instead, then, regardless of memory ordering used, the transformation wouldn't generally be valid, because, as you said, it would become possible for another thread to observe a value that it shouldn't have been able to observe.