@@ -248,14 +248,15 @@ const binoptable = [
248248 (:umin , min, LLVM. API. LLVMAtomicRMWBinOpUMin),
249249 (:fadd , + , LLVM. API. LLVMAtomicRMWBinOpFAdd),
250250 (:fsub , - , LLVM. API. LLVMAtomicRMWBinOpFSub),
251+ (:fmax , max, LLVM. API. LLVMAtomicRMWBinOpFMax),
252+ (:fmin , min, LLVM. API. LLVMAtomicRMWBinOpFMin),
251253]
252- if VERSION ≥ v " 1.10-"
253- push! (binoptable, (:fmax , max, LLVM. API. LLVMAtomicRMWBinOpFMax))
254- push! (binoptable, (:fmin , min, LLVM. API. LLVMAtomicRMWBinOpFMin))
255- end
256254
257255const AtomicRMWBinOpVal = Union{(Val{binop} for (_, _, binop) in binoptable). .. }
258256
257+ # LLVM API accepts string literal as a syncscope argument.
258+ @inline syncscope_to_string (:: Type{Val{S}} ) where {S} = string (S)
259+
259260@generated function llvm_atomic_op (
260261 binop:: AtomicRMWBinOpVal ,
261262 ptr:: LLVMPtr{T,A} ,
@@ -293,6 +294,40 @@ const AtomicRMWBinOpVal = Union{(Val{binop} for (_, _, binop) in binoptable)...}
293294 end
294295end
295296
297+ @generated function llvm_atomic_op (
298+ binop:: AtomicRMWBinOpVal ,
299+ ptr:: LLVMPtr{T,A} ,
300+ val:: T ,
301+ order:: LLVMOrderingVal ,
302+ syncscope:: Val{S} ,
303+ ) where {T,A,S}
304+ @dispose ctx = Context () begin
305+ T_val = convert (LLVMType, T)
306+ T_ptr = convert (LLVMType, ptr)
307+
308+ T_typed_ptr = LLVM. PointerType (T_val, A)
309+ llvm_f, _ = create_function (T_val, [T_ptr, T_val])
310+
311+ @dispose builder = IRBuilder () begin
312+ entry = BasicBlock (llvm_f, " entry" )
313+ position! (builder, entry)
314+
315+ typed_ptr = bitcast! (builder, parameters (llvm_f)[1 ], T_typed_ptr)
316+ rv = atomic_rmw! (
317+ builder,
318+ _valueof (binop ()),
319+ typed_ptr,
320+ parameters (llvm_f)[2 ],
321+ _valueof (order ()),
322+ syncscope_to_string (syncscope),
323+ )
324+
325+ ret! (builder, rv)
326+ end
327+ call_function (llvm_f, T, Tuple{LLVMPtr{T,A},T}, :ptr , :val )
328+ end
329+ end
330+
296331@inline function atomic_pointermodify (pointer, op:: OP , x, order:: Symbol ) where {OP}
297332 @dynamic_order (order) do order
298333 atomic_pointermodify (pointer, op, x, order)
@@ -359,8 +394,18 @@ for (opname, op, llvmop) in binoptable
359394 :: $ (typeof (op)),
360395 x:: $T ,
361396 order:: AtomicOrdering ,
362- )
363- old = llvm_atomic_op ($ (Val (llvmop)), ptr, x, llvm_from_julia_ordering (order))
397+ syncscope:: Val{S} = Val {:system} (),
398+ ) where {S}
399+ old =
400+ syncscope isa Val{:system } ?
401+ llvm_atomic_op ($ (Val (llvmop)), ptr, x, llvm_from_julia_ordering (order)) :
402+ llvm_atomic_op (
403+ $ (Val (llvmop)),
404+ ptr,
405+ x,
406+ llvm_from_julia_ordering (order),
407+ syncscope,
408+ )
364409 return old => $ op (old, x)
365410 end
366411 end
0 commit comments