Skip to content

Commit ff15977

Browse files
authored
Extend atomic instruction APIs (#495)
1 parent a4ed387 commit ff15977

File tree

6 files changed

+102
-6
lines changed

6 files changed

+102
-6
lines changed

docs/src/lib/instructions.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ ordering!
4040
SyncScope
4141
syncscope
4242
syncscope!
43+
binop
44+
isweak
45+
weak!
46+
success_ordering
47+
success_ordering!
48+
failure_ordering
49+
failure_ordering!
4350
```
4451

4552
## Call instructions

docs/src/man/instructions.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,14 @@ the instruction. This is done by calling the `debuglocation!` function on the bu
8888
Atomic instructions support a few additional APIs:
8989

9090
- `is_atomic`: check if the instruction is atomic.
91-
- `ordering`/`ordering!`: get or set the ordering of the instruction.
91+
- `isweak`/`weak!`: check if the instruction is weak, or set it to be weak.
9292
- `syncscope`/`syncscope!`: get or set the synchronization scope of the instruction to
9393
a specific `SyncScope`
94+
- `ordering`/`ordering!`: get or set the ordering of the instruction.
95+
- `success_ordering`/`success_ordering!`: get or set the success ordering of an atomic
96+
compare-and-swap instruction.
97+
- `failure_ordering`/`failure_ordering!`: get or set the failure ordering of an atomic
98+
- `binop`: to get the binary operation of an atomic read-modify-write instruction.
9499

95100

96101
## Call sites instructions

src/core/instructions.jl

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ predicate(inst::FCmpInst) = API.LLVMGetFCmpPredicate(inst)
121121

122122
## atomics
123123

124-
export is_atomic, ordering, ordering!, SyncScope, syncscope, syncscope!
124+
export is_atomic, ordering, ordering!, SyncScope, syncscope, syncscope!, binop,
125+
isweak, weak!, success_ordering, success_ordering!, failure_ordering, failure_ordering!
125126

126127
const AtomicInst = Union{LoadInst, StoreInst, FenceInst, AtomicRMWInst, AtomicCmpXchgInst}
127128

@@ -209,6 +210,69 @@ function syncscope!(inst::AtomicInst, scope::SyncScope)
209210
API.LLVMSetAtomicSyncScopeID(inst, scope)
210211
end
211212

213+
"""
214+
binop(inst::AtomicRMWInst)
215+
216+
Get the binary operation of the given atomic read-modify-write instruction.
217+
"""
218+
function binop(inst::AtomicRMWInst)
219+
API.LLVMGetAtomicRMWBinOp(inst)
220+
end
221+
222+
"""
223+
isweak(inst::AtomicCmpXchgInst)
224+
225+
Check if the given atomic compare-and-exchange instruction is weak.
226+
"""
227+
function isweak(inst::AtomicCmpXchgInst)
228+
API.LLVMGetWeak(inst) |> Bool
229+
end
230+
231+
"""
232+
weak!(inst::AtomicCmpXchgInst, is_weak::Bool)
233+
234+
Set whether the given atomic compare-and-exchange instruction is weak.
235+
"""
236+
function weak!(inst::AtomicCmpXchgInst, is_weak::Bool)
237+
API.LLVMSetWeak(inst, is_weak)
238+
end
239+
240+
"""
241+
success_ordering(inst::AtomicCmpXchgInst)
242+
243+
Get the success ordering of the given atomic compare-and-exchange instruction.
244+
"""
245+
function success_ordering(inst::AtomicCmpXchgInst)
246+
API.LLVMGetCmpXchgSuccessOrdering(inst)
247+
end
248+
249+
"""
250+
success_ordering!(inst::AtomicCmpXchgInst, ord::API.LLVMAtomicOrdering)
251+
252+
Set the success ordering of the given atomic compare-and-exchange instruction.
253+
"""
254+
function success_ordering!(inst::AtomicCmpXchgInst, ord::API.LLVMAtomicOrdering)
255+
API.LLVMSetCmpXchgSuccessOrdering(inst, ord)
256+
end
257+
258+
"""
259+
failure_ordering(inst::AtomicCmpXchgInst)
260+
261+
Get the failure ordering of the given atomic compare-and-exchange instruction.
262+
"""
263+
function failure_ordering(inst::AtomicCmpXchgInst)
264+
API.LLVMGetCmpXchgFailureOrdering(inst)
265+
end
266+
267+
"""
268+
failure_ordering!(inst::AtomicCmpXchgInst, ord::API.LLVMAtomicOrdering)
269+
270+
Set the failure ordering of the given atomic compare-and-exchange instruction.
271+
"""
272+
function failure_ordering!(inst::AtomicCmpXchgInst, ord::API.LLVMAtomicOrdering)
273+
API.LLVMSetCmpXchgFailureOrdering(inst, ord)
274+
end
275+
212276

213277
## call sites and invocations
214278

src/newpm.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ function NewPMPassBuilder(; kwargs...)
203203
API.LLVMPassBuilderOptionsSetSLPVectorization(obj, value)
204204
elseif name == :loop_unrolling
205205
API.LLVMPassBuilderOptionsSetLoopUnrolling(obj, value)
206-
elseif loop == :forget_all_scev_in_loop_unroll
206+
elseif name == :forget_all_scev_in_loop_unroll
207207
API.LLVMPassBuilderOptionsSetForgetAllSCEVInLoopUnroll(obj, value)
208208
elseif name == :licm_mssa_opt_cap
209209
API.LLVMPassBuilderOptionsSetLicmMSSAOptCap(obj, value)

src/utils.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ end
6464
Simpler version of [`clone_into!`](@ref) that clones a function `f` into a new function,
6565
optionally mapping values according to the `value_map` dictionary.
6666
"""
67-
function clone(f::Function; value_map::Dict{<:Value,<:Value}=Dict{Value,Value}())
67+
function clone(f::Function; value_map::Dict{<:Value,<:Value}=Dict{Value,Value}(), kwargs...)
6868
argtypes = LLVMType[]
6969

7070
# The user might be deleting arguments to the function by specifying them in
@@ -96,8 +96,7 @@ function clone(f::Function; value_map::Dict{<:Value,<:Value}=Dict{Value,Value}()
9696
end
9797
end
9898

99-
clone_into!(new_f, f;
100-
value_map, changes=API.LLVMCloneFunctionChangeTypeLocalChangesOnly)
99+
clone_into!(new_f, f; value_map, kwargs...)
101100

102101
return new_f
103102
end

test/instructions_tests.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,27 @@
239239
else
240240
@check_ir atomic_rmw_inst "atomicrmw add ptr %4, i32 %0 seq_cst"
241241
end
242+
@test binop(atomic_rmw_inst) == LLVM.API.LLVMAtomicRMWBinOpAdd
243+
@test syncscope(atomic_rmw_inst) == SyncScope("system")
244+
syncscope!(atomic_rmw_inst, SyncScope("agent"))
245+
@test syncscope(atomic_rmw_inst) == SyncScope("agent")
246+
247+
atomic_cmpxchg_inst = atomic_cmpxchg!(builder, ptr1, int1, int2,
248+
LLVM.API.LLVMAtomicOrderingSequentiallyConsistent, LLVM.API.LLVMAtomicOrderingAcquire, single_thread)
249+
if supports_typed_pointers(ctx)
250+
@check_ir atomic_cmpxchg_inst "cmpxchg i32* %4, i32 %0, i32 %1 seq_cst acquire"
251+
else
252+
@check_ir atomic_cmpxchg_inst "cmpxchg ptr %4, i32 %0, i32 %1 seq_cst acquire"
253+
end
254+
@test success_ordering(atomic_cmpxchg_inst) == LLVM.API.LLVMAtomicOrderingSequentiallyConsistent
255+
success_ordering!(atomic_cmpxchg_inst, LLVM.API.LLVMAtomicOrderingAcquireRelease)
256+
@test success_ordering(atomic_cmpxchg_inst) == LLVM.API.LLVMAtomicOrderingAcquireRelease
257+
@test failure_ordering(atomic_cmpxchg_inst) == LLVM.API.LLVMAtomicOrderingAcquire
258+
failure_ordering!(atomic_cmpxchg_inst, LLVM.API.LLVMAtomicOrderingMonotonic)
259+
@test failure_ordering(atomic_cmpxchg_inst) == LLVM.API.LLVMAtomicOrderingMonotonic
260+
@test !isweak(atomic_cmpxchg_inst)
261+
weak!(atomic_cmpxchg_inst, true)
262+
@test isweak(atomic_cmpxchg_inst)
242263

243264
single_thread = true
244265
atomic_rmw_inst = atomic_rmw!(builder,

0 commit comments

Comments
 (0)