|
1 | 1 | # implementation of the GPUCompiler interfaces for generating GCN code |
2 | 2 |
|
| 3 | +const AMDGPU_LLVM_Backend_jll = |
| 4 | + LazyModule("AMDGPU_LLVM_Backend_jll", |
| 5 | + UUID("cc5c0156-bd05-5a77-8a68-bb0aafb29019")) |
| 6 | + |
3 | 7 | ## target |
4 | 8 |
|
5 | 9 | export GCNCompilerTarget |
6 | 10 |
|
7 | 11 | Base.@kwdef struct GCNCompilerTarget <: AbstractCompilerTarget |
8 | 12 | dev_isa::String |
9 | 13 | features::String="" |
| 14 | + |
| 15 | + backend::Symbol = isavailable(AMDGPU_LLVM_Backend_jll) ? :external : :inprocess |
10 | 16 | end |
11 | | -GCNCompilerTarget(dev_isa; features="") = GCNCompilerTarget(dev_isa, features) |
| 17 | +GCNCompilerTarget(dev_isa; kwargs...) = GCNCompilerTarget(; dev_isa, kwargs...) |
12 | 18 |
|
13 | 19 | llvm_triple(::GCNCompilerTarget) = "amdgcn-amd-amdhsa" |
14 | 20 |
|
|
35 | 41 |
|
36 | 42 | # TODO: encode debug build or not in the compiler job |
37 | 43 | # https://github.com/JuliaGPU/CUDAnative.jl/issues/368 |
38 | | -runtime_slug(job::CompilerJob{GCNCompilerTarget}) = "gcn-$(job.config.target.dev_isa)$(job.config.target.features)" |
| 44 | +runtime_slug(job::CompilerJob{GCNCompilerTarget}) = "gcn-$(job.config.target.dev_isa)$(job.config.target.features)-$(job.config.target.backend)" |
39 | 45 |
|
40 | 46 | const gcn_intrinsics = () # TODO: ("vprintf", "__assertfail", "malloc", "free") |
41 | 47 | isintrinsic(::CompilerJob{GCNCompilerTarget}, fn::String) = in(fn, gcn_intrinsics) |
@@ -153,6 +159,70 @@ function add_kernarg_address_spaces!( |
153 | 159 | return new_f |
154 | 160 | end |
155 | 161 |
|
| 162 | +@unlocked function mcgen(@nospecialize(job::CompilerJob{GCNCompilerTarget}), |
| 163 | + mod::LLVM.Module, format=LLVM.API.LLVMAssemblyFile) |
| 164 | + target = job.config.target |
| 165 | + |
| 166 | + if target.backend === :inprocess |
| 167 | + if :AMDGPU ∉ LLVM.backends() |
| 168 | + error("The in-process LLVM lacks the AMDGPU target; cannot compile to GCN. " * |
| 169 | + "Load AMDGPU_LLVM_Backend_jll and use `backend=:external` instead.") |
| 170 | + end |
| 171 | + return invoke(mcgen, Tuple{CompilerJob, LLVM.Module, typeof(format)}, |
| 172 | + job, mod, format) |
| 173 | + elseif target.backend !== :external |
| 174 | + error("Unsupported GCN back-end $(repr(target.backend)); " * |
| 175 | + "expected :external or :inprocess.") |
| 176 | + end |
| 177 | + |
| 178 | + if !isavailable(AMDGPU_LLVM_Backend_jll) || !AMDGPU_LLVM_Backend_jll.is_available() |
| 179 | + error("The :external GCN back-end requires AMDGPU_LLVM_Backend_jll, which " * |
| 180 | + "should be installed and loaded first.") |
| 181 | + end |
| 182 | + |
| 183 | + filetype = if format == LLVM.API.LLVMAssemblyFile |
| 184 | + "asm" |
| 185 | + elseif format == LLVM.API.LLVMObjectFile |
| 186 | + "obj" |
| 187 | + else |
| 188 | + error("Unsupported GCN output format $format") |
| 189 | + end |
| 190 | + |
| 191 | + input = tempname(cleanup=false) * ".bc" |
| 192 | + output = tempname(cleanup=false) * (filetype == "asm" ? ".s" : ".o") |
| 193 | + write(input, mod) |
| 194 | + |
| 195 | + cmd = `$(AMDGPU_LLVM_Backend_jll.llc()) $input |
| 196 | + -mtriple=$(llvm_triple(target)) |
| 197 | + -mcpu=$(target.dev_isa) |
| 198 | + -mattr=$(target.features) |
| 199 | + --relocation-model=pic |
| 200 | + -filetype=$filetype |
| 201 | + -o $output` |
| 202 | + out = Pipe() |
| 203 | + proc = run(pipeline(ignorestatus(cmd); stdout=out, stderr=out); wait=false) |
| 204 | + close(out.in) |
| 205 | + log = strip(read(out, String)) |
| 206 | + wait(proc) |
| 207 | + if !success(proc) |
| 208 | + # keep the input around for debugging |
| 209 | + msg = "Failed to compile to GCN with external llc" |
| 210 | + isempty(log) || (msg *= ":\n" * log) |
| 211 | + msg *= "\nIf you think this is a bug, please file an issue and attach $(input)." |
| 212 | + isfile(output) && rm(output) |
| 213 | + error(msg) |
| 214 | + elseif !isempty(log) |
| 215 | + # llc only diagnoses on stderr; even successful compilation may e.g. have |
| 216 | + # ignored an unrecognized CPU or feature, so make sure this surfaces. |
| 217 | + @warn "External llc reported:\n$log" |
| 218 | + end |
| 219 | + |
| 220 | + code = filetype == "asm" ? read(output, String) : String(read(output)) |
| 221 | + rm(input) |
| 222 | + rm(output) |
| 223 | + return code |
| 224 | +end |
| 225 | + |
156 | 226 |
|
157 | 227 | ## LLVM passes |
158 | 228 |
|
|
0 commit comments