[llvm] [docs] Reflect C++'s read-write and write-read coherence rules in the LLVM memory model (PR #217849)
Fabian Ritter via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 21 01:49:22 PDT 2026
https://github.com/ritter-x2a created https://github.com/llvm/llvm-project/pull/217849
Currently, the LLVM IR memory model as written allows behaviors of monotonic
atomic operations that violate C++'s [read-write](https://eel.is/c++draft/basic.exec#intro.races-13) and [write-read](https://eel.is/c++draft/basic.exec#intro.races-14) coherence rules.
This PR adds similar rules to the definition of the monotonic memory ordering
to make monotonic atomics behave more like C++'s relaxed atomics.
Without this, translating C++'s relaxed atomics into LLVM's monotonic atomics
is technically incorrect.
Example litmus tests:
1: read-write coherence
```
; thread 0
store atomic i32 1, ptr %p monotonic ; S1
; thread 1
%l0 = load atomic i32, ptr %p monotonic ; L0
store atomic i32 2, ptr %p monotonic ; S2
; thread 2
%l1 = load atomic i32, ptr %p monotonic ; L1
%l2 = load atomic i32, ptr %p monotonic ; L2
```
Here, C++'s [read-write coherence](https://eel.is/c++draft/basic.exec#intro.races-13) rule says that
the execution where `%l0 = 1; %l1 = 2; %l2 = 1` is not allowed (L0
happens-before S2, therefore L0 must read from a store before S2 in the
modification order. If L0 reads 1 from S1, S1 must therefore be before S2 in the
modification order, so the happens-before-ordered loads L1, L2 can't read them
in the opposite order due to read-read coherence.) So far, there is nothing
ruling out this execution in the LLVM memory model.
2: write-read coherence
```
; thread 0
store atomic i32 1, ptr %p monotonic ; S1
; thread 1
store atomic i32 2, ptr %p monotonic ; S2
%l0 = load atomic i32, ptr %p monotonic ; L0
; thread 2
%l1 = load atomic i32, ptr %p monotonic ; L1
%l2 = load atomic i32, ptr %p monotonic ; L2
```
Here, C++'s [write-read coherence](https://eel.is/c++draft/basic.exec#intro.races-14) rule says that
the execution where `%l0 = 1; %l1 = 1; %l2 = 2` is not allowed (S2
happens-before L0, therefore L0 must read from S2 or a later store in the
modification order. If L0 reads 1 from S1, S1 must therefore be after S2 in the
modification order, so the happens-before-ordered loads L1, L2 can't read them
in the opposite order due to read-read coherence.) So far, there is nothing
ruling out this execution in the LLVM memory model, either.
The read-read coherence constraint already existed in the LangRef, I've grouped
it together with the new constraints to improve readability.
write-write coherence is missing from the list because it is already implied by
the earlier "All modification orders must be compatible with the happens-before
order." constraint.
Related change in our formal memory model: https://github.com/ROCm/formal-models/pull/3
>From 9e151d400c245e532b048c6f72b1a6b50f971ed1 Mon Sep 17 00:00:00 2001
From: Fabian Ritter <fabian.ritter at amd.com>
Date: Fri, 21 Aug 2026 04:35:45 -0400
Subject: [PATCH] [docs] Reflect C++'s read-write and write-read coherence
rules in the LLVM memory model
Currently, the LLVM IR memory model as written allows behaviors of monotonic
atomic operations that violate C++'s [read-write](https://eel.is/c++draft/basic.exec#intro.races-13) and [write-read](https://eel.is/c++draft/basic.exec#intro.races-14) coherence rules.
This PR adds similar rules to the definition of the monotonic memory ordering
to make monotonic atomics behave more like C++'s relaxed atomics.
Without this, translating C++'s relaxed atomics into LLVM's monotonic atomics
is technically incorrect.
Example litmus tests:
1: read-write coherence
```
; thread 0
store atomic i32 1, ptr %p monotonic ; S1
; thread 1
%l0 = load atomic i32, ptr %p monotonic ; L0
store atomic i32 2, ptr %p monotonic ; S2
; thread 2
%l1 = load atomic i32, ptr %p monotonic ; L1
%l2 = load atomic i32, ptr %p monotonic ; L2
```
Here, C++'s [read-write coherence](https://eel.is/c++draft/basic.exec#intro.races-13) rule says that
the execution where `%l0 = 1; %l1 = 2; %l2 = 1` is not allowed (L0
happens-before S2, therefore L0 must read from a store before S2 in the
modification order. If L0 reads 1 from S1, S1 must therefore be before S2 in the
modification order, so the happens-before-ordered loads L1, L2 can't read them
in the opposite order due to read-read coherence.) So far, there is nothing
ruling out this execution in the LLVM memory model.
2: write-read coherence
```
; thread 0
store atomic i32 1, ptr %p monotonic ; S1
; thread 1
store atomic i32 2, ptr %p monotonic ; S2
%l0 = load atomic i32, ptr %p monotonic ; L0
; thread 2
%l1 = load atomic i32, ptr %p monotonic ; L1
%l2 = load atomic i32, ptr %p monotonic ; L2
```
Here, C++'s [write-read coherence](https://eel.is/c++draft/basic.exec#intro.races-14) rule says that
the execution where `%l0 = 1; %l1 = 1; %l2 = 2` is not allowed (S2
happens-before L0, therefore L0 must read from S2 or a later store in the
modification order. If L0 reads 1 from S1, S1 must therefore be after S2 in the
modification order, so the happens-before-ordered loads L1, L2 can't read them
in the opposite order due to read-read coherence.) So far, there is nothing
ruling out this execution in the LLVM memory model, either.
The read-read coherence constraint already existed in the LangRef, I've grouped
it together with the new constraints to improve readability.
write-write coherence is missing from the list because it is already implied by
the earlier "All modification orders must be compatible with the happens-before
order." constraint.
Related change in our formal memory model: https://github.com/ROCm/formal-models/pull/3
---
llvm/docs/LangRef.md | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/llvm/docs/LangRef.md b/llvm/docs/LangRef.md
index 82eebd26c0054..d203721914e30 100644
--- a/llvm/docs/LangRef.md
+++ b/llvm/docs/LangRef.md
@@ -4170,10 +4170,23 @@ happens-before must be perfectly overlapping to act atomically.
read-modify-write operation M ({ref}`cmpxchg <i_cmpxchg>` and
{ref}`atomicrmw <i_atomicrmw>`) reads from a perfectly overlapping
`monotonic` (or stronger) write W, W must be immediately before M in
- the relevant modification order. If one atomic read happens before
- another perfectly overlapping atomic read and both are at least
- `monotonic`, the later read must not see an earlier value in the
- address's modification order. This disallows reordering of perfectly
+ the relevant modification order.
+
+ Atomic accesses that are `monotonic` (or stronger) satisfy coherence rules:
+ - read-read coherence: If one atomic read happens before another
+ perfectly overlapping atomic read and both are at least
+ `monotonic`, the later read must not see an earlier value in the
+ address's modification order.
+ - read-write coherence: If an atomic read R happens before a
+ perfectly overlapping atomic write W and both are at least
+ `monotonic`, R must not read from writes that are later than W
+ in the address's modification order.
+ - write-read coherence: If an atomic read R happens after a
+ perfectly overlapping atomic write W and both are at least
+ `monotonic`, R must not read from from writes that are earlier
+ than W in the address's modification order.
+
+ This disallows reordering of perfectly
overlapping `monotonic` (or stronger) operations. If an address is
written `monotonic`-ally by one thread, and other threads
`monotonic`-ally read that address repeatedly with perfectly
More information about the llvm-commits
mailing list