Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ ChainRulesCore = "1"
EnzymeCore = "0.8"
ExprTools = "0.1"
GPUArrays = "11.5.14"
GPUCompiler = "2.12"
GPUCompiler = "2.13"
GPUToolbox = "3"
KernelAbstractions = "0.9.2"
LLVM = "10"
Expand Down
11 changes: 1 addition & 10 deletions src/compiler/codegen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,7 @@ function annotate_atomics!(mod::LLVM.Module, job::HIPCompilerJob)
for fn in mod.functions, bb in fn.blocks, inst in bb.instructions
inst isa LLVM.AtomicRMWInst || continue
md = inst.metadata
if params.atomic_memory_assumptions && inst.syncscope.name in NARROW_SYNCSCOPES &&
!usub_sat_unselectable(inst)
if params.atomic_memory_assumptions && inst.syncscope.name in NARROW_SYNCSCOPES
md["amdgpu.no.fine.grained.memory"] = empty_md
md["amdgpu.no.remote.memory"] = empty_md
end
Expand All @@ -184,14 +183,6 @@ function denormal_metadata_name(target::GCNCompilerTarget)
llvm >= v"24" ? "atomic.ignore.denormal.mode" : "amdgpu.ignore.denormal.mode"
end

# LLVM 22+ fails with "Cannot select: AtomicLoadUSubSat" when it may use the native
# instruction for an i32 flat `usub_sat` on gfx10.3/gfx11, which either memory assumption
# allows (llvm/llvm-project#229442). Global pointers select fine. Interim workaround
# until GPUCompiler expands the unselectable cases to CAS loops.
usub_sat_unselectable(inst::LLVM.AtomicRMWInst) =
inst.binop == LLVM.AtomicRMWBinOp.USubSat &&
LLVM.addrspace(LLVM.value_type(LLVM.operands(inst)[1])) != AS.Global

# LLVM only folds `llvm.amdgcn.wavefrontsize` during instruction selection, which then
# fails on branches for the other wavefront size (e.g. in `ballot`), so fold it here.
function fold_wavefrontsize!(mod::LLVM.Module, wavefrontsize64::Bool)
Expand Down
17 changes: 11 additions & 6 deletions test/core/codegen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,15 @@ end

# compile for a GPU other than the local one, e.g. one whose atomics depend on the metadata
function compile_offline(f, tt, format; dev_isa="gfx90a", backend=:external,
unsafe_fp_atomics=true, atomic_memory_assumptions=true)
unsafe_fp_atomics=true, atomic_memory_assumptions=true,
validate=true)
wf64 = !startswith(dev_isa, "gfx1")
features = wf64 ? "-wavefrontsize32,+wavefrontsize64" : "+wavefrontsize32,-wavefrontsize64"
target = GPUCompiler.GCNCompilerTarget(; dev_isa, features, backend)
params = AMDGPU.Compiler.HIPCompilerParams(wf64, unsafe_fp_atomics,
atomic_memory_assumptions)
config = GPUCompiler.CompilerConfig(target, params; kernel=true, always_inline=true)
config = GPUCompiler.CompilerConfig(target, params; kernel=true, always_inline=true,
validate)
job = GPUCompiler.CompilerJob(GPUCompiler.methodinstance(typeof(f), tt), config)
GPUCompiler.JuliaContext() do _
if format === :llvm
Expand Down Expand Up @@ -233,7 +235,9 @@ end
("cluster-one-as", true), ("one-as", false),
("unknown-scope", false))
scope = UnsafeAtomics.SyncScope(Symbol(name))
ir = compile_offline(rmw_kernel, rmw_tt(Int32, max, scope), :llvm)
# (GPUCompiler rejects unknown scopes when validating the IR)
ir = compile_offline(rmw_kernel, rmw_tt(Int32, max, scope), :llvm;
validate=name != "unknown-scope")
rmw = only(atomic_lines(ir, "atomicrmw"))
@test occursin("syncscope(\"$name\")", rmw)
@test assumed ? memory_md(rmw) : no_memory_md(rmw)
Expand Down Expand Up @@ -284,12 +288,13 @@ end

# UnsafeAtomics only emits `atomicrmw usub_sat` with LLVM 20+
Base.libllvm_version >= v"20" && @testset "flat usub_sat" begin
# LLVM 22+ can't select a native flat usub_sat on gfx10.3/gfx11, which the
# memory assumptions would permit
# LLVM 22 couldn't select a native flat usub_sat on gfx10.3/gfx11 with the memory
# assumptions (llvm/llvm-project#229442), which GPUCompiler works around, so they
# are attached like for other operations
flat_tt = Tuple{Core.LLVMPtr{Core.LLVMPtr{UInt32,0},1}, UInt32,
typeof(UnsafeAtomics.sub_sat), typeof(UnsafeAtomics.device)}
ir = compile_offline(flat_rmw_kernel, flat_tt, :llvm; dev_isa="gfx1030")
@test no_memory_md(only(atomic_lines(ir, "atomicrmw")))
@test memory_md(only(atomic_lines(ir, "atomicrmw")))
if external
asm = compile_offline(flat_rmw_kernel, flat_tt, :asm; dev_isa="gfx1030")
@test occursin("flat_atomic_cmpswap", asm)
Expand Down