[llvm] [RFC][LangRef] Specify that the accessed bytes of concurrent atomics must be either disjoint or the same (PR #204329)
Fabian Ritter via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 14 00:56:45 PDT 2026
================
@@ -4057,12 +4057,18 @@ Given that definition, R{sub}`byte` is defined as follows:
- Otherwise, if R{sub}`byte` may see exactly one write,
R{sub}`byte` returns the value written by that write.
- Otherwise, if R is atomic, and all the writes R{sub}`byte` may
- see are atomic, it chooses one of the values written. See the {ref}`Atomic
+ see are atomic, and R and the writes all access the exact same set of
+ bytes, it chooses one of the values written. See the {ref}`Atomic
Memory Ordering Constraints <ordering>` section for additional
constraints on how the choice is made. Targets may impose additional
requirements on R and the writes it may see based on their `syncscope`.
- Otherwise R{sub}`byte` returns `undef`.
+Defined atomic accesses cannot tear: Two byte subaccesses R{sub}`byte1`,
+R{sub}`byte2` of an atomic read R cannot read from different atomic
+writes W{sub}`1`, W{sub}`2` if both read subaccesses, R{sub}`byte1`,
----------------
ritter-x2a wrote:
> I am a bit concerned about the case where byte 0 can see W1 and W2, and byte 1 can see W1 and W3. It seems like your definition would allow the sub-reads to use any combination of different writes. But maybe that situation cannot arise because it would have been a write-write race somewhere before already?
Yes, that situation can't happen: If byte 0 can see W1 and W2 and byte 1 can see W1 and W3, then W1 overlaps partially with W2 and with W3 and they are not in hb. The other addition of this PR makes involved reads therefore return undef.
(I suppose there are also other situations where you can get the may-see situation you describe with additional partially overlapping writes that overshadow W2 and W3 partially, I believe that would also cause undef reads).
If we wanted to define partially overlapping atomics to behave properly atomically (which we currently don't), we would need additional constraints.
>I think under the UB you have, your definition is equivalent to the following that I find easier to understand -- or did I miss something?
>
>>Defined atomic accesses cannot tear: If a byte subaccess R{sub}byte1 of
an atomic read R reads from W{sub}1, then all other byte subaccesses R{sub}byte2 of R that can see W{sub}1 must also read from W{sub}1.
Yes, I think that works, and I like the simpler formulation. I've updated the PR (with minor adjustments: W{sub}1 doesn't need an index and it should be an atomic write).
For the record: There would be a problem with it if partially overlapping atomics were supposed to behave properly atomically (again: which we currently don't want):
Then, this constraint would (in my opinion: wrongly) disallow in the following scenario that L reads anything from S2:
```
thread 1:
S1: store atomic unordered to bytes {0, 1, 2, 3} starting at %p
Rel: store atomic release %flag
thread 2:
S2: store atomic unordered to bytes {0, 1} starting at %p
Acq: load atomic acquire %flag // assume it reads from Rel and establishes synchronization and hb
L: load atomic unordered from bytes {0, 1, 2, 3} starting at %p // should be allowed to read {0, 1} from S2 and {2, 3} from S1 if partially overlapping atomics behaved atomically
```
https://github.com/llvm/llvm-project/pull/204329
More information about the llvm-commits
mailing list