You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Metal: bus error in the LLVM inliner on dynamic code, instead of an InvalidIRError #965
Compiling a Metal kernel that ends up with dynamic code crashes the process during optimization, instead of reporting an InvalidIRError:
using Metal, UnsafeAtomics # UnsafeAtomics from JuliaConcurrent/UnsafeAtomics.jl#30const UA = UnsafeAtomics
wrapper(p, x; kwargs...) = UA.add!(p, x, UA.monotonic, UA.device; kwargs...)
k(a) = (wrapper(pointer(a), Int32(1); volatile =true, align =8); nothing)
@metal threads=1k(MtlArray(Int32[0]))
[30093] signal 10 (1): Bus error: 10
_ZN12_GLOBAL__N_112CallAnalyzer7analyzeEv at .../libLLVM.dylib
llvm::getInlineCost(...)
...
llvm::InlinerPass::run(...)
...
llvm::ModuleInlinerWrapperPass::run(...)
LLVMRunJuliaPasses at LLVM/JGisQ/lib/18/libLLVM_extra.jl:319
run! at LLVM/JGisQ/src/newpm.jl:380
optimize_module! at GPUCompiler/src/metal.jl:425
optimize! at GPUCompiler/src/optim.jl:52
emit_llvm at GPUCompiler/src/driver.jl:176
GPUCompiler main (037ef5a), Julia 1.12.7, M1. The same crash happens with the Metal atomics branch (#942/#943). With #949, it crashed earlier instead, in check_allocation!/referenced_object.
The code is dynamic because Julia doesn't const-prop the keywords into the non-inlined wrapper, so align is a run-time value and Val(align) becomes a dynamic call to UnsafeAtomics' @generatedllvmcall primitive. Base.@constprop :aggressive on the wrapper avoids it. Metal.code_llvm(…; optimize = false) works and gives about 2,400 lines of IR (typejoin, _growbeg!, boxing, …); the crash is in the LLVM inliner over that module. A similar kernel whose dynamic code doesn't involve llvmcall (wrapper(a, x; kwargs...) = store(a, x, Val(kwargs[:index]))) is correctly reported as an InvalidIRError.
Activity