diff --git a/Project.toml b/Project.toml index 1e7b1bb50..3c7095546 100644 --- a/Project.toml +++ b/Project.toml @@ -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" diff --git a/src/compiler/codegen.jl b/src/compiler/codegen.jl index 801ad1549..642b4a2b6 100644 --- a/src/compiler/codegen.jl +++ b/src/compiler/codegen.jl @@ -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 @@ -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) diff --git a/test/core/codegen.jl b/test/core/codegen.jl index d9937945e..3b8e55ece 100644 --- a/test/core/codegen.jl +++ b/test/core/codegen.jl @@ -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 @@ -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) @@ -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)