Skip to content

Commit 0437ba7

Browse files
pxl-thvchuravy
andauthored
Dispatch to LLVM atomic OP (#21)
Co-authored-by: Valentin Churavy <v.churavy@gmail.com>
1 parent 98bb4ab commit 0437ba7

3 files changed

Lines changed: 61 additions & 1 deletion

File tree

Project.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ julia = "1.10"
1717
LLVM = "929cbde3-209d-540e-8aea-75f648917ca0"
1818
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1919
TestFunctionRunner = "792026f5-ac9a-4a19-adcb-47b0ce2deb5d"
20+
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
2021

2122
[targets]
22-
test = ["Test", "TestFunctionRunner", "LLVM"]
23+
test = ["Test", "TestFunctionRunner", "LLVM", "InteractiveUtils"]

ext/UnsafeAtomicsLLVM/atomics.jl

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,48 @@ end
257257
return old => x
258258
end
259259

260+
const atomictypes = Any[
261+
Int8,
262+
Int16,
263+
Int32,
264+
Int64,
265+
Int128,
266+
UInt8,
267+
UInt16,
268+
UInt32,
269+
UInt64,
270+
UInt128,
271+
Float16,
272+
Float32,
273+
Float64,
274+
]
275+
276+
for (opname, op, llvmop) in binoptable
277+
opname === :xchg && continue
278+
types = if opname in (:min, :max)
279+
filter(t -> t <: Signed, atomictypes)
280+
elseif opname in (:umin, :umax)
281+
filter(t -> t <: Unsigned, atomictypes)
282+
elseif opname in (:fadd, :fsub, :fmin, :fmax)
283+
filter(t -> t <: AbstractFloat, atomictypes)
284+
else
285+
filter(t -> t <: Integer, atomictypes)
286+
end
287+
for T in types
288+
@eval @inline function atomic_pointermodify(
289+
ptr::LLVMPtr{$T},
290+
::$(typeof(op)),
291+
x::$T,
292+
order::AtomicOrdering,
293+
sync::Val{S},
294+
) where {S}
295+
old = llvm_atomic_op(
296+
$(Val(llvmop)), ptr, x, llvm_from_julia_ordering(order), sync)
297+
return old => $op(old, x)
298+
end
299+
end
300+
end
301+
260302
# @inline atomic_pointerswap(pointer, new) = first(atomic_pointermodify(pointer, right, new))
261303
@inline atomic_pointerswap(pointer, new, order, sync) =
262304
first(atomic_pointermodify(pointer, right, new, order, sync))

test/UnsafeAtomicsLLVM.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import LLVM
2+
import InteractiveUtils
23

34
using UnsafeAtomics: UnsafeAtomics, acquire, release, acq_rel, seq_cst
45
using UnsafeAtomics.Internal: OP_RMW_TABLE, inttypes
@@ -34,6 +35,14 @@ function check_default_ordering(xs::AbstractArray{T}, x1::T, x2::T) where T
3435
xs[1] = x1
3536
@test rmw(ptr, x2) === x1
3637
@test xs[1] === op(x1, x2)
38+
39+
# Check dispatch to LLVM atomic OP instead of CAS loop.
40+
if (op == +) || (op == -)
41+
IR = sprint(io->InteractiveUtils.code_llvm(io,
42+
UnsafeAtomics.modify!,
43+
typeof.((ptr, +, T(1)))))
44+
@test occursin("atomicrmw", IR)
45+
end
3746
end
3847
end
3948
end
@@ -80,6 +89,14 @@ function test_explicit_ordering(xs::AbstractArray{T}, x1::T, x2::T) where T
8089
(x1 => op(x1, x2))
8190
@test xs[1] === op(x1, x2)
8291
end
92+
93+
# Check dispatch to LLVM atomic OP instead of CAS loop.
94+
if (op == +) || (op == -)
95+
IR = sprint(io->InteractiveUtils.code_llvm(io,
96+
UnsafeAtomics.modify!,
97+
typeof.((ptr, +, T(1), seq_cst, UnsafeAtomics.singlethread))))
98+
@test occursin("atomicrmw", IR)
99+
end
83100
end
84101
end
85102
end

0 commit comments

Comments
 (0)