[llvm] [AMDGPU] Fix SSID merge in SIMemoryLegalizer to use smallest inclusiv… (PR #208300)
Wooseok Lee via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 10 06:52:47 PDT 2026
https://github.com/wooseoklee updated https://github.com/llvm/llvm-project/pull/208300
>From e0ebcf37830c7e3432ad5b042005faaffeae8aa8 Mon Sep 17 00:00:00 2001
From: wooseoklee <wolee at amd.com>
Date: Wed, 8 Jul 2026 13:17:37 -0500
Subject: [PATCH 1/5] [AMDGPU] Fix SSID merge in SIMemoryLegalizer to use
smallest inclusive scope
SIMemOpAccess::constructFromMIWithMMO merged multiple MMO sync scopes by
calling isSyncScopeInclusion(A, B) and blindly overwriting SSID with B
when it returned false. This was correct when B strictly subsumes A, but
isSyncScopeInclusion returned false for both "A < B" and "A and B are
incomparable" -- e.g. agent-one-as (one-AS, agent level) vs workgroup
(cross-AS, workgroup level) live on different branches of the two-dimensional
scope lattice and neither subsumes the other. In the incomparable case the
resulting SSID depended on MMO order, silently dropping agent-scope
cache-management requirements.
Fix: replace isSyncScopeInclusion (std::optional<bool>) with
getMergedSyncScopeID (std::optional<SyncScope::ID>) which returns the
smallest scope inclusive of both inputs. The merged level is max(level_A,
level_B); if either input is cross-AS the result is also cross-AS, since
dropping cross-AS ordering would silently lose the ordering guarantee for
address spaces not covered by a one-AS scope.
Add tests in memory-legalizer-multiple-mem-operands-atomics.mir verifying
that a FLAT_ATOMIC_ADD with agent-one-as and workgroup MMOs produces
agent-scope cache ops (BUFFER_WBINVL1_VOL) regardless of MMO order.
---
.../Target/AMDGPU/AMDGPUMachineModuleInfo.h | 60 ++++++++++++++-----
llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp | 21 +++----
llvm/test/CodeGen/AMDGPU/av-invalid-scope.ll | 4 +-
.../memory-legalizer-invalid-syncscope.ll | 8 +--
...egalizer-multiple-mem-operands-atomics.mir | 46 ++++++++++++++
5 files changed, 109 insertions(+), 30 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h b/llvm/lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h
index bf852bb38376e..b2dd1841f4a55 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h
@@ -130,26 +130,58 @@ class AMDGPUMachineModuleInfo final : public MachineModuleInfoELF {
return ClusterOneAddressSpaceSSID;
}
- /// In AMDGPU target synchronization scopes are inclusive, meaning a
- /// larger synchronization scope is inclusive of a smaller synchronization
- /// scope.
+ /// In AMDGPU, synchronization scopes are inclusive: a larger scope is
+ /// inclusive of a smaller one (e.g. agent includes workgroup).
+ ///
+ /// Returns the merged synchronization scope of \p A and \p B: the smallest
+ /// scope that is inclusive of both. Takes the larger inclusion level and,
+ /// if either scope is cross-address-space, the result is also
+ /// cross-address-space (since a one-AS scope cannot subsume a cross-AS
+ /// scope at the same level).
///
- /// \returns True if synchronization scope \p A is larger than or equal to
- /// synchronization scope \p B, false if synchronization scope \p A is smaller
- /// than synchronization scope \p B, or "std::nullopt" if either
- /// synchronization scope \p A or \p B is not supported by the AMDGPU target.
- std::optional<bool> isSyncScopeInclusion(SyncScope::ID A,
- SyncScope::ID B) const {
+ /// \returns The merged scope ID, or "std::nullopt" if either scope is not
+ /// supported by the AMDGPU target.
+ std::optional<SyncScope::ID> getMergedSyncScopeID(SyncScope::ID A,
+ SyncScope::ID B) const {
const auto &AIO = getSyncScopeInclusionOrdering(A);
const auto &BIO = getSyncScopeInclusionOrdering(B);
if (!AIO || !BIO)
return std::nullopt;
- bool IsAOneAddressSpace = isOneAddressSpace(A);
- bool IsBOneAddressSpace = isOneAddressSpace(B);
-
- return *AIO >= *BIO &&
- (IsAOneAddressSpace == IsBOneAddressSpace || !IsAOneAddressSpace);
+ uint8_t Level = std::max(*AIO, *BIO);
+ // If either scope is cross-AS, the result must be cross-AS.
+ if (isOneAddressSpace(A) && isOneAddressSpace(B)) {
+ switch (Level) {
+ case 0:
+ return SyncScope::SingleThread;
+ case 1:
+ return getWavefrontOneAddressSpaceSSID();
+ case 2:
+ return getWorkgroupOneAddressSpaceSSID();
+ case 3:
+ return getClusterOneAddressSpaceSSID();
+ case 4:
+ return getAgentOneAddressSpaceSSID();
+ case 5:
+ return getSystemOneAddressSpaceSSID();
+ }
+ } else {
+ switch (Level) {
+ case 0:
+ return SyncScope::SingleThread;
+ case 1:
+ return getWavefrontSSID();
+ case 2:
+ return getWorkgroupSSID();
+ case 3:
+ return getClusterSSID();
+ case 4:
+ return getAgentSSID();
+ case 5:
+ return SyncScope::System;
+ }
+ }
+ return std::nullopt;
}
};
diff --git a/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp b/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp
index 409fcc7f8d980..b90ceffdf5582 100644
--- a/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp
+++ b/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp
@@ -851,7 +851,7 @@ std::optional<SIMemOpInfo> SIMemOpAccess::constructFromMIWithMMO(
const MachineBasicBlock::iterator &MI) const {
assert(MI->getNumMemOperands() > 0);
- SyncScope::ID SSID = SyncScope::SingleThread;
+ std::optional<SyncScope::ID> MergedSSID;
AtomicOrdering Ordering = AtomicOrdering::NotAtomic;
AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic;
SIAtomicAddrSpace InstrAddrSpace = SIAtomicAddrSpace::NONE;
@@ -867,19 +867,19 @@ std::optional<SIMemOpInfo> SIMemOpAccess::constructFromMIWithMMO(
IsVolatile |= MMO->isVolatile();
IsLastUse |= MMO->getFlags() & MOLastUse;
IsCooperative |= MMO->getFlags() & MOCooperative;
- InstrAddrSpace |=
- toSIAtomicAddrSpace(MMO->getPointerInfo().getAddrSpace());
+ InstrAddrSpace |= toSIAtomicAddrSpace(MMO->getPointerInfo().getAddrSpace());
AtomicOrdering OpOrdering = MMO->getSuccessOrdering();
if (OpOrdering != AtomicOrdering::NotAtomic) {
- const auto &IsSyncScopeInclusion =
- MMI->isSyncScopeInclusion(SSID, MMO->getSyncScopeID());
- if (!IsSyncScopeInclusion) {
- reportUnsupported(MI,
- "Unsupported non-inclusive atomic synchronization scope");
+ // Merge the accumulated scope with the new one to get the smallest scope
+ // inclusive of both.
+ SyncScope::ID CurSSID = MergedSSID.value_or(MMO->getSyncScopeID());
+ const auto &Merged =
+ MMI->getMergedSyncScopeID(CurSSID, MMO->getSyncScopeID());
+ if (!Merged) {
+ reportUnsupported(MI, "Unsupported atomic synchronization scope");
return std::nullopt;
}
-
- SSID = *IsSyncScopeInclusion ? SSID : MMO->getSyncScopeID();
+ MergedSSID = *Merged;
Ordering = getMergedAtomicOrdering(Ordering, OpOrdering);
assert(MMO->getFailureOrdering() != AtomicOrdering::Release &&
MMO->getFailureOrdering() != AtomicOrdering::AcquireRelease);
@@ -887,6 +887,7 @@ std::optional<SIMemOpInfo> SIMemOpAccess::constructFromMIWithMMO(
getMergedAtomicOrdering(FailureOrdering, MMO->getFailureOrdering());
}
}
+ SyncScope::ID SSID = MergedSSID.value_or(SyncScope::SingleThread);
// FIXME: The MMO of buffer atomic instructions does not always have an atomic
// ordering. We only need to handle VBUFFER atomics on GFX12+ so we can fix it
diff --git a/llvm/test/CodeGen/AMDGPU/av-invalid-scope.ll b/llvm/test/CodeGen/AMDGPU/av-invalid-scope.ll
index ce4522f4b4ad7..d64366a2b3f9b 100644
--- a/llvm/test/CodeGen/AMDGPU/av-invalid-scope.ll
+++ b/llvm/test/CodeGen/AMDGPU/av-invalid-scope.ll
@@ -1,8 +1,8 @@
; RUN: not llc -global-isel=0 -mtriple=amdgcn -mcpu=gfx942 -filetype=null < %s 2>&1 | FileCheck %s
; RUN: not llc -global-isel=1 -mtriple=amdgcn -mcpu=gfx942 -filetype=null < %s 2>&1 | FileCheck %s
-; CHECK: error: {{.*}}: in function av_load_bad_scope {{.*}}: Unsupported non-inclusive atomic synchronization scope
-; CHECK: error: {{.*}}: in function av_store_bad_scope {{.*}}: Unsupported non-inclusive atomic synchronization scope
+; CHECK: error: {{.*}}: in function av_load_bad_scope {{.*}}: Unsupported atomic synchronization scope
+; CHECK: error: {{.*}}: in function av_store_bad_scope {{.*}}: Unsupported atomic synchronization scope
define <4 x i32> @av_load_bad_scope(ptr addrspace(1) %p) {
%v = call <4 x i32> @llvm.amdgcn.av.load.b128.p1(ptr addrspace(1) %p, metadata !0)
diff --git a/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-syncscope.ll b/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-syncscope.ll
index 1a2058cbe39e4..e820bac9e5ae5 100644
--- a/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-syncscope.ll
+++ b/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-syncscope.ll
@@ -11,7 +11,7 @@ entry:
ret void
}
-; CHECK: error: <unknown>:0:0: in function invalid_load void (ptr, ptr): Unsupported non-inclusive atomic synchronization scope
+; CHECK: error: <unknown>:0:0: in function invalid_load void (ptr, ptr): Unsupported atomic synchronization scope
define amdgpu_kernel void @invalid_load(
ptr %in, ptr %out) {
entry:
@@ -20,7 +20,7 @@ entry:
ret void
}
-; CHECK: error: <unknown>:0:0: in function invalid_store void (i32, ptr): Unsupported non-inclusive atomic synchronization scope
+; CHECK: error: <unknown>:0:0: in function invalid_store void (i32, ptr): Unsupported atomic synchronization scope
define amdgpu_kernel void @invalid_store(
i32 %in, ptr %out) {
entry:
@@ -28,7 +28,7 @@ entry:
ret void
}
-; CHECK: error: <unknown>:0:0: in function invalid_cmpxchg void (ptr, i32, i32): Unsupported non-inclusive atomic synchronization scope
+; CHECK: error: <unknown>:0:0: in function invalid_cmpxchg void (ptr, i32, i32): Unsupported atomic synchronization scope
define amdgpu_kernel void @invalid_cmpxchg(
ptr %out, i32 %in, i32 %old) {
entry:
@@ -37,7 +37,7 @@ entry:
ret void
}
-; CHECK: error: <unknown>:0:0: in function invalid_rmw void (ptr, i32): Unsupported non-inclusive atomic synchronization scope
+; CHECK: error: <unknown>:0:0: in function invalid_rmw void (ptr, i32): Unsupported atomic synchronization scope
define amdgpu_kernel void @invalid_rmw(
ptr %out, i32 %in) {
entry:
diff --git a/llvm/test/CodeGen/AMDGPU/memory-legalizer-multiple-mem-operands-atomics.mir b/llvm/test/CodeGen/AMDGPU/memory-legalizer-multiple-mem-operands-atomics.mir
index 3941da208f825..1496f2533d88b 100644
--- a/llvm/test/CodeGen/AMDGPU/memory-legalizer-multiple-mem-operands-atomics.mir
+++ b/llvm/test/CodeGen/AMDGPU/memory-legalizer-multiple-mem-operands-atomics.mir
@@ -111,3 +111,49 @@ body: |
S_ENDPGM 0
...
+---
+# Test that multi-MMO atomics with incomparable sync scopes (agent-one-as and
+# workgroup) produce agent-scope cache ops regardless of MMO order. The merged
+# scope of agent-one-as and workgroup is agent (cross-AS). Before the fix, the
+# result was MMO-order dependent.
+name: merge_agent_one_as_and_workgroup
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3
+ ; GCN-LABEL: name: merge_agent_one_as_and_workgroup
+ ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3
+ ; GCN-NEXT: {{ $}}
+ ; GCN-NEXT: renamable $vgpr0_vgpr1 = COPY $sgpr0_sgpr1
+ ; GCN-NEXT: renamable $vgpr2 = COPY $sgpr2
+ ; GCN-NEXT: S_WAITCNT_soft .Vmcnt_0_Lgkmcnt_0
+ ; GCN-NEXT: FLAT_ATOMIC_ADD $vgpr0_vgpr1, $vgpr2, 0, 0, implicit $exec, implicit $flat_scr :: (load store syncscope("agent-one-as") seq_cst (s32) on `ptr addrspace(1) poison`, addrspace 1), (load store syncscope("workgroup") seq_cst (s32) on `ptr addrspace(1) poison`, addrspace 1)
+ ; GCN-NEXT: S_WAITCNT_soft .Vmcnt_0
+ ; GCN-NEXT: BUFFER_WBINVL1_VOL implicit $exec
+ ; GCN-NEXT: S_ENDPGM 0
+ renamable $vgpr0_vgpr1 = COPY $sgpr0_sgpr1
+ renamable $vgpr2 = COPY $sgpr2
+ FLAT_ATOMIC_ADD $vgpr0_vgpr1, $vgpr2, 0, 0, implicit $exec, implicit $flat_scr :: (load store syncscope("agent-one-as") seq_cst (s32) on `ptr addrspace(1) poison`), (load store syncscope("workgroup") seq_cst (s32) on `ptr addrspace(1) poison`)
+ S_ENDPGM 0
+...
+---
+name: merge_agent_one_as_and_workgroup_reversed
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3
+ ; GCN-LABEL: name: merge_agent_one_as_and_workgroup_reversed
+ ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3
+ ; GCN-NEXT: {{ $}}
+ ; GCN-NEXT: renamable $vgpr0_vgpr1 = COPY $sgpr0_sgpr1
+ ; GCN-NEXT: renamable $vgpr2 = COPY $sgpr2
+ ; GCN-NEXT: S_WAITCNT_soft .Vmcnt_0_Lgkmcnt_0
+ ; GCN-NEXT: FLAT_ATOMIC_ADD $vgpr0_vgpr1, $vgpr2, 0, 0, implicit $exec, implicit $flat_scr :: (load store syncscope("workgroup") seq_cst (s32) on `ptr addrspace(1) poison`, addrspace 1), (load store syncscope("agent-one-as") seq_cst (s32) on `ptr addrspace(1) poison`, addrspace 1)
+ ; GCN-NEXT: S_WAITCNT_soft .Vmcnt_0
+ ; GCN-NEXT: BUFFER_WBINVL1_VOL implicit $exec
+ ; GCN-NEXT: S_ENDPGM 0
+ renamable $vgpr0_vgpr1 = COPY $sgpr0_sgpr1
+ renamable $vgpr2 = COPY $sgpr2
+ FLAT_ATOMIC_ADD $vgpr0_vgpr1, $vgpr2, 0, 0, implicit $exec, implicit $flat_scr :: (load store syncscope("workgroup") seq_cst (s32) on `ptr addrspace(1) poison`), (load store syncscope("agent-one-as") seq_cst (s32) on `ptr addrspace(1) poison`)
+ S_ENDPGM 0
+...
>From 5e81400fed414c7d702f91f6d64354b8b353f7d9 Mon Sep 17 00:00:00 2001
From: wooseoklee <wolee at amd.com>
Date: Thu, 9 Jul 2026 09:02:33 -0500
Subject: [PATCH 2/5] Address the issue from the reviwer.
---
.../Target/AMDGPU/AMDGPUMachineModuleInfo.h | 113 ++++++------------
1 file changed, 36 insertions(+), 77 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h b/llvm/lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h
index b2dd1841f4a55..5062fd8f0e2e2 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h
@@ -47,47 +47,6 @@ class AMDGPUMachineModuleInfo final : public MachineModuleInfoELF {
/// Cluster synchronization scope ID (single address space).
SyncScope::ID ClusterOneAddressSpaceSSID;
- /// In AMDGPU target synchronization scopes are inclusive, meaning a
- /// larger synchronization scope is inclusive of a smaller synchronization
- /// scope.
- ///
- /// \returns \p SSID's inclusion ordering, or "std::nullopt" if \p SSID is not
- /// supported by the AMDGPU target.
- std::optional<uint8_t>
- getSyncScopeInclusionOrdering(SyncScope::ID SSID) const {
- if (SSID == SyncScope::SingleThread ||
- SSID == getSingleThreadOneAddressSpaceSSID())
- return 0;
- else if (SSID == getWavefrontSSID() ||
- SSID == getWavefrontOneAddressSpaceSSID())
- return 1;
- else if (SSID == getWorkgroupSSID() ||
- SSID == getWorkgroupOneAddressSpaceSSID())
- return 2;
- else if (SSID == getClusterSSID() ||
- SSID == getClusterOneAddressSpaceSSID())
- return 3;
- else if (SSID == getAgentSSID() ||
- SSID == getAgentOneAddressSpaceSSID())
- return 4;
- else if (SSID == SyncScope::System ||
- SSID == getSystemOneAddressSpaceSSID())
- return 5;
-
- return std::nullopt;
- }
-
- /// \returns True if \p SSID is restricted to single address space, false
- /// otherwise
- bool isOneAddressSpace(SyncScope::ID SSID) const {
- return SSID == getClusterOneAddressSpaceSSID() ||
- SSID == getSingleThreadOneAddressSpaceSSID() ||
- SSID == getWavefrontOneAddressSpaceSSID() ||
- SSID == getWorkgroupOneAddressSpaceSSID() ||
- SSID == getAgentOneAddressSpaceSSID() ||
- SSID == getSystemOneAddressSpaceSSID();
- }
-
public:
AMDGPUMachineModuleInfo(const MachineModuleInfo &MMI);
@@ -143,45 +102,45 @@ class AMDGPUMachineModuleInfo final : public MachineModuleInfoELF {
/// supported by the AMDGPU target.
std::optional<SyncScope::ID> getMergedSyncScopeID(SyncScope::ID A,
SyncScope::ID B) const {
- const auto &AIO = getSyncScopeInclusionOrdering(A);
- const auto &BIO = getSyncScopeInclusionOrdering(B);
- if (!AIO || !BIO)
+ // Ordered from smallest to largest scope. Level is the index.
+ // Cross-AS and one-AS scopes share the same inclusion ordering level.
+ // Level | Cross-AS scope | One-AS scope
+ // ------+------------------+----------------------
+ // 0 | singlethread | singlethread-one-as
+ // 1 | wavefront | wavefront-one-as
+ // 2 | workgroup | workgroup-one-as
+ // 3 | cluster | cluster-one-as
+ // 4 | agent | agent-one-as
+ // 5 | system | one-as
+ const SyncScope::ID CrossAS[] = {
+ SyncScope::SingleThread, getWavefrontSSID(), getWorkgroupSSID(),
+ getClusterSSID(), getAgentSSID(), SyncScope::System};
+ const SyncScope::ID OneAS[] = {
+ getSingleThreadOneAddressSpaceSSID(), getWavefrontOneAddressSpaceSSID(),
+ getWorkgroupOneAddressSpaceSSID(), getClusterOneAddressSpaceSSID(),
+ getAgentOneAddressSpaceSSID(), getSystemOneAddressSpaceSSID()};
+
+ // Returns {level, isOneAS} for a given scope, or nullopt if unsupported.
+ auto GetLevelAndOneAS =
+ [&](SyncScope::ID SSID)
+ -> std::optional<std::pair<unsigned, bool>> {
+ for (unsigned I = 0; I < std::size(CrossAS); ++I) {
+ if (CrossAS[I] == SSID)
+ return std::make_pair(I, false);
+ if (OneAS[I] == SSID)
+ return std::make_pair(I, true);
+ }
+ return std::nullopt;
+ };
+
+ auto AI = GetLevelAndOneAS(A);
+ auto BI = GetLevelAndOneAS(B);
+ if (!AI || !BI)
return std::nullopt;
- uint8_t Level = std::max(*AIO, *BIO);
+ unsigned Level = std::max(AI->first, BI->first);
// If either scope is cross-AS, the result must be cross-AS.
- if (isOneAddressSpace(A) && isOneAddressSpace(B)) {
- switch (Level) {
- case 0:
- return SyncScope::SingleThread;
- case 1:
- return getWavefrontOneAddressSpaceSSID();
- case 2:
- return getWorkgroupOneAddressSpaceSSID();
- case 3:
- return getClusterOneAddressSpaceSSID();
- case 4:
- return getAgentOneAddressSpaceSSID();
- case 5:
- return getSystemOneAddressSpaceSSID();
- }
- } else {
- switch (Level) {
- case 0:
- return SyncScope::SingleThread;
- case 1:
- return getWavefrontSSID();
- case 2:
- return getWorkgroupSSID();
- case 3:
- return getClusterSSID();
- case 4:
- return getAgentSSID();
- case 5:
- return SyncScope::System;
- }
- }
- return std::nullopt;
+ return (AI->second && BI->second) ? OneAS[Level] : CrossAS[Level];
}
};
>From 3af06ec874e49378ae972af4106d91bb1c8b18bd Mon Sep 17 00:00:00 2001
From: wooseoklee <wolee at amd.com>
Date: Thu, 9 Jul 2026 09:07:08 -0500
Subject: [PATCH 3/5] Format fix
---
llvm/lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h b/llvm/lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h
index 5062fd8f0e2e2..eb77f11ad6ebd 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h
@@ -122,8 +122,7 @@ class AMDGPUMachineModuleInfo final : public MachineModuleInfoELF {
// Returns {level, isOneAS} for a given scope, or nullopt if unsupported.
auto GetLevelAndOneAS =
- [&](SyncScope::ID SSID)
- -> std::optional<std::pair<unsigned, bool>> {
+ [&](SyncScope::ID SSID) -> std::optional<std::pair<unsigned, bool>> {
for (unsigned I = 0; I < std::size(CrossAS); ++I) {
if (CrossAS[I] == SSID)
return std::make_pair(I, false);
>From 876394bd0cba1c36a8b7f4c0d4af6c310e70328d Mon Sep 17 00:00:00 2001
From: wooseoklee <wolee at amd.com>
Date: Thu, 9 Jul 2026 15:48:15 -0500
Subject: [PATCH 4/5] Update error messages to start with lower case letters
---
llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp | 10 +++++-----
llvm/test/CodeGen/AMDGPU/av-invalid-scope.ll | 4 ++--
.../AMDGPU/memory-legalizer-invalid-addrspace.mir | 8 ++++----
.../AMDGPU/memory-legalizer-invalid-syncscope.ll | 10 +++++-----
4 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp b/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp
index b90ceffdf5582..00757653082cc 100644
--- a/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp
+++ b/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp
@@ -876,7 +876,7 @@ std::optional<SIMemOpInfo> SIMemOpAccess::constructFromMIWithMMO(
const auto &Merged =
MMI->getMergedSyncScopeID(CurSSID, MMO->getSyncScopeID());
if (!Merged) {
- reportUnsupported(MI, "Unsupported atomic synchronization scope");
+ reportUnsupported(MI, "unsupported atomic synchronization scope");
return std::nullopt;
}
MergedSSID = *Merged;
@@ -902,7 +902,7 @@ std::optional<SIMemOpInfo> SIMemOpAccess::constructFromMIWithMMO(
if (Ordering != AtomicOrdering::NotAtomic) {
auto ScopeOrNone = toSIAtomicScope(SSID, InstrAddrSpace);
if (!ScopeOrNone) {
- reportUnsupported(MI, "Unsupported atomic synchronization scope");
+ reportUnsupported(MI, "unsupported atomic synchronization scope");
return std::nullopt;
}
std::tie(Scope, OrderingAddrSpace, IsCrossAddressSpaceOrdering) =
@@ -910,7 +910,7 @@ std::optional<SIMemOpInfo> SIMemOpAccess::constructFromMIWithMMO(
if ((OrderingAddrSpace == SIAtomicAddrSpace::NONE) ||
((OrderingAddrSpace & SIAtomicAddrSpace::ATOMIC) != OrderingAddrSpace) ||
((InstrAddrSpace & SIAtomicAddrSpace::ATOMIC) == SIAtomicAddrSpace::NONE)) {
- reportUnsupported(MI, "Unsupported atomic address space");
+ reportUnsupported(MI, "unsupported atomic address space");
return std::nullopt;
}
}
@@ -961,7 +961,7 @@ SIMemOpAccess::getAtomicFenceInfo(const MachineBasicBlock::iterator &MI) const {
SyncScope::ID SSID = static_cast<SyncScope::ID>(MI->getOperand(1).getImm());
auto ScopeOrNone = toSIAtomicScope(SSID, SIAtomicAddrSpace::ATOMIC);
if (!ScopeOrNone) {
- reportUnsupported(MI, "Unsupported atomic synchronization scope");
+ reportUnsupported(MI, "unsupported atomic synchronization scope");
return std::nullopt;
}
@@ -976,7 +976,7 @@ SIMemOpAccess::getAtomicFenceInfo(const MachineBasicBlock::iterator &MI) const {
// can refine the AS ordered by the fence.
// If that changes, we need to review the semantics of that function
// in case it needs to preserve certain address spaces.
- reportUnsupported(MI, "Unsupported atomic address space");
+ reportUnsupported(MI, "unsupported atomic address space");
return std::nullopt;
}
diff --git a/llvm/test/CodeGen/AMDGPU/av-invalid-scope.ll b/llvm/test/CodeGen/AMDGPU/av-invalid-scope.ll
index d64366a2b3f9b..9bb18a0e01213 100644
--- a/llvm/test/CodeGen/AMDGPU/av-invalid-scope.ll
+++ b/llvm/test/CodeGen/AMDGPU/av-invalid-scope.ll
@@ -1,8 +1,8 @@
; RUN: not llc -global-isel=0 -mtriple=amdgcn -mcpu=gfx942 -filetype=null < %s 2>&1 | FileCheck %s
; RUN: not llc -global-isel=1 -mtriple=amdgcn -mcpu=gfx942 -filetype=null < %s 2>&1 | FileCheck %s
-; CHECK: error: {{.*}}: in function av_load_bad_scope {{.*}}: Unsupported atomic synchronization scope
-; CHECK: error: {{.*}}: in function av_store_bad_scope {{.*}}: Unsupported atomic synchronization scope
+; CHECK: error: {{.*}}: in function av_load_bad_scope {{.*}}: unsupported atomic synchronization scope
+; CHECK: error: {{.*}}: in function av_store_bad_scope {{.*}}: unsupported atomic synchronization scope
define <4 x i32> @av_load_bad_scope(ptr addrspace(1) %p) {
%v = call <4 x i32> @llvm.amdgcn.av.load.b128.p1(ptr addrspace(1) %p, metadata !0)
diff --git a/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-addrspace.mir b/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-addrspace.mir
index 0251284696591..0765761737e51 100644
--- a/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-addrspace.mir
+++ b/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-addrspace.mir
@@ -2,7 +2,7 @@
---
-# GCN: error: <unknown>:0:0: in function invalid_load void (): Unsupported atomic address space
+# GCN: error: <unknown>:0:0: in function invalid_load void (): unsupported atomic address space
name: invalid_load
body: |
@@ -20,7 +20,7 @@ body: |
...
---
-# GCN: error: <unknown>:0:0: in function invalid_store void (): Unsupported atomic address space
+# GCN: error: <unknown>:0:0: in function invalid_store void (): unsupported atomic address space
name: invalid_store
body: |
@@ -36,7 +36,7 @@ body: |
...
---
-# GCN: error: <unknown>:0:0: in function invalid_cmpxchg void (): Unsupported atomic address space
+# GCN: error: <unknown>:0:0: in function invalid_cmpxchg void (): unsupported atomic address space
name: invalid_cmpxchg
body: |
@@ -53,7 +53,7 @@ body: |
...
---
-# GCN: error: <unknown>:0:0: in function invalid_rmw void (): Unsupported atomic address space
+# GCN: error: <unknown>:0:0: in function invalid_rmw void (): unsupported atomic address space
name: invalid_rmw
body: |
diff --git a/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-syncscope.ll b/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-syncscope.ll
index e820bac9e5ae5..3e41328bc3b2a 100644
--- a/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-syncscope.ll
+++ b/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-syncscope.ll
@@ -4,14 +4,14 @@
; RUN: not llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 < %s 2>&1 | FileCheck %s
; RUN: not llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1100 < %s 2>&1 | FileCheck %s
-; CHECK: error: <unknown>:0:0: in function invalid_fence void (): Unsupported atomic synchronization scope
+; CHECK: error: <unknown>:0:0: in function invalid_fence void (): unsupported atomic synchronization scope
define amdgpu_kernel void @invalid_fence() {
entry:
fence syncscope("invalid") seq_cst
ret void
}
-; CHECK: error: <unknown>:0:0: in function invalid_load void (ptr, ptr): Unsupported atomic synchronization scope
+; CHECK: error: <unknown>:0:0: in function invalid_load void (ptr, ptr): unsupported atomic synchronization scope
define amdgpu_kernel void @invalid_load(
ptr %in, ptr %out) {
entry:
@@ -20,7 +20,7 @@ entry:
ret void
}
-; CHECK: error: <unknown>:0:0: in function invalid_store void (i32, ptr): Unsupported atomic synchronization scope
+; CHECK: error: <unknown>:0:0: in function invalid_store void (i32, ptr): unsupported atomic synchronization scope
define amdgpu_kernel void @invalid_store(
i32 %in, ptr %out) {
entry:
@@ -28,7 +28,7 @@ entry:
ret void
}
-; CHECK: error: <unknown>:0:0: in function invalid_cmpxchg void (ptr, i32, i32): Unsupported atomic synchronization scope
+; CHECK: error: <unknown>:0:0: in function invalid_cmpxchg void (ptr, i32, i32): unsupported atomic synchronization scope
define amdgpu_kernel void @invalid_cmpxchg(
ptr %out, i32 %in, i32 %old) {
entry:
@@ -37,7 +37,7 @@ entry:
ret void
}
-; CHECK: error: <unknown>:0:0: in function invalid_rmw void (ptr, i32): Unsupported atomic synchronization scope
+; CHECK: error: <unknown>:0:0: in function invalid_rmw void (ptr, i32): unsupported atomic synchronization scope
define amdgpu_kernel void @invalid_rmw(
ptr %out, i32 %in) {
entry:
>From 227048529f8188629078707f168608fa44264e43 Mon Sep 17 00:00:00 2001
From: wooseoklee <wolee at amd.com>
Date: Fri, 10 Jul 2026 08:52:29 -0500
Subject: [PATCH 5/5] Address the review. Revert NFC change
---
llvm/lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h | 6 +++---
llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp | 10 +++++-----
llvm/test/CodeGen/AMDGPU/av-invalid-scope.ll | 4 ++--
.../AMDGPU/memory-legalizer-invalid-addrspace.mir | 8 ++++----
.../AMDGPU/memory-legalizer-invalid-syncscope.ll | 10 +++++-----
5 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h b/llvm/lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h
index eb77f11ad6ebd..6aee1bba71335 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUMachineModuleInfo.h
@@ -123,10 +123,10 @@ class AMDGPUMachineModuleInfo final : public MachineModuleInfoELF {
// Returns {level, isOneAS} for a given scope, or nullopt if unsupported.
auto GetLevelAndOneAS =
[&](SyncScope::ID SSID) -> std::optional<std::pair<unsigned, bool>> {
- for (unsigned I = 0; I < std::size(CrossAS); ++I) {
- if (CrossAS[I] == SSID)
+ for (auto [I, Cross, One] : llvm::enumerate(CrossAS, OneAS)) {
+ if (Cross == SSID)
return std::make_pair(I, false);
- if (OneAS[I] == SSID)
+ if (One == SSID)
return std::make_pair(I, true);
}
return std::nullopt;
diff --git a/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp b/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp
index 00757653082cc..b90ceffdf5582 100644
--- a/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp
+++ b/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp
@@ -876,7 +876,7 @@ std::optional<SIMemOpInfo> SIMemOpAccess::constructFromMIWithMMO(
const auto &Merged =
MMI->getMergedSyncScopeID(CurSSID, MMO->getSyncScopeID());
if (!Merged) {
- reportUnsupported(MI, "unsupported atomic synchronization scope");
+ reportUnsupported(MI, "Unsupported atomic synchronization scope");
return std::nullopt;
}
MergedSSID = *Merged;
@@ -902,7 +902,7 @@ std::optional<SIMemOpInfo> SIMemOpAccess::constructFromMIWithMMO(
if (Ordering != AtomicOrdering::NotAtomic) {
auto ScopeOrNone = toSIAtomicScope(SSID, InstrAddrSpace);
if (!ScopeOrNone) {
- reportUnsupported(MI, "unsupported atomic synchronization scope");
+ reportUnsupported(MI, "Unsupported atomic synchronization scope");
return std::nullopt;
}
std::tie(Scope, OrderingAddrSpace, IsCrossAddressSpaceOrdering) =
@@ -910,7 +910,7 @@ std::optional<SIMemOpInfo> SIMemOpAccess::constructFromMIWithMMO(
if ((OrderingAddrSpace == SIAtomicAddrSpace::NONE) ||
((OrderingAddrSpace & SIAtomicAddrSpace::ATOMIC) != OrderingAddrSpace) ||
((InstrAddrSpace & SIAtomicAddrSpace::ATOMIC) == SIAtomicAddrSpace::NONE)) {
- reportUnsupported(MI, "unsupported atomic address space");
+ reportUnsupported(MI, "Unsupported atomic address space");
return std::nullopt;
}
}
@@ -961,7 +961,7 @@ SIMemOpAccess::getAtomicFenceInfo(const MachineBasicBlock::iterator &MI) const {
SyncScope::ID SSID = static_cast<SyncScope::ID>(MI->getOperand(1).getImm());
auto ScopeOrNone = toSIAtomicScope(SSID, SIAtomicAddrSpace::ATOMIC);
if (!ScopeOrNone) {
- reportUnsupported(MI, "unsupported atomic synchronization scope");
+ reportUnsupported(MI, "Unsupported atomic synchronization scope");
return std::nullopt;
}
@@ -976,7 +976,7 @@ SIMemOpAccess::getAtomicFenceInfo(const MachineBasicBlock::iterator &MI) const {
// can refine the AS ordered by the fence.
// If that changes, we need to review the semantics of that function
// in case it needs to preserve certain address spaces.
- reportUnsupported(MI, "unsupported atomic address space");
+ reportUnsupported(MI, "Unsupported atomic address space");
return std::nullopt;
}
diff --git a/llvm/test/CodeGen/AMDGPU/av-invalid-scope.ll b/llvm/test/CodeGen/AMDGPU/av-invalid-scope.ll
index 9bb18a0e01213..d64366a2b3f9b 100644
--- a/llvm/test/CodeGen/AMDGPU/av-invalid-scope.ll
+++ b/llvm/test/CodeGen/AMDGPU/av-invalid-scope.ll
@@ -1,8 +1,8 @@
; RUN: not llc -global-isel=0 -mtriple=amdgcn -mcpu=gfx942 -filetype=null < %s 2>&1 | FileCheck %s
; RUN: not llc -global-isel=1 -mtriple=amdgcn -mcpu=gfx942 -filetype=null < %s 2>&1 | FileCheck %s
-; CHECK: error: {{.*}}: in function av_load_bad_scope {{.*}}: unsupported atomic synchronization scope
-; CHECK: error: {{.*}}: in function av_store_bad_scope {{.*}}: unsupported atomic synchronization scope
+; CHECK: error: {{.*}}: in function av_load_bad_scope {{.*}}: Unsupported atomic synchronization scope
+; CHECK: error: {{.*}}: in function av_store_bad_scope {{.*}}: Unsupported atomic synchronization scope
define <4 x i32> @av_load_bad_scope(ptr addrspace(1) %p) {
%v = call <4 x i32> @llvm.amdgcn.av.load.b128.p1(ptr addrspace(1) %p, metadata !0)
diff --git a/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-addrspace.mir b/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-addrspace.mir
index 0765761737e51..0251284696591 100644
--- a/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-addrspace.mir
+++ b/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-addrspace.mir
@@ -2,7 +2,7 @@
---
-# GCN: error: <unknown>:0:0: in function invalid_load void (): unsupported atomic address space
+# GCN: error: <unknown>:0:0: in function invalid_load void (): Unsupported atomic address space
name: invalid_load
body: |
@@ -20,7 +20,7 @@ body: |
...
---
-# GCN: error: <unknown>:0:0: in function invalid_store void (): unsupported atomic address space
+# GCN: error: <unknown>:0:0: in function invalid_store void (): Unsupported atomic address space
name: invalid_store
body: |
@@ -36,7 +36,7 @@ body: |
...
---
-# GCN: error: <unknown>:0:0: in function invalid_cmpxchg void (): unsupported atomic address space
+# GCN: error: <unknown>:0:0: in function invalid_cmpxchg void (): Unsupported atomic address space
name: invalid_cmpxchg
body: |
@@ -53,7 +53,7 @@ body: |
...
---
-# GCN: error: <unknown>:0:0: in function invalid_rmw void (): unsupported atomic address space
+# GCN: error: <unknown>:0:0: in function invalid_rmw void (): Unsupported atomic address space
name: invalid_rmw
body: |
diff --git a/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-syncscope.ll b/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-syncscope.ll
index 3e41328bc3b2a..e820bac9e5ae5 100644
--- a/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-syncscope.ll
+++ b/llvm/test/CodeGen/AMDGPU/memory-legalizer-invalid-syncscope.ll
@@ -4,14 +4,14 @@
; RUN: not llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 < %s 2>&1 | FileCheck %s
; RUN: not llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1100 < %s 2>&1 | FileCheck %s
-; CHECK: error: <unknown>:0:0: in function invalid_fence void (): unsupported atomic synchronization scope
+; CHECK: error: <unknown>:0:0: in function invalid_fence void (): Unsupported atomic synchronization scope
define amdgpu_kernel void @invalid_fence() {
entry:
fence syncscope("invalid") seq_cst
ret void
}
-; CHECK: error: <unknown>:0:0: in function invalid_load void (ptr, ptr): unsupported atomic synchronization scope
+; CHECK: error: <unknown>:0:0: in function invalid_load void (ptr, ptr): Unsupported atomic synchronization scope
define amdgpu_kernel void @invalid_load(
ptr %in, ptr %out) {
entry:
@@ -20,7 +20,7 @@ entry:
ret void
}
-; CHECK: error: <unknown>:0:0: in function invalid_store void (i32, ptr): unsupported atomic synchronization scope
+; CHECK: error: <unknown>:0:0: in function invalid_store void (i32, ptr): Unsupported atomic synchronization scope
define amdgpu_kernel void @invalid_store(
i32 %in, ptr %out) {
entry:
@@ -28,7 +28,7 @@ entry:
ret void
}
-; CHECK: error: <unknown>:0:0: in function invalid_cmpxchg void (ptr, i32, i32): unsupported atomic synchronization scope
+; CHECK: error: <unknown>:0:0: in function invalid_cmpxchg void (ptr, i32, i32): Unsupported atomic synchronization scope
define amdgpu_kernel void @invalid_cmpxchg(
ptr %out, i32 %in, i32 %old) {
entry:
@@ -37,7 +37,7 @@ entry:
ret void
}
-; CHECK: error: <unknown>:0:0: in function invalid_rmw void (ptr, i32): unsupported atomic synchronization scope
+; CHECK: error: <unknown>:0:0: in function invalid_rmw void (ptr, i32): Unsupported atomic synchronization scope
define amdgpu_kernel void @invalid_rmw(
ptr %out, i32 %in) {
entry:
More information about the llvm-commits
mailing list