[clang] [llvm] [HLSL] Add `InterlockedCompareStore` function and resource methods (PR #222164)

Joshua Batista via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 24 15:47:39 PDT 2026


================
@@ -833,24 +833,42 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
   }
 }
 
+// Shapes of the synthesized atomic overloads. The read-modify-write operations
+// can report the previous value through a trailing reference. Every argument
+// of compare-store is an input.
+enum class AtomicOverloadShape {
+  Binary,             // (dest, value)
+  BinaryWithOriginal, // (dest, value, original_value)
+  CompareStore,       // (dest, compare_value, value)
+};
+
 // Build a single overload of an HLSL atomic intrinsic in the hlsl namespace.
 // `dest` is an address-space-qualified reference; `original_value` (when
 // present) is a plain reference. The synthesized FunctionDecl aliases the
 // underlying clang builtin via BuiltinAliasAttr.
 static void buildAtomicOverload(Sema &S, NamespaceDecl *NS, StringRef FuncName,
                                 StringRef BuiltinName, QualType ElemTy,
-                                LangAS DestAS, bool ThreeArg) {
+                                LangAS DestAS, AtomicOverloadShape Shape) {
   ASTContext &AST = S.getASTContext();
 
   QualType DestTy =
       AST.getLValueReferenceType(AST.getAddrSpaceQualType(ElemTy, DestAS));
   QualType OrigRefTy = AST.getLValueReferenceType(ElemTy);
 
-  SmallVector<QualType, 3> ParamTypes;
-  ParamTypes.push_back(DestTy);
-  ParamTypes.push_back(ElemTy);
-  if (ThreeArg)
+  SmallVector<QualType, 3> ParamTypes = {DestTy, ElemTy};
+  if (Shape == AtomicOverloadShape::BinaryWithOriginal)
     ParamTypes.push_back(OrigRefTy);
+  else if (Shape == AtomicOverloadShape::CompareStore)
+    ParamTypes.push_back(ElemTy);
----------------
bob80905 wrote:

When checking against DXC, it looks like it automatically casts into uint. Your DXC example is probably in range of 0 - uint max.
Do you get the same thing if you try RWStructedBuffer<uint> ?
If you gave DXC something larger than uintmax, then it should emit `undef`.
DXC converts the operands to uint, where 2147483648 and 4294967040 are both in range, so it folds them to the bit patterns -2147483648 and -256. Clang converts to the destination element type `int`, where the same literals are out of range, so it warns and emits poison.

Give DXC a genuinely out-of-range value for uint, and it should emit undef, the old-LLVM equivalent of poison.
I think we want to keep the current behavior because if the buffer is of type int, then DXC emits undef, while clang emits -5.0f correctly as -5u.

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


More information about the llvm-commits mailing list