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