[llvm] [NVPTX] Fix scoped atomic when given runtime values (PR #185883)

Joseph Huber via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 16 08:46:51 PDT 2026


https://github.com/jhuber6 updated https://github.com/llvm/llvm-project/pull/185883

>From e0409287036ce47bfd23c8c671671257f74f2dd6 Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Wed, 11 Mar 2026 08:37:07 -0500
Subject: [PATCH] [NVPTX] Fix scoped atomic when given runtime values

Summary:
The `__scoped_` atomic builtins will expand to each supported scope in
the case of a runtime value. There are two problems:
1. Singlethreaded scope doesn't exist -> Widen to block scope
2. Cluster is not supported on all tagets -> Widen to device scope
---
 llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp | 36 +++++++++++++--------
 1 file changed, 22 insertions(+), 14 deletions(-)

diff --git a/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp b/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp
index 99982ff3181b3..8e916126fecb6 100644
--- a/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp
@@ -773,14 +773,9 @@ NVPTX::Scope NVPTXDAGToDAGISel::getOperationScope(MemSDNode *N,
   case NVPTX::Ordering::SequentiallyConsistent:
     auto S = Scopes[N->getSyncScopeID()];
 
-    // Atomic operations must have a scope greater than thread.
-    if (S == NVPTX::Scope::Thread)
-      report_fatal_error(
-          formatv("Atomics need scope > \"{}\".", ScopeToString(S)));
-
-    // If scope is cluster, clusters must be supported.
-    if (S == NVPTX::Scope::Cluster)
-      Subtarget->failIfClustersUnsupported("cluster scope");
+    // If scope is cluster but clusters aren't supported, widen to device.
+    if (S == NVPTX::Scope::Cluster && !Subtarget->hasClusters())
+      S = NVPTX::Scope::Device;
 
     // If operation is volatile, then its scope is system.
     return N->isVolatile() ? NVPTX::Scope::System : S;
@@ -798,8 +793,9 @@ static bool canLowerToLDG(const MemSDNode &N, const NVPTXSubtarget &Subtarget,
 
 static unsigned int getFenceOp(NVPTX::Ordering O, NVPTX::Scope S,
                                NVPTXSubtarget const *T) {
-  if (S == NVPTX::Scope::Cluster)
-    T->failIfClustersUnsupported(".cluster scope fence");
+  // If scope is cluster but clusters aren't supported, widen to device.
+  if (S == NVPTX::Scope::Cluster && !T->hasClusters())
+    S = NVPTX::Scope::Device;
 
   // Fall back to .acq_rel if .acquire, .release is not supported.
   if (!T->hasSplitAcquireAndReleaseFences() &&
@@ -909,6 +905,11 @@ NVPTXDAGToDAGISel::insertMemoryInstructionFence(SDLoc DL, SDValue &Chain,
       getOperationOrderings(N, Subtarget);
   auto Scope = getOperationScope(N, InstructionOrdering);
 
+  // Singlethread scope has no inter-thread synchronization requirements, so
+  // the operation is lowered as plain and the fence is skipped.
+  if (Scope == NVPTX::Scope::Thread)
+    return {NVPTX::Ordering::NotAtomic, Scope};
+
   // If a fence is required before the operation, insert it:
   switch (NVPTX::Ordering(FenceOrdering)) {
   case NVPTX::Ordering::NotAtomic:
@@ -1857,9 +1858,16 @@ void NVPTXDAGToDAGISel::SelectI128toV2I64(SDNode *N) {
 bool NVPTXDAGToDAGISel::tryFence(SDNode *N) {
   SDLoc DL(N);
   assert(N->getOpcode() == ISD::ATOMIC_FENCE);
-  unsigned int FenceOp =
-      getFenceOp(NVPTX::Ordering(N->getConstantOperandVal(1)),
-                 Scopes[N->getConstantOperandVal(2)], Subtarget);
+  auto Scope = Scopes[N->getConstantOperandVal(2)];
+
+  // Singlethread fences have no inter-thread synchronization requirements.
+  if (Scope == NVPTX::Scope::Thread) {
+    ReplaceNode(N, N->getOperand(0).getNode());
+    return true;
+  }
+
+  unsigned int FenceOp = getFenceOp(
+      NVPTX::Ordering(N->getConstantOperandVal(1)), Scope, Subtarget);
   SDValue Chain = N->getOperand(0);
   SDNode *FenceNode = CurDAG->getMachineNode(FenceOp, DL, MVT::Other, Chain);
   ReplaceNode(N, FenceNode);
@@ -2310,4 +2318,4 @@ void NVPTXDAGToDAGISel::selectBR_JT(SDNode *N) {
                               SDValue(Chain, 0), SDValue(Chain, 1)});
 
   ReplaceNode(N, BrxEnd);
-}
\ No newline at end of file
+}



More information about the llvm-commits mailing list