Skip to content

Commit 9218172

Browse files
committed
Adapt to LLVM.jl 6.
1 parent e1f9a7d commit 9218172

27 files changed

+334
-387
lines changed

Manifest.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ version = "1.4.1"
3939

4040
[[LLVM]]
4141
deps = ["CEnum", "LLVMExtra_jll", "Libdl", "Printf", "Unicode"]
42-
git-tree-sha1 = "5007c1421563108110bbd57f63d8ad4565808818"
42+
git-tree-sha1 = "ce502fbe565c66e60c2279114c442ddab31fa56b"
4343
uuid = "929cbde3-209d-540e-8aea-75f648917ca0"
44-
version = "5.2.0"
44+
version = "6.0.0"
4545

4646
[[LLVMExtra_jll]]
4747
deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"]

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
1515

1616
[compat]
1717
ExprTools = "0.1"
18-
LLVM = "5"
18+
LLVM = "6"
1919
Scratch = "1"
2020
TimerOutputs = "0.5"
2121
julia = "1.6"

examples/kernel.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ function main()
2222
config = CompilerConfig(target, params)
2323
job = CompilerJob(source, config)
2424

25-
println(GPUCompiler.compile(:asm, job)[1])
25+
output = JuliaContext() do ctx
26+
GPUCompiler.compile(:asm, job)
27+
end
28+
29+
println(output[1])
2630
end
2731

2832
isinteractive() || main()

src/driver.jl

Lines changed: 69 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,13 @@ export JuliaContext
1919
# unique context on all other versions. Once we only support Julia 1.9, we'll deprecate
2020
# this helper to a regular `Context()` call.
2121
function JuliaContext()
22-
if VERSION >= v"1.9.0-DEV.115"
22+
if VERSION >= v"1.9.0-DEV.516"
23+
# Julia 1.9 knows how to deal with arbitrary contexts,
24+
# and uses ORC's thread safe versions.
25+
ThreadSafeContext()
26+
elseif VERSION >= v"1.9.0-DEV.115"
2327
# Julia 1.9 knows how to deal with arbitrary contexts
24-
JuliaContextType()
28+
Context()
2529
else
2630
# earlier versions of Julia claim so, but actually use a global context
2731
isboxed_ref = Ref{Bool}()
@@ -31,19 +35,34 @@ function JuliaContext()
3135
end
3236
end
3337
function JuliaContext(f)
34-
if VERSION >= v"1.9.0-DEV.115"
35-
JuliaContextType(f)
38+
if VERSION >= v"1.9.0-DEV.516"
39+
ts_ctx = ThreadSafeContext()
40+
# for now, also activate the underlying context
41+
# XXX: this is wrong; we can't expose the underlying LLVM context, but should
42+
# instead always go through the callback in order to unlock it properly.
43+
# rework this once we depend on Julia 1.9 or later.
44+
ctx = context(ts_ctx)
45+
activate(ctx)
46+
try
47+
f(ctx)
48+
finally
49+
deactivate(ctx)
50+
dispose(ts_ctx)
51+
end
52+
elseif VERSION >= v"1.9.0-DEV.115"
53+
Context(f)
3654
else
37-
f(JuliaContext())
38-
# we cannot dispose of the global unique context
55+
ctx = JuliaContext()
56+
activate(ctx)
57+
try
58+
f(ctx)
59+
finally
60+
deactivate(ctx)
61+
# we cannot dispose of the global unique context
62+
end
3963
end
4064
end
4165

42-
if VERSION >= v"1.9.0-DEV.516"
43-
unwrap_context(ctx::ThreadSafeContext) = context(ctx)
44-
end
45-
unwrap_context(ctx::Context) = ctx
46-
4766

4867
## compiler entrypoint
4968

@@ -79,76 +98,62 @@ Other keyword arguments can be found in the documentation of [`cufunction`](@ref
7998
function compile(target::Symbol, @nospecialize(job::CompilerJob);
8099
libraries::Bool=true, toplevel::Bool=true,
81100
optimize::Bool=true, cleanup::Bool=true, strip::Bool=false,
82-
validate::Bool=true, only_entry::Bool=false,
83-
ctx::Union{JuliaContextType,Nothing}=nothing)
101+
validate::Bool=true, only_entry::Bool=false)
84102
if compile_hook[] !== nothing
85103
compile_hook[](job)
86104
end
87105

88106
return codegen(target, job;
89-
libraries, toplevel, optimize, cleanup, strip, validate, only_entry, ctx)
107+
libraries, toplevel, optimize, cleanup, strip, validate, only_entry)
90108
end
91109

92110
function codegen(output::Symbol, @nospecialize(job::CompilerJob);
93111
libraries::Bool=true, toplevel::Bool=true, optimize::Bool=true,
94112
cleanup::Bool=true, strip::Bool=false, validate::Bool=true,
95-
only_entry::Bool=false, parent_job::Union{Nothing, CompilerJob}=nothing,
96-
ctx::Union{JuliaContextType,Nothing}=nothing)
113+
only_entry::Bool=false, parent_job::Union{Nothing, CompilerJob}=nothing)
114+
if context(; throw_error=false) === nothing
115+
error("No active LLVM context. Use `JuliaContext()` do-block syntax to create one.")
116+
elseif VERSION < v"1.9.0-DEV.115" && context() != JuliaContext()
117+
error("""Julia <1.9 does not suppport generating code in an arbitrary LLVM context.
118+
Use `JuliaContext()` do-block syntax to get an appropriate one.""")
119+
end
120+
97121
@timeit_debug to "Validation" begin
98122
check_method(job) # not optional
99123
validate && check_invocation(job)
100124
end
101125

102-
temporary_context = ctx === nothing
103-
if temporary_context && output == :llvm
104-
# if we return IR structures, we cannot construct a temporary context
105-
error("Request to return LLVM IR; please provide a context")
106-
end
107-
108-
try
109-
## LLVM IR
110126

111-
if temporary_context
112-
ctx = JuliaContext()
113-
elseif VERSION < v"1.9.0-DEV.115" && ctx != JuliaContext()
114-
error("""Julia <1.9 does not suppport generating code in an arbitrary LLVM context.
115-
Use a JuliaContext instead.""")
116-
end
127+
## LLVM IR
117128

118-
ir, ir_meta = emit_llvm(job; libraries, toplevel, optimize, cleanup, only_entry, validate, ctx)
119-
120-
if output == :llvm
121-
if strip
122-
@timeit_debug to "strip debug info" strip_debuginfo!(ir)
123-
end
129+
ir, ir_meta = emit_llvm(job; libraries, toplevel, optimize, cleanup, only_entry, validate)
124130

125-
return ir, ir_meta
131+
if output == :llvm
132+
if strip
133+
@timeit_debug to "strip debug info" strip_debuginfo!(ir)
126134
end
127135

136+
return ir, ir_meta
137+
end
128138

129-
## machine code
130139

131-
format = if output == :asm
132-
LLVM.API.LLVMAssemblyFile
133-
elseif output == :obj
134-
LLVM.API.LLVMObjectFile
135-
else
136-
error("Unknown assembly format $output")
137-
end
138-
asm, asm_meta = emit_asm(job, ir; strip, validate, format)
139-
140-
if output == :asm || output == :obj
141-
return asm, (; asm_meta..., ir_meta..., ir)
142-
end
140+
## machine code
143141

142+
format = if output == :asm
143+
LLVM.API.LLVMAssemblyFile
144+
elseif output == :obj
145+
LLVM.API.LLVMObjectFile
146+
else
147+
error("Unknown assembly format $output")
148+
end
149+
asm, asm_meta = emit_asm(job, ir; strip, validate, format)
144150

145-
error("Unknown compilation output $output")
146-
finally
147-
if temporary_context && VERSION >= v"1.9.0-DEV.115"
148-
@assert ctx != JuliaContext()
149-
dispose(ctx)
150-
end
151+
if output == :asm || output == :obj
152+
return asm, (; asm_meta..., ir_meta..., ir)
151153
end
154+
155+
156+
error("Unknown compilation output $output")
152157
end
153158

154159
# primitive mechanism for deferred compilation, for implementing CUDA dynamic parallelism.
@@ -183,8 +188,7 @@ const __llvm_initialized = Ref(false)
183188

184189
@locked function emit_llvm(@nospecialize(job::CompilerJob);
185190
libraries::Bool=true, toplevel::Bool=true, optimize::Bool=true,
186-
cleanup::Bool=true, only_entry::Bool=false, validate::Bool=true,
187-
ctx::JuliaContextType)
191+
cleanup::Bool=true, only_entry::Bool=false, validate::Bool=true)
188192
if !__llvm_initialized[]
189193
InitializeAllTargets()
190194
InitializeAllTargetInfos()
@@ -195,7 +199,7 @@ const __llvm_initialized = Ref(false)
195199
end
196200

197201
@timeit_debug to "IR generation" begin
198-
ir, compiled = irgen(job; ctx)
202+
ir, compiled = irgen(job)
199203
if job.config.entry_abi === :specfunc
200204
entry_fn = compiled[job.source].specfunc
201205
else
@@ -251,20 +255,20 @@ const __llvm_initialized = Ref(false)
251255
dyn_ir, dyn_meta = codegen(:llvm, dyn_job; validate=false,
252256
optimize=false,
253257
toplevel=false,
254-
parent_job=job, ctx)
258+
parent_job=job)
255259
dyn_entry_fn = LLVM.name(dyn_meta.entry)
256260
merge!(compiled, dyn_meta.compiled)
257-
@assert context(dyn_ir) == unwrap_context(ctx)
261+
@assert context(dyn_ir) == context(ir)
258262
link!(ir, dyn_ir)
259263
changed = true
260264
dyn_entry_fn
261265
end
262266
dyn_entry = functions(ir)[dyn_entry_fn]
263267

264268
# insert a pointer to the function everywhere the entry is used
265-
T_ptr = convert(LLVMType, Ptr{Cvoid}; ctx=unwrap_context(ctx))
269+
T_ptr = convert(LLVMType, Ptr{Cvoid})
266270
for call in worklist[dyn_job]
267-
@dispose builder=IRBuilder(unwrap_context(ctx)) begin
271+
@dispose builder=IRBuilder() begin
268272
position!(builder, call)
269273
fptr = ptrtoint!(builder, dyn_entry, T_ptr)
270274
replace_uses!(call, fptr)
@@ -283,7 +287,7 @@ const __llvm_initialized = Ref(false)
283287
# always preload the runtime, and do so early; it cannot be part of any
284288
# timing block because it recurses into the compiler
285289
if !uses_julia_runtime(job) && libraries
286-
runtime = load_runtime(job; ctx)
290+
runtime = load_runtime(job)
287291
runtime_fns = LLVM.name.(defs(runtime))
288292
runtime_intrinsics = ["julia.gc_alloc_obj"]
289293
end
@@ -323,7 +327,7 @@ const __llvm_initialized = Ref(false)
323327

324328
# mark the kernel entry-point functions (optimization may need it)
325329
if job.config.kernel
326-
push!(metadata(ir)["julia.kernel"], MDNode([entry]; ctx=unwrap_context(ctx)))
330+
push!(metadata(ir)["julia.kernel"], MDNode([entry]))
327331

328332
# IDEA: save all jobs, not only kernels, and save other attributes
329333
# so that we can reconstruct the CompileJob instead of setting it globally

src/gcn.jl

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ end
9595

9696
function lower_throw_extra!(mod::LLVM.Module)
9797
job = current_job::CompilerJob
98-
ctx = context(mod)
9998
changed = false
10099
@timeit_debug to "lower throw (extra)" begin
101100

@@ -115,7 +114,7 @@ function lower_throw_extra!(mod::LLVM.Module)
115114
call = user(use)::LLVM.CallInst
116115

117116
# replace the throw with a trap
118-
@dispose builder=IRBuilder(ctx) begin
117+
@dispose builder=IRBuilder() begin
119118
position!(builder, call)
120119
emit_exception!(builder, f_name, call)
121120
end
@@ -154,7 +153,6 @@ end
154153
function fix_alloca_addrspace!(fn::LLVM.Function)
155154
changed = false
156155
alloca_as = 5
157-
ctx = context(fn)
158156

159157
for bb in blocks(fn)
160158
for insn in instructions(bb)
@@ -164,7 +162,7 @@ function fix_alloca_addrspace!(fn::LLVM.Function)
164162
addrspace(ty) == alloca_as && continue
165163

166164
new_insn = nothing
167-
@dispose builder=IRBuilder(ctx) begin
165+
@dispose builder=IRBuilder() begin
168166
position!(builder, insn)
169167
_alloca = alloca!(builder, ety, name(insn))
170168
new_insn = addrspacecast!(builder, _alloca, ty)
@@ -179,16 +177,15 @@ function fix_alloca_addrspace!(fn::LLVM.Function)
179177
end
180178

181179
function emit_trap!(job::CompilerJob{GCNCompilerTarget}, builder, mod, inst)
182-
ctx = context(mod)
183-
trap_ft = LLVM.FunctionType(LLVM.VoidType(ctx))
180+
trap_ft = LLVM.FunctionType(LLVM.VoidType())
184181
trap = if haskey(functions(mod), "llvm.trap")
185182
functions(mod)["llvm.trap"]
186183
else
187184
LLVM.Function(mod, "llvm.trap", trap_ft)
188185
end
189186
if Base.libllvm_version < v"9"
190-
rl_ft = LLVM.FunctionType(LLVM.Int32Type(ctx),
191-
[LLVM.Int32Type(ctx)])
187+
rl_ft = LLVM.FunctionType(LLVM.Int32Type(),
188+
[LLVM.Int32Type()])
192189
rl = if haskey(functions(mod), "llvm.amdgcn.readfirstlane")
193190
functions(mod)["llvm.amdgcn.readfirstlane"]
194191
else
@@ -201,8 +198,8 @@ function emit_trap!(job::CompilerJob{GCNCompilerTarget}, builder, mod, inst)
201198
# this, the target will only attempt to do a "masked branch", which
202199
# only works on vector instructions (trap is a scalar instruction, and
203200
# therefore it is executed even when EXEC==0).
204-
rl_val = call!(builder, rl_ft, rl, [ConstantInt(Int32(32); ctx)])
205-
rl_bc = inttoptr!(builder, rl_val, LLVM.PointerType(LLVM.Int32Type(ctx)))
201+
rl_val = call!(builder, rl_ft, rl, [ConstantInt(Int32(32))])
202+
rl_bc = inttoptr!(builder, rl_val, LLVM.PointerType(LLVM.Int32Type()))
206203
store!(builder, rl_val, rl_bc)
207204
end
208205
call!(builder, trap_ft, trap)

src/interface.jl

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -158,15 +158,6 @@ function Base.hash(job::CompilerJob, h::UInt)
158158
end
159159

160160

161-
## contexts
162-
163-
if VERSION >= v"1.9.0-DEV.516"
164-
const JuliaContextType = ThreadSafeContext
165-
else
166-
const JuliaContextType = Context
167-
end
168-
169-
170161
## default definitions that can be overridden to influence GPUCompiler's behavior
171162

172163
# Has the runtime available and does not require special handling

0 commit comments

Comments
 (0)