[llvm] [Docs][AMDGPU] availability/visibility in addrspace(3) (PR #212707)

Sameer Sahasrabuddhe via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 30 02:54:42 PDT 2026


https://github.com/ssahasra updated https://github.com/llvm/llvm-project/pull/212707

>From fb93fdd95e607d4c7e062adee4a0bf5f2d4cac66 Mon Sep 17 00:00:00 2001
From: Sameer Sahasrabuddhe <sameer.sahasrabuddhe at amd.com>
Date: Wed, 29 Jul 2026 13:47:36 +0530
Subject: [PATCH 1/2] [Docs][AMDGPU] availability/visibility in addrspace(3)
 and other cleanups

addrspace(3) on AMDGPU corresponds to LDS, which is a fast memory directly
accessed by all threads in a workgroup (there is no intervening cache). Thus,
any accesses to this addrspace have built-in availability and visibility at
"workgroup" scope.

Other cleanups:

- Update the intrinsic names to match the implementation.
- Explain store-available and load-visible.
- Rename to "make-available" and "make-visible" for consistent spelling.
---
 llvm/docs/AMDGPUMemoryModel.md | 119 ++++++++++++++++++++++-----------
 llvm/docs/AMDGPUUsage.rst      |   2 +
 2 files changed, 81 insertions(+), 40 deletions(-)

diff --git a/llvm/docs/AMDGPUMemoryModel.md b/llvm/docs/AMDGPUMemoryModel.md
index c057909b0539c..68e989afb6502 100644
--- a/llvm/docs/AMDGPUMemoryModel.md
+++ b/llvm/docs/AMDGPUMemoryModel.md
@@ -126,19 +126,44 @@ these necessary conditions, and hence they can be explained using the rules from
 either memory model. But the new intrinsics and metadata *opt out* of the LLVM
 memory model, and can only be explained using the AMDGPU memory model.
 
+:::{note}
+We introduce new intrinsics because metadata cannot be used to express the
+availability and visibility of ordinary
+load/store operations, because the scope is necessary for correctness. In a
+hypothetical operation like this:
+
+```llvm
+store ptr addrspace(1) %ptr, <4 x i32> %value, !mmra !{!"amdgcn-av", !"workgroup"}
+```
+
+If the metadata is dropped or ignored, there is no guarantee that the store
+will become available at the intended scope. In implementation terms, the
+store may be completed at a nearer cache than the one required for that
+scope. A corresponding *load-visible* that does not access the same near
+cache will fail to observe this store.
+:::
+
 (amdgpu-store-available)=
 
 ### store-available
 
+A *store-available* operation `X` writes data to the specified location, and
+then propagates those side-effects up to its scope instance `S` and also all
+the subscope instances of `S` that contain `X`.
+
 ```llvm
- at llvm.amdgcn.av.global.store.b128(ptr, value, scope)
-store atomic [syncscope("<target-scope>")]
-atomicrmw    [syncscope("<target-scope>")]
-cmpxchg      [syncscope("<target-scope>")]
+ at llvm.amdgcn.av.store.b128(%addr, %value, metadata !scope)
 ```
 
-The `@llvm.amdgcn.av.global.store.b128` intrinsic performs a non-atomic
-*store-available* operation on `ptr` with scope `scope`.
+The `@llvm.amdgcn.av.store.b128` intrinsic performs a non-atomic
+*store-available* operation on `%addr` with scope `!scope`. See
+{ref}`amdgpu-av-load-store` for details.
+
+```llvm
+store atomic ..., [syncscope("<target-scope>")]
+atomicrmw    ..., [syncscope("<target-scope>")]
+cmpxchg      ..., [syncscope("<target-scope>")]
+```
 
 An atomic operation that results in a store operation is a *store-available*
 operation with scope `syncscope`.
@@ -147,38 +172,47 @@ operation with scope `syncscope`.
 
 ### load-visible
 
+A *load-visible* operation `Y` retrieves the state of the specified location
+from its scope instance `S`, and then loads the value at that location. In
+addition, it makes the retrieved state visible to all subscope instances of `S`
+that contain `Y`.
+
 ```llvm
- at llvm.amdgcn.av.global.load.b128(ptr, scope)
-load atomic  [syncscope("<target-scope>")]
-atomicrmw    [syncscope("<target-scope>")]
-cmpxchg      [syncscope("<target-scope>")]
+%value = @llvm.amdgcn.av.load.b128(%addr, metadata !scope)
 ```
 
-The `@llvm.amdgcn.av.global.load.b128` intrinsic performs a non-atomic
-*load-visible* operation on `ptr` with scope `scope`.
+The `@llvm.amdgcn.av.load.b128` intrinsic performs a non-atomic *load-visible*
+operation on `%addr` with scope `!scope`. See {ref}`amdgpu-av-load-store` for
+details.
+
+```llvm
+%value = load atomic ..., [syncscope("<target-scope>")]
+%value = atomicrmw   ..., [syncscope("<target-scope>")]
+%value = cmpxchg     ..., [syncscope("<target-scope>")]
+```
 
 An atomic operation that results in a read operation is a *load-visible*
 operation with scope `syncscope`.
 
-:::{note}
-Metadata cannot be used to model this using ordinary load/store operations,
-because the scope is necessary for correctness. In a hypothetical operation
-like this:
+### addrspace(3) Accesses
 
-```llvm
-store ptr, data, !mmra !{!"amdgcn-av", !"workgroup"}
-```
+Any access to `addrspace(3)` (aka LDS or local) always results in a *store-available* or
+*load-visible* operation with scope "workgroup".
 
-If the metadata is dropped or ignored, there is no guarantee that the store
-will become available at the intended scope. In implementation terms, the
-store may be completed at a nearer cache than the one required for that
-scope. A corresponding *load-visible* that does not access the same near
-cache will fail to observe this store.
-:::
+Any access to `addrspace(0)` (aka flat or global) always results in a
+*store-available* or *load-visible* operation with scope "workgroup", if the
+flat address resolves to `addrspace(3)`.
+
+```{note}
+This is independent of the `syncscope` of an atomic access. For example, Even if
+a `store atomic` specifies a smaller `syncscope` such as "wavefront", the
+side-effects are made available at "workgroup" scope. In other words, the scope
+for atomicity is not always the same as the scope for availability/visibility.
+```
 
 (amdgpu-av-metadata)=
 
-### AV Metadata
+### !"amdgcn-av" metadata
 
 ```llvm
 !mmra !{!"amdgcn-av", !"none"}
@@ -193,7 +227,12 @@ release` or `load atomic acquire`), the metadata does not affect the
 availability or the visibility of the access performed by the operation itself.
 It only affects the synchronization of other memory accesses.
 
-### MakeAvailable and MakeVisible
+### make-available and make-visible
+
+*make-available* and *make-visible* operations propagate certain side-effects
+from or to the specified scope respectively. They are similar to the
+*store-available* and *load-visible* operations, except that their effect is not
+limited to specific locations.
 
 ```llvm
 store atomic [syncscope("<target-scope>")] <ordering> [, !mmra !{!"amdgcn-av", !"none"}]
@@ -204,24 +243,24 @@ fence        [syncscope("<target-scope>")] <ordering> [, !mmra !{!"amdgcn-av", !
 ```
 
 A synchronizing operation with at least `release` ordering is a
-`MakeAvailable` operation with scope `syncscope`, if it is not marked as
+*make-available* operation with scope `syncscope`, if it is not marked as
 `!{!"amdgcn-av", !"none"}`.
 
 A synchronizing operation with at least `acquire` ordering is a
-`MakeVisible` operation with scope `syncscope`, if it is not marked as
+*make-visible* operation with scope `syncscope`, if it is not marked as
 `!{!"amdgcn-av", !"none"}`.
 
 ```llvm
 ; This includes the following operations:
 ; - The atomic store at "agent" scope,
 ; - A store-available operation at "agent" scope on `ptr`,
-; - A `MakeAvailable` operation at "agent" scope that affects previous memory accesses.
+; - A *make-available* operation at "agent" scope that affects previous memory accesses.
 store atomic syncscope("agent") release ptr
 
 ; This includes the following operations:
 ; - The atomic store at "agent" scope,
 ; - A store-available operation at "agent" scope on `ptr`.
-; Notably, it does not include a `MakeAvailable` operation on other memory accesses.
+; Notably, it does not include a *make-available* operation on other memory accesses.
 store atomic syncscope("agent") release ptr, !mmra !{!"amdgcn-av", !"none"}
 ```
 
@@ -240,10 +279,10 @@ following holds:
 
 - `X` is `W` itself, and `W` is a *store-available* operation, or,
 
-- `X` is a `MakeAvailable` operation that follows `W` in program order,
+- `X` is a *make-available* operation that follows `W` in program order,
   or,
 
-- `X` is a `MakeAvailable` operation whose scope instance includes `W`,
+- `X` is a *make-available* operation whose scope instance includes `W`,
   and there is an availability operation `Z` on `W` such that:
 
   - `Z` happens-before `X`, and,
@@ -255,13 +294,13 @@ subscope instance of `S` that also includes `W`.
 ### Visibility Operation
 
 An operation `Y` is a *visibility operation* on a write `W` if `Y` is a
-*load-visible* operation to the same address, or a `MakeVisible` operation,
+*load-visible* operation to the same address, or a *make-visible* operation,
 and one of the following holds:
 
 - There exists an *availability* operation `X` on write `W` such that:
 
   - `X` happens-before `Y`, and,
-  - `X` and `Y` specify inclusive scopes.
+  - `X` and `Y` have inclusive scopes.
 
   Then `Y` makes `W` visible in the common scope instance `S` of `X` and
   `Y`, and every subscope instance of `S` that includes `Y`.
@@ -340,7 +379,7 @@ The following properties follow from the definitions above:
    outwards" into progressively larger scopes.
 3. **Visibility is bounded by availability.** When a write is available in a
    scope instance, it can be made visible in that scope instance by a visibility
-   operation with the corresponding scope. Subsequent `MakeVisible` operations
+   operation with the corresponding scope. Subsequent *make-visible* operations
    make that write visible into narrower scope instances towards the observer.
 4. **A write can be made visible in a scope instance that does not contain it.**
    The definition of a *visibility operation* anchors scope instances to the
@@ -367,7 +406,7 @@ particular, the following instructions are equivalent.
 
 ```{list-table}
 :header-rows: 1
-:widths: 20 20 60
+:widths: 25 20 55
 
    * - LLVM
      - SPIRV
@@ -387,19 +426,19 @@ particular, the following instructions are equivalent.
    * - `load atomic`
      - `OpAtomicLoad`
      - `MakePointerVisible`. Also `MakeVisible` when order is at least `acquire`.
-   * - `load atomic !{!"amdgcn-av", !"none"}`
+   * - `load atomic`<br>`!{!"amdgcn-av", !"none"}`
      - `OpAtomicLoad`
      - `MakePointerVisible`
    * - `store atomic`
      - `OpAtomicStore`
      - `MakePointerAvailable`. Also `MakeAvailable` when order is at least `release`.
-   * - `store atomic !{!"amdgcn-av", !"none"}`
+   * - `store atomic`<br>`!{!"amdgcn-av", !"none"}`
      - `OpAtomicStore`
      - `MakePointerAvailable`
    * - `fence`
      - `OpMemoryBarrier`
      - `MakeAvailable` when order is at least `release`, and `MakeVisible` when order is at least `acquire`.
-   * - `fence !{!"amdgcn-av", !"none"}`
+   * - `fence`<br>`!{!"amdgcn-av", !"none"}`
      - `OpMemoryBarrier`
      - \-
 ```
diff --git a/llvm/docs/AMDGPUUsage.rst b/llvm/docs/AMDGPUUsage.rst
index e65baa0f48b78..87ba811e1a686 100644
--- a/llvm/docs/AMDGPUUsage.rst
+++ b/llvm/docs/AMDGPUUsage.rst
@@ -2114,6 +2114,8 @@ The AMDGPU backend implements the following LLVM IR intrinsics.
 
    List AMDGPU intrinsics.
 
+.. _amdgpu-av-load-store:
+
 '``llvm.amdgcn.av``' Intrinsics
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

>From 5937ccbb462a7ae592b79a2600d623d807601460 Mon Sep 17 00:00:00 2001
From: Sameer Sahasrabuddhe <sameer.sahasrabuddhe at amd.com>
Date: Thu, 30 Jul 2026 15:21:11 +0530
Subject: [PATCH 2/2] fix minor typo

---
 llvm/docs/AMDGPUMemoryModel.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/docs/AMDGPUMemoryModel.md b/llvm/docs/AMDGPUMemoryModel.md
index 68e989afb6502..18d56d542cf7e 100644
--- a/llvm/docs/AMDGPUMemoryModel.md
+++ b/llvm/docs/AMDGPUMemoryModel.md
@@ -204,8 +204,8 @@ Any access to `addrspace(0)` (aka flat or global) always results in a
 flat address resolves to `addrspace(3)`.
 
 ```{note}
-This is independent of the `syncscope` of an atomic access. For example, Even if
-a `store atomic` specifies a smaller `syncscope` such as "wavefront", the
+This is independent of the `syncscope` of an atomic access. For example, even if
+a `store atomic` to `addrspace(3)` specifies a smaller `syncscope` such as "wavefront", the
 side-effects are made available at "workgroup" scope. In other words, the scope
 for atomicity is not always the same as the scope for availability/visibility.
 ```



More information about the llvm-commits mailing list