-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Description
This is a sibling issue to #56450: LLVM will sometimes replace atomicrmw xchg
by atomic store
, specifically when the ordering is relaxed or release, and the result of the xchg
is unused.
However, replacing an RMW by a non-RMW operation like is not sound under the C++ memory model (and LLVM does not seem to implement a fundamentally different model in that regard). Here's a counterexample using pseudocode notation:
Y:=1 rlx
fence(rel)
SWAP(X,0,rlx)
fence(acq)
a := Z rlx
||
Z:=1 rlx
fence(rel)
SWAP(X,0,rlx)
fence(acq)
b := Y rlx
One of the two SWAP has to read-from the other. This is because two RMWs cannot both read-from the same store (the implicit initial store of 0). Without loss of generality, let's assume the SWAP in the 2nd thread reads-from the first. Therefore we now have a synchronization edge from the fence(rel) in the first thread to the fence(acq) in the 2nd thread. Therefore b
must be 1. (In the symmetric case, a
must be 1.)
After the optimization, it is possible for both a
and b
to be 0. This means the optimization introduced new program behavior, and is therefore wrong.
(Thanks to Ori Lahav and Jeehoon Kang.)