2 ms·
That's the crux of the matter: if i is replaced with 3 on the second line, what do you think prevents an ARM CPU from hoisting the x[3] above the i load first l
by gpderetta 3y ago
That's the crux of the matter: if i is replaced with 3 on the second line, what do you think prevents an ARM CPU from hoisting the x[3] above the i load first line?
In practice the volatile cast might prevent current GCCs from performing constant propagation, so this exact code sequence might work, but it is extremely fragile and can break for some variations:
if (int i2 = volatile_lvalue(int, i); i2 == 3) {
y = x[i2]; // i2 is replaced, no data dependency
}
or
if (volatile_lvalue(int, i)) {
y = x[i-i]; // data dependency becomes a control dependency
}
You also have to be careful to what you do with y and with any value derived form it.
As currently there is no way to efficiently implement consume you have to do with what you have, so for example the Linux kernel does use volatile casts and compilation barriers to implement LOAD_ONCE, but then has a large manual that documents what operations are currently considered safe and what are known to break.
That's hardly a specification that can be put in a standard and you can't really can reason about the semantics of it. Linus himself has considered multiple time if it is worth the hassle and whether the kernel should just switch to acquire everywhere now that arm and power have relevant cheap barriers.
- kazinator 3y agoAh, for that problem, I'd prefer to have read_barrier() and write_barrier() type primitives that take no arguments.