[llvm-branch-commits] [llvm] [AMDGPU][NFC] Extract SIAtomicAddrSpace and fence MMRA parsing from SIMemoryLegalizer (PR #231854)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Oct 14 03:52:44 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-amdgpu

Author: Fabian Ritter (ritter-x2a)

<details>
<summary>Changes</summary>

Determining which memory accesses are ordered by a fence is already
useful in the middle-end; this PR extracts the code to do that from
SIMemoryLegalizer, so that it can be used in middle-end transformations.

So far, unexpected suffix values for the `amdgpu-synchronize-as` were
reported when they were encountered in SIMemoryLegalizer. This PR keeps
that and doesn't report them in the middle end, since that would lead to
a lot of repeated diagnostics for them.

Disclaimer: Claude gave review comments and suggestions that I addressed
during development.

Preparation for ROCM-29879.

Assisted-by: AI

---
Full diff: https://github.com/llvm/llvm-project/pull/231854.diff


3 Files Affected:

- (modified) llvm/lib/Target/AMDGPU/AMDGPUMemoryUtils.cpp (+65) 
- (modified) llvm/lib/Target/AMDGPU/AMDGPUMemoryUtils.h (+45) 
- (modified) llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp (+10-83) 


``````````diff
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUMemoryUtils.cpp b/llvm/lib/Target/AMDGPU/AMDGPUMemoryUtils.cpp
index 8a4887afd3e00..837a5f7d7cc55 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUMemoryUtils.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUMemoryUtils.cpp
@@ -9,6 +9,7 @@
 #include "AMDGPUMemoryUtils.h"
 #include "Utils/AMDGPUBaseInfo.h"
 #include "llvm/ADT/SetOperations.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/CallGraph.h"
 #include "llvm/Analysis/MemorySSA.h"
@@ -17,6 +18,7 @@
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/IntrinsicsAMDGPU.h"
 #include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/MemoryModelRelaxationAnnotations.h"
 #include "llvm/IR/ReplaceConstant.h"
 #include "llvm/Support/AMDGPUAddrSpace.h"
 #include "llvm/Support/AtomicOrdering.h"
@@ -478,4 +480,67 @@ bool isClobberedInFunction(const LoadInst *Load, MemorySSA *MSSA,
   return false;
 }
 
+SIAtomicAddrSpace toSIAtomicAddrSpace(unsigned AS) {
+  if (AS == AMDGPUAS::FLAT_ADDRESS)
+    return SIAtomicAddrSpace::FLAT;
+  if (AS == AMDGPUAS::GLOBAL_ADDRESS)
+    return SIAtomicAddrSpace::GLOBAL;
+  if (AS == AMDGPUAS::LOCAL_ADDRESS)
+    return SIAtomicAddrSpace::LDS;
+  if (AS == AMDGPUAS::PRIVATE_ADDRESS)
+    return SIAtomicAddrSpace::SCRATCH;
+  if (AS == AMDGPUAS::REGION_ADDRESS)
+    return SIAtomicAddrSpace::GDS;
+  if (AS == AMDGPUAS::BUFFER_FAT_POINTER || AS == AMDGPUAS::BUFFER_RESOURCE ||
+      AS == AMDGPUAS::BUFFER_STRIDED_POINTER)
+    return SIAtomicAddrSpace::GLOBAL;
+
+  // Constant addrspaces map to OTHER because there is no point in atomic
+  // operations in them, since their memory does not change during kernel
+  // execution.
+  return SIAtomicAddrSpace::OTHER;
+}
+
+static const StringMap<SIAtomicAddrSpace> ASNames = {{
+    {"global", SIAtomicAddrSpace::GLOBAL},
+    {"local", SIAtomicAddrSpace::LDS},
+}};
+
+std::optional<SIAtomicAddrSpace>
+getSynchronizeAddrSpace(const MMRAMetadata &MMRA,
+                        function_ref<void(StringRef)> Diag) {
+  static constexpr StringLiteral FenceASPrefix = "amdgpu-synchronize-as";
+
+  if (!MMRA)
+    return std::nullopt;
+
+  SIAtomicAddrSpace Result = SIAtomicAddrSpace::NONE;
+  for (const auto &[Prefix, Suffix] : MMRA) {
+    if (Prefix != FenceASPrefix)
+      continue;
+
+    if (auto It = ASNames.find(Suffix); It != ASNames.end()) {
+      Result |= It->second;
+    } else {
+      SmallString<128> Str;
+      raw_svector_ostream OS(Str);
+      OS << "unknown address space '" << Suffix << "'; expected one of ";
+      ListSeparator LS;
+      for (const auto &[Name, Val] : ASNames)
+        OS << LS << '\'' << Name << '\'';
+      Diag(Str);
+    }
+  }
+
+  if (Result == SIAtomicAddrSpace::NONE)
+    return std::nullopt;
+
+  return Result;
+}
+
+std::optional<SIAtomicAddrSpace> getSynchronizeAddrSpace(const Instruction &I) {
+  const auto MMRA = MMRAMetadata(I);
+  return getSynchronizeAddrSpace(MMRA, [](StringRef) {});
+}
+
 } // end namespace llvm::AMDGPU
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUMemoryUtils.h b/llvm/lib/Target/AMDGPU/AMDGPUMemoryUtils.h
index 95f8c91a4dd93..e4bc43de91da8 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUMemoryUtils.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUMemoryUtils.h
@@ -10,9 +10,12 @@
 #define LLVM_LIB_TARGET_AMDGPU_UTILS_AMDGPUMEMORYUTILS_H
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitmaskEnum.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
+#include <optional>
 
 namespace llvm {
 
@@ -20,9 +23,11 @@ struct Align;
 class AAResults;
 class DataLayout;
 class GlobalVariable;
+class Instruction;
 class LoadInst;
 class MemoryDef;
 class MemorySSA;
+class MMRAMetadata;
 class Value;
 class Function;
 class CallGraph;
@@ -113,6 +118,46 @@ bool isReallyAClobber(const Value *Ptr, MemoryDef *Def, AAResults *AA);
 bool isClobberedInFunction(const LoadInst *Load, MemorySSA *MSSA,
                            AAResults *AA);
 
+/// The distinct address spaces supported by the AMDGPU target for
+/// atomic memory operation. Can be ORed together.
+enum class SIAtomicAddrSpace {
+  NONE = 0u,
+  GLOBAL = 1u << 0,
+  LDS = 1u << 1,
+  SCRATCH = 1u << 2,
+  GDS = 1u << 3,
+  OTHER = 1u << 4,
+
+  /// The address spaces that can be accessed by a FLAT instruction.
+  FLAT = GLOBAL | LDS | SCRATCH,
+
+  /// The address spaces that support atomic instructions.
+  ATOMIC = GLOBAL | LDS | SCRATCH | GDS,
+
+  /// All address spaces.
+  ALL = GLOBAL | LDS | SCRATCH | GDS | OTHER,
+
+  LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ ALL)
+};
+
+/// \return Return a bit set of the address spaces accessed by \p AS.
+SIAtomicAddrSpace toSIAtomicAddrSpace(unsigned AS);
+
+/// Reads \p I's MMRAs to parse the "amdgpu-synchronize-as" MMRA.
+/// If this tag isn't present, or if it has no meaningful values, returns
+/// \p none, otherwise returns the address spaces specified by the MD.
+/// Does not diagnose unexpected MMRA tag suffixes.
+std::optional<SIAtomicAddrSpace> getSynchronizeAddrSpace(const Instruction &I);
+
+/// Parses the values for the "amdgpu-synchronize-as" MMRA.
+/// If this tag isn't present, or if it has no meaningful values, returns
+/// \p none, otherwise returns the address spaces specified by the MD.
+/// If an unexpected suffix for the MMRA tag is found, \p Diag is called with
+/// an error message.
+std::optional<SIAtomicAddrSpace>
+getSynchronizeAddrSpace(const MMRAMetadata &MMRA,
+                        function_ref<void(StringRef)> Diag);
+
 } // end namespace AMDGPU
 
 } // end namespace llvm
diff --git a/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp b/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp
index 10804d65b82b0..518956fdeb36c 100644
--- a/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp
+++ b/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp
@@ -15,6 +15,7 @@
 
 #include "AMDGPU.h"
 #include "AMDGPUMachineModuleInfo.h"
+#include "AMDGPUMemoryUtils.h"
 #include "GCNSubtarget.h"
 #include "llvm/ADT/BitmaskEnum.h"
 #include "llvm/ADT/StringExtras.h"
@@ -24,7 +25,6 @@
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/MemoryModelRelaxationAnnotations.h"
 #include "llvm/IR/PassManager.h"
-#include "llvm/Support/AMDGPUAddrSpace.h"
 #include "llvm/Support/AtomicOrdering.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/TargetParser/AMDGPUTargetParser.h"
@@ -69,28 +69,6 @@ enum class SIAtomicScope {
   SYSTEM
 };
 
-/// The distinct address spaces supported by the AMDGPU target for
-/// atomic memory operation. Can be ORed together.
-enum class SIAtomicAddrSpace {
-  NONE = 0u,
-  GLOBAL = 1u << 0,
-  LDS = 1u << 1,
-  SCRATCH = 1u << 2,
-  GDS = 1u << 3,
-  OTHER = 1u << 4,
-
-  /// The address spaces that can be accessed by a FLAT instruction.
-  FLAT = GLOBAL | LDS | SCRATCH,
-
-  /// The address spaces that support atomic instructions.
-  ATOMIC = GLOBAL | LDS | SCRATCH | GDS,
-
-  /// All address spaces.
-  ALL = GLOBAL | LDS | SCRATCH | GDS | OTHER,
-
-  LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ ALL)
-};
-
 #ifndef NDEBUG
 static StringRef toString(SIAtomicScope S) {
   switch (S) {
@@ -292,9 +270,6 @@ class SIMemOpAccess final {
   std::optional<std::tuple<SIAtomicScope, SIAtomicAddrSpace, bool>>
   toSIAtomicScope(SyncScope::ID SSID, SIAtomicAddrSpace InstrAddrSpace) const;
 
-  /// \return Return a bit set of the address spaces accessed by \p AS.
-  SIAtomicAddrSpace toSIAtomicAddrSpace(unsigned AS) const;
-
   /// \returns Info constructed from \p MI, which has at least machine memory
   /// operand.
   std::optional<SIMemOpInfo>
@@ -687,50 +662,20 @@ class SIMemoryLegalizerLegacy final : public MachineFunctionPass {
   bool runOnMachineFunction(MachineFunction &MF) override;
 };
 
-static const StringMap<SIAtomicAddrSpace> ASNames = {{
-    {"global", SIAtomicAddrSpace::GLOBAL},
-    {"local", SIAtomicAddrSpace::LDS},
-}};
-
-void diagnoseUnknownMMRAASName(const MachineInstr &MI, StringRef AS) {
-  const MachineFunction *MF = MI.getMF();
-  const Function &Fn = MF->getFunction();
-  SmallString<128> Str;
-  raw_svector_ostream OS(Str);
-  OS << "unknown address space '" << AS << "'; expected one of ";
-  ListSeparator LS;
-  for (const auto &[Name, Val] : ASNames)
-    OS << LS << '\'' << Name << '\'';
-  Fn.getContext().diagnose(
-      DiagnosticInfoUnsupported(Fn, Str.str(), MI.getDebugLoc(), DS_Warning));
-}
-
 /// Reads \p MI's MMRAs to parse the "amdgpu-synchronize-as" MMRA.
 /// If this tag isn't present, or if it has no meaningful values, returns
 /// \p none, otherwise returns the address spaces specified by the MD.
+/// Issues a diagnostic if an unexpected suffix is observed for the MMRA tag.
 static std::optional<SIAtomicAddrSpace>
 getSynchronizeAddrSpaceMD(const MachineInstr &MI) {
-  static constexpr StringLiteral FenceASPrefix = "amdgpu-synchronize-as";
-
-  auto MMRA = MMRAMetadata(MI.getMMRAMetadata());
-  if (!MMRA)
-    return std::nullopt;
-
-  SIAtomicAddrSpace Result = SIAtomicAddrSpace::NONE;
-  for (const auto &[Prefix, Suffix] : MMRA) {
-    if (Prefix != FenceASPrefix)
-      continue;
-
-    if (auto It = ASNames.find(Suffix); It != ASNames.end())
-      Result |= It->second;
-    else
-      diagnoseUnknownMMRAASName(MI, Suffix);
-  }
-
-  if (Result == SIAtomicAddrSpace::NONE)
-    return std::nullopt;
-
-  return Result;
+  const auto MMRA = MMRAMetadata(MI.getMMRAMetadata());
+  auto Diag = [&MI](StringRef S) {
+    const MachineFunction *MF = MI.getMF();
+    const Function &Fn = MF->getFunction();
+    Fn.getContext().diagnose(
+        DiagnosticInfoUnsupported(Fn, S, MI.getDebugLoc(), DS_Warning));
+  };
+  return getSynchronizeAddrSpace(MMRA, Diag);
 }
 
 static void diagnoseUnknownAVMetadata(const MachineInstr &MI,
@@ -806,24 +751,6 @@ SIMemOpAccess::toSIAtomicScope(SyncScope::ID SSID,
   return std::nullopt;
 }
 
-SIAtomicAddrSpace SIMemOpAccess::toSIAtomicAddrSpace(unsigned AS) const {
-  if (AS == AMDGPUAS::FLAT_ADDRESS)
-    return SIAtomicAddrSpace::FLAT;
-  if (AS == AMDGPUAS::GLOBAL_ADDRESS)
-    return SIAtomicAddrSpace::GLOBAL;
-  if (AS == AMDGPUAS::LOCAL_ADDRESS)
-    return SIAtomicAddrSpace::LDS;
-  if (AS == AMDGPUAS::PRIVATE_ADDRESS)
-    return SIAtomicAddrSpace::SCRATCH;
-  if (AS == AMDGPUAS::REGION_ADDRESS)
-    return SIAtomicAddrSpace::GDS;
-  if (AS == AMDGPUAS::BUFFER_FAT_POINTER || AS == AMDGPUAS::BUFFER_RESOURCE ||
-      AS == AMDGPUAS::BUFFER_STRIDED_POINTER)
-    return SIAtomicAddrSpace::GLOBAL;
-
-  return SIAtomicAddrSpace::OTHER;
-}
-
 SIMemOpAccess::SIMemOpAccess(const AMDGPUMachineModuleInfo &MMI_,
                              const GCNSubtarget &ST)
     : MMI(&MMI_), ST(ST) {}

``````````

</details>


https://github.com/llvm/llvm-project/pull/231854


More information about the llvm-branch-commits mailing list