[llvm] [SPIRV] Add missing OpenCL atomic_fetch_min/max builtin mappings (PR #186971)

via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 17 01:09:46 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-spir-v

Author: Paulius Velesko (pvelesko)

<details>
<summary>Changes</summary>

## Summary

- Add missing `atomic_fetch_min/max`, `atomic_fetch_min/max_explicit`, and legacy `atom_min/max` OpenCL builtin-to-SPIR-V opcode mappings in `SPIRVBuiltins.td`
- Add `OpAtomicSMax/SMin/UMax/UMin` cases to the atomic RMW dispatch in `generateAtomicInst`
- Handle signed/unsigned opcode selection in `buildAtomicRMWInst` based on the `OpTypeInt` signedness operand

The backend already had mappings for `atomic_fetch_add/sub/or/xor/and` and their `_explicit` variants, but was missing `min/max`. This caused OpenCL programs using these atomics to emit unresolved function calls instead of the correct `OpAtomicSMin/OpAtomicSMax/OpAtomicUMin/OpAtomicUMax` instructions.

## Test plan

- [ ] Verified with chipStar test suite: 10 `atomicMin/Max` tests and `cuda-simpleAtomicIntrinsics` now pass on the in-tree SPIR-V backend (previously failed with "Missing definition for `atomic_fetch_max_explicit`")
- [ ] Need to add a lit test for `atomic_fetch_min/max_explicit` → `OpAtomicSMin/OpAtomicSMax/OpAtomicUMin/OpAtomicUMax` lowering

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


2 Files Affected:

- (modified) llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp (+15) 
- (modified) llvm/lib/Target/SPIRV/SPIRVBuiltins.td (+6) 


``````````diff
diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index f9a9127446013..95adf05b91c8d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -840,6 +840,17 @@ static bool buildAtomicRMWInst(const SPIRV::IncomingCall *Call, unsigned Opcode,
                                          Semantics, MIRBuilder, GR);
   Register ValueReg = Call->Arguments[1];
   Register ValueTypeReg = GR->getSPIRVTypeID(Call->ReturnType);
+  // For min/max atomics, select signed or unsigned opcode based on the
+  // integer return type's signedness.
+  if (Call->ReturnType->getOpcode() == SPIRV::OpTypeInt) {
+    bool IsUnsigned = Call->ReturnType->getOperand(2).getImm() == 0;
+    if (IsUnsigned) {
+      if (Opcode == SPIRV::OpAtomicSMax)
+        Opcode = SPIRV::OpAtomicUMax;
+      else if (Opcode == SPIRV::OpAtomicSMin)
+        Opcode = SPIRV::OpAtomicUMin;
+    }
+  }
   // support cl_ext_float_atomics
   if (Call->ReturnType->getOpcode() == SPIRV::OpTypeFloat) {
     if (Opcode == SPIRV::OpAtomicIAdd) {
@@ -1775,6 +1786,10 @@ static bool generateAtomicInst(const SPIRV::IncomingCall *Call,
   case SPIRV::OpAtomicXor:
   case SPIRV::OpAtomicAnd:
   case SPIRV::OpAtomicExchange:
+  case SPIRV::OpAtomicSMax:
+  case SPIRV::OpAtomicSMin:
+  case SPIRV::OpAtomicUMax:
+  case SPIRV::OpAtomicUMin:
     return buildAtomicRMWInst(Call, Opcode, MIRBuilder, GR);
   case SPIRV::OpMemoryBarrier:
     return buildBarrierInst(Call, SPIRV::OpMemoryBarrier, MIRBuilder, GR);
diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
index eb1b6c3185e7d..630fb762c6eb2 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
@@ -633,6 +633,12 @@ defm : DemangledNativeBuiltin<"atomic_fetch_sub_explicit", OpenCL_std, Atomic, 3
 defm : DemangledNativeBuiltin<"atomic_fetch_or_explicit", OpenCL_std, Atomic, 3, 4, OpAtomicOr>;
 defm : DemangledNativeBuiltin<"atomic_fetch_xor_explicit", OpenCL_std, Atomic, 3, 4, OpAtomicXor>;
 defm : DemangledNativeBuiltin<"atomic_fetch_and_explicit", OpenCL_std, Atomic, 3, 4, OpAtomicAnd>;
+defm : DemangledNativeBuiltin<"atomic_fetch_min", OpenCL_std, Atomic, 2, 4, OpAtomicSMin>;
+defm : DemangledNativeBuiltin<"atomic_fetch_max", OpenCL_std, Atomic, 2, 4, OpAtomicSMax>;
+defm : DemangledNativeBuiltin<"atomic_fetch_min_explicit", OpenCL_std, Atomic, 3, 4, OpAtomicSMin>;
+defm : DemangledNativeBuiltin<"atomic_fetch_max_explicit", OpenCL_std, Atomic, 3, 4, OpAtomicSMax>;
+defm : DemangledNativeBuiltin<"atom_min", OpenCL_std, Atomic, 2, 2, OpAtomicSMin>;
+defm : DemangledNativeBuiltin<"atom_max", OpenCL_std, Atomic, 2, 2, OpAtomicSMax>;
 defm : DemangledNativeBuiltin<"atomic_flag_test_and_set", OpenCL_std, Atomic, 1, 1, OpAtomicFlagTestAndSet>;
 defm : DemangledNativeBuiltin<"__spirv_AtomicFlagTestAndSet", OpenCL_std, Atomic, 3, 3, OpAtomicFlagTestAndSet>;
 defm : DemangledNativeBuiltin<"atomic_flag_test_and_set_explicit", OpenCL_std, Atomic, 2, 3, OpAtomicFlagTestAndSet>;

``````````

</details>


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


More information about the llvm-commits mailing list