Skip to content

Commit

Permalink
Extend atomic instruction APIs (#495)
Browse files Browse the repository at this point in the history
  • Loading branch information
maleadt authored Dec 20, 2024
1 parent a4ed387 commit ff15977
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 6 deletions.
7 changes: 7 additions & 0 deletions docs/src/lib/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ ordering!
SyncScope
syncscope
syncscope!
binop
isweak
weak!
success_ordering
success_ordering!
failure_ordering
failure_ordering!
```

## Call instructions
Expand Down
7 changes: 6 additions & 1 deletion docs/src/man/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,14 @@ the instruction. This is done by calling the `debuglocation!` function on the bu
Atomic instructions support a few additional APIs:

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


## Call sites instructions
Expand Down
66 changes: 65 additions & 1 deletion src/core/instructions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ predicate(inst::FCmpInst) = API.LLVMGetFCmpPredicate(inst)

## atomics

export is_atomic, ordering, ordering!, SyncScope, syncscope, syncscope!
export is_atomic, ordering, ordering!, SyncScope, syncscope, syncscope!, binop,
isweak, weak!, success_ordering, success_ordering!, failure_ordering, failure_ordering!

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

Expand Down Expand Up @@ -209,6 +210,69 @@ function syncscope!(inst::AtomicInst, scope::SyncScope)
API.LLVMSetAtomicSyncScopeID(inst, scope)
end

"""
binop(inst::AtomicRMWInst)
Get the binary operation of the given atomic read-modify-write instruction.
"""
function binop(inst::AtomicRMWInst)
API.LLVMGetAtomicRMWBinOp(inst)
end

"""
isweak(inst::AtomicCmpXchgInst)
Check if the given atomic compare-and-exchange instruction is weak.
"""
function isweak(inst::AtomicCmpXchgInst)
API.LLVMGetWeak(inst) |> Bool
end

"""
weak!(inst::AtomicCmpXchgInst, is_weak::Bool)
Set whether the given atomic compare-and-exchange instruction is weak.
"""
function weak!(inst::AtomicCmpXchgInst, is_weak::Bool)
API.LLVMSetWeak(inst, is_weak)
end

"""
success_ordering(inst::AtomicCmpXchgInst)
Get the success ordering of the given atomic compare-and-exchange instruction.
"""
function success_ordering(inst::AtomicCmpXchgInst)
API.LLVMGetCmpXchgSuccessOrdering(inst)
end

"""
success_ordering!(inst::AtomicCmpXchgInst, ord::API.LLVMAtomicOrdering)
Set the success ordering of the given atomic compare-and-exchange instruction.
"""
function success_ordering!(inst::AtomicCmpXchgInst, ord::API.LLVMAtomicOrdering)
API.LLVMSetCmpXchgSuccessOrdering(inst, ord)
end

"""
failure_ordering(inst::AtomicCmpXchgInst)
Get the failure ordering of the given atomic compare-and-exchange instruction.
"""
function failure_ordering(inst::AtomicCmpXchgInst)
API.LLVMGetCmpXchgFailureOrdering(inst)
end

"""
failure_ordering!(inst::AtomicCmpXchgInst, ord::API.LLVMAtomicOrdering)
Set the failure ordering of the given atomic compare-and-exchange instruction.
"""
function failure_ordering!(inst::AtomicCmpXchgInst, ord::API.LLVMAtomicOrdering)
API.LLVMSetCmpXchgFailureOrdering(inst, ord)
end


## call sites and invocations

Expand Down
2 changes: 1 addition & 1 deletion src/newpm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ function NewPMPassBuilder(; kwargs...)
API.LLVMPassBuilderOptionsSetSLPVectorization(obj, value)
elseif name == :loop_unrolling
API.LLVMPassBuilderOptionsSetLoopUnrolling(obj, value)
elseif loop == :forget_all_scev_in_loop_unroll
elseif name == :forget_all_scev_in_loop_unroll
API.LLVMPassBuilderOptionsSetForgetAllSCEVInLoopUnroll(obj, value)
elseif name == :licm_mssa_opt_cap
API.LLVMPassBuilderOptionsSetLicmMSSAOptCap(obj, value)
Expand Down
5 changes: 2 additions & 3 deletions src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ end
Simpler version of [`clone_into!`](@ref) that clones a function `f` into a new function,
optionally mapping values according to the `value_map` dictionary.
"""
function clone(f::Function; value_map::Dict{<:Value,<:Value}=Dict{Value,Value}())
function clone(f::Function; value_map::Dict{<:Value,<:Value}=Dict{Value,Value}(), kwargs...)
argtypes = LLVMType[]

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

clone_into!(new_f, f;
value_map, changes=API.LLVMCloneFunctionChangeTypeLocalChangesOnly)
clone_into!(new_f, f; value_map, kwargs...)

return new_f
end
Expand Down
21 changes: 21 additions & 0 deletions test/instructions_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,27 @@
else
@check_ir atomic_rmw_inst "atomicrmw add ptr %4, i32 %0 seq_cst"
end
@test binop(atomic_rmw_inst) == LLVM.API.LLVMAtomicRMWBinOpAdd
@test syncscope(atomic_rmw_inst) == SyncScope("system")
syncscope!(atomic_rmw_inst, SyncScope("agent"))
@test syncscope(atomic_rmw_inst) == SyncScope("agent")

atomic_cmpxchg_inst = atomic_cmpxchg!(builder, ptr1, int1, int2,
LLVM.API.LLVMAtomicOrderingSequentiallyConsistent, LLVM.API.LLVMAtomicOrderingAcquire, single_thread)
if supports_typed_pointers(ctx)
@check_ir atomic_cmpxchg_inst "cmpxchg i32* %4, i32 %0, i32 %1 seq_cst acquire"
else
@check_ir atomic_cmpxchg_inst "cmpxchg ptr %4, i32 %0, i32 %1 seq_cst acquire"
end
@test success_ordering(atomic_cmpxchg_inst) == LLVM.API.LLVMAtomicOrderingSequentiallyConsistent
success_ordering!(atomic_cmpxchg_inst, LLVM.API.LLVMAtomicOrderingAcquireRelease)
@test success_ordering(atomic_cmpxchg_inst) == LLVM.API.LLVMAtomicOrderingAcquireRelease
@test failure_ordering(atomic_cmpxchg_inst) == LLVM.API.LLVMAtomicOrderingAcquire
failure_ordering!(atomic_cmpxchg_inst, LLVM.API.LLVMAtomicOrderingMonotonic)
@test failure_ordering(atomic_cmpxchg_inst) == LLVM.API.LLVMAtomicOrderingMonotonic
@test !isweak(atomic_cmpxchg_inst)
weak!(atomic_cmpxchg_inst, true)
@test isweak(atomic_cmpxchg_inst)

single_thread = true
atomic_rmw_inst = atomic_rmw!(builder,
Expand Down

0 comments on commit ff15977

Please sign in to comment.