[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