Am Samstag, dem 01.03.2025 um 16:52 +0300 schrieb Alexander Monakov:
> On Sat, 1 Mar 2025, Martin Uecker via Gcc wrote:
>
> > Sorry for being a bit slow. This is still not clear to me.
> >
> > In vect/pr65206.c the following loop can be vectorized
> > with -fallow-store-data-races.
> >
> > #define N 1024
> >
> > double a[N], b[N];
> >
> > void foo ()
> > {
> > for (int i = 0; i < N; ++i)
> > if (b[i] < 3.)
> > a[i] += b[i];
> > }
> >
> > But even though this invents stores these would still seem
> > to be allowed by C11 because they are not detectable to
> > another reader because they write back the same value as
> > read.
> >
> > Is this understanding correct?
>
> No. Imagine another thread running a similar loop, but with
> the opposite condition in the 'if' (b[i] > 3). Then there are
> no data races in the abstract machine, but vectorized code
> may end up with wrong result.
>
> (suppose all odd elements in 'b' are less than three, all even
> are more than three, and the two threads proceed through the
> loop in lockstep; then half of updates to 'a' are lost)
Ah, right. Thank you! So this example would violate C11.
>
> > Does -fallow-store-data-races also create other data races
> > which would not be allowed by C11?
>
> Yes, for instance it allows an unsafe form of store motion where
> a conditional store is moved out of the loop and made unconditional:
>
> int position;
>
> void f(int n, float *a)
> {
> for (int i = 0; i < n; i++)
> if (a[i] < 0)
> position = i;
> }
Now I wonder why this is not allowed in C11. This
is transformed to:
void f(int n, float *a)
{
int tmp = position;
for (int i = 0; i < n; i++)
if (a[i] < 0)
tmp = i;
position = tmp;
}
So if there is a write, no other thread can read or write
position. Thus, the interesting case is when there should
be no write at all, i.e.
void f(int n, float *a)
{
int tmp = position;
position = tmp;
}
and this could undo the store from another thread, so violates
the C11 memory model.
>
> > What was the reason to disallow those optimizations that
> > could be allowed by default?
>
> -fallow-store-data-races guards transforms that we know to be incorrect
> for source code that may become a part of a multithreaded program.
> Are you asking about something else?
I am looking for an example where stores are invented but this
is allowed by C11. So something such as
if (x != 1)
x = 1;
being transformed to
x = 1;
this should not harm another reader for x == 1 and if
there is a writer it is UB anyway, so this should be ok. Does GCC
do such things? And is then then also guarded by the
-falloc-store-data-races flag or not (because it is allowed in C11)?
Martin