[llvm] [NVPTX] Add syncscope support for cmpxchg (PR #140812)

Akshay Deodhar via llvm-commits llvm-commits at lists.llvm.org
Fri May 30 16:42:02 PDT 2025


================
@@ -41,6 +41,27 @@ def AS_match {
   }];
 }
 
+multiclass nvvm_ternary_atomic_op_scoped<SDPatternOperator frag> {
+  defvar frag_pat = (frag node:$ptr, node:$cmp, node:$val);
+  def NAME#_cta: PatFrag<!setdagop(frag_pat, ops),
+      (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{
+        return Scopes[cast<MemSDNode>(N)->getSyncScopeID()] == NVPTX::Scope::Block;
+  }]>;
+  def NAME#_cluster : PatFrag<!setdagop(frag_pat, ops),
+      (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{
+        return Scopes[cast<MemSDNode>(N)->getSyncScopeID()] == NVPTX::Scope::Cluster;
+  }]>;
+  def NAME#_gpu: PatFrag<!setdagop(frag_pat, ops),
+      (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{
+        return Scopes[cast<MemSDNode>(N)->getSyncScopeID()] == NVPTX::Scope::Device;
+  }]>;
+  def NAME#_sys: PatFrag<!setdagop(frag_pat, ops),
+      (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{
+        return Scopes[cast<MemSDNode>(N)->getSyncScopeID()] == NVPTX::Scope::System;
+  }]>;
+}
----------------
akshayrdeodhar wrote:

There isn't a general mechanism, and I gave a lot of thought to creating one before creating this PR. The idea that I came up with was something like the following- an integer parameter to binary_atomic_op, and ternary_atomic_op called "scope".

Then either instantiate ternary_atomic_op<op, max_scopeid_across_backends> in TargetSelectionDAG, or have individual targets instantiate this multiclass based on the highest ID that they want to support. 

The first idea would require backends to mutually ensure that max(syncscope_id) across backends is maintained. 
```
multiclass ternary_atomic_op<SDNode atomic_op, int scopes = 2> { # default, singlethread and system
  foreach vt = [ i8, i16, i32, i64 ] in {
    def _#vt : PatFrag<(ops node:$ptr, node:$cmp, node:$val),
                       (atomic_op node:$ptr, node:$cmp, node:$val)> {
      let IsAtomic = true;
      let MemoryVT = vt;
    }

	foreach scope = !range(scopes) in {
		defvar scope_str = !cast<string>(scope);
		defvar frag_pat = (!cast<SDPatternOperator>(NAME_#_vt) node:$a node:$b node:$c)
		def _#vt_#scope_#scope_str : PatFrag<!setdagop(frag_pat, ops), frag_pat>;
		
		defm NAME#_#vt#_#scope_#scope_str : ternary_atomic_op_ord
	}

    defm NAME#_#vt  : ternary_atomic_op_ord;
  }
}
```

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


More information about the llvm-commits mailing list