Skip to content

Commit ae520af

Browse files
authored
Updates for Julia 1.12 (#656)
1 parent b692685 commit ae520af

File tree

6 files changed

+93
-62
lines changed

6 files changed

+93
-62
lines changed

src/jlgen.jl

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -480,8 +480,32 @@ end # HAS_INTEGRATED_CACHE
480480
## codegen/inference integration
481481

482482
function ci_cache_populate(interp, cache, mi, min_world, max_world)
483-
if VERSION >= v"1.12.0-DEV.15"
484-
inferred_ci = CC.typeinf_ext_toplevel(interp, mi, CC.SOURCE_MODE_FORCE_SOURCE) # or SOURCE_MODE_FORCE_SOURCE_UNCACHED?
483+
codeinfos = Pair{CodeInstance, CodeInfo}[]
484+
@static if VERSION >= v"1.12.0-DEV.1434"
485+
# see typeinfer.jl: typeinf_ext_toplevel
486+
ci = CC.typeinf_ext(interp, mi, CC.SOURCE_MODE_NOT_REQUIRED)
487+
inspected = IdSet{CodeInstance}()
488+
tocompile = CodeInstance[ci]
489+
while !isempty(tocompile)
490+
callee = pop!(tocompile)
491+
callee in inspected && continue
492+
push!(inspected, callee)
493+
# now make sure everything has source code, if desired
494+
mi = CC.get_ci_mi(callee)
495+
def = mi.def
496+
if CC.use_const_api(callee)
497+
src = CC.codeinfo_for_const(interp, mi, ci.rettype_const)
498+
else
499+
# TODO: typeinf_code could return something with different edges/ages/owner/abi (needing an update to callee), which we don't handle here
500+
src = CC.typeinf_code(interp, mi, true)
501+
end
502+
if src isa CodeInfo
503+
CC.collectinvokes!(tocompile, src)
504+
push!(codeinfos, callee => src)
505+
end
506+
end
507+
elseif VERSION >= v"1.12.0-DEV.15"
508+
inferred_ci = CC.typeinf_ext_toplevel(interp, mi, CC.SOURCE_MODE_FORCE_SOURCE)
485509
@assert inferred_ci !== nothing "Inference of $mi failed"
486510

487511
# inference should have populated our cache
@@ -512,13 +536,13 @@ function ci_cache_populate(interp, cache, mi, min_world, max_world)
512536
end
513537
end
514538

515-
return ci::CodeInstance
539+
return codeinfos
516540
end
517541

518542
function ci_cache_lookup(cache, mi, min_world, max_world)
519543
wvc = WorldView(cache, min_world, max_world)
520544
ci = CC.get(wvc, mi, nothing)
521-
if ci !== nothing && ci.inferred === nothing
545+
if VERSION < v"1.12.0-DEV.1434" && ci !== nothing && ci.inferred === nothing
522546
# if for some reason we did end up with a codeinfo without inferred source, e.g.,
523547
# because of calling `Base.return_types` which only sets rettyp, pretend we didn't
524548
# run inference so that we re-infer now and not during codegen (which is disallowed)
@@ -543,23 +567,6 @@ end
543567
CompilationPolicyExtern = 1
544568
end
545569

546-
# HACK: in older versions of Julia, `jl_create_native` doesn't take a world argument
547-
# but instead always generates code for the current world. note that this doesn't
548-
# actually change the world age, but just spoofs the counter `jl_create_native` reads.
549-
# XXX: Base.get_world_counter is supposed to be monotonically increasing and is runtime global.
550-
macro in_world(world, ex)
551-
quote
552-
actual_world = Base.get_world_counter()
553-
world_counter = cglobal(:jl_world_counter, Csize_t)
554-
unsafe_store!(world_counter, $(esc(world)))
555-
try
556-
$(esc(ex))
557-
finally
558-
unsafe_store!(world_counter, actual_world)
559-
end
560-
end
561-
end
562-
563570
"""
564571
precompile(job::CompilerJob)
565572
@@ -574,10 +581,7 @@ function Base.precompile(@nospecialize(job::CompilerJob))
574581
# populate the cache
575582
interp = get_interpreter(job)
576583
cache = CC.code_cache(interp)
577-
if ci_cache_lookup(cache, job.source, job.world, job.world) === nothing
578-
ci_cache_populate(interp, cache, job.source, job.world, job.world)
579-
return ci_cache_lookup(cache, job.source, job.world, job.world) !== nothing
580-
end
584+
ci_cache_populate(interp, cache, job.source, job.world, job.world)
581585
return true
582586
end
583587

@@ -589,10 +593,7 @@ function compile_method_instance(@nospecialize(job::CompilerJob))
589593
# populate the cache
590594
interp = get_interpreter(job)
591595
cache = CC.code_cache(interp)
592-
if ci_cache_lookup(cache, job.source, job.world, job.world) === nothing
593-
ci_cache_populate(interp, cache, job.source, job.world, job.world)
594-
@assert ci_cache_lookup(cache, job.source, job.world, job.world) !== nothing
595-
end
596+
populated = ci_cache_populate(interp, cache, job.source, job.world, job.world)
596597

597598
# create a callback to look-up function in our cache,
598599
# and keep track of the method instances we needed.
@@ -639,7 +640,16 @@ function compile_method_instance(@nospecialize(job::CompilerJob))
639640
Metadata(ConstantInt(DEBUG_METADATA_VERSION()))
640641
end
641642

642-
native_code = if VERSION >= v"1.12.0-DEV.1667"
643+
native_code = if VERSION >= v"1.12.0-DEV.1823"
644+
codeinfos = Any[]
645+
for (ci, src) in populated
646+
# each item in the list should be a CodeInstance followed by a CodeInfo
647+
# indicating something to compile
648+
push!(codeinfos, ci::CodeInstance)
649+
push!(codeinfos, src::CodeInfo)
650+
end
651+
@ccall jl_emit_native(codeinfos::Vector{Any}, ts_mod::LLVM.API.LLVMOrcThreadSafeModuleRef, Ref(params)::Ptr{Base.CodegenParams}, #=extern linkage=# false::Cint)::Ptr{Cvoid}
652+
elseif VERSION >= v"1.12.0-DEV.1667"
643653
ccall(:jl_create_native, Ptr{Cvoid},
644654
(Vector{MethodInstance}, LLVM.API.LLVMOrcThreadSafeModuleRef, Ptr{Base.CodegenParams}, Cint, Cint, Cint, Csize_t, Ptr{Cvoid}),
645655
[job.source], ts_mod, Ref(params), CompilationPolicyExtern, #=imaging mode=# 0, #=external linkage=# 0, job.world, Base.unsafe_convert(Ptr{Nothing}, lookup_cb))

src/validation.jl

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,9 +250,30 @@ function check_ir!(job, errors::Vector{IRError}, inst::LLVM.CallInst)
250250
@safe_debug "Decoding arguments to jl_reresolve_binding_value_seqcst failed" inst bb=LLVM.parent(inst)
251251
push!(errors, (DELAYED_BINDING, bt, nothing))
252252
end
253+
elseif startswith(fn, "tojlinvoke")
254+
try
255+
fun, args, nargs = arguments(inst)
256+
fun = first(operands(fun::ConstantExpr))::ConstantInt
257+
fun = convert(Int, fun)
258+
fun = Ptr{Cvoid}(fun)
259+
fun = Base.unsafe_pointer_to_objref(fun)::Base.Function
260+
push!(errors, (DYNAMIC_CALL, bt, fun))
261+
# XXX: an invoke trampoline happens when codegen doesn't have access to code
262+
# which suggests a GPUCompiler.jl bug. throw an error instead?
263+
catch e
264+
@safe_debug "Decoding arguments to jl_invoke failed" inst bb = LLVM.parent(inst)
265+
push!(errors, (DYNAMIC_CALL, bt, nothing))
266+
end
253267
elseif fn == "jl_invoke" || fn == "ijl_invoke"
268+
# most invokes are contained in a trampoline handled above,
269+
# but some direct ones remain (e.g., with `@nospecialize`)
270+
# XXX: this shouldn't be true on 1.12+ anymore; jl_invoke is always trampolined
271+
caller = LLVM.parent(LLVM.parent(inst))
272+
if startswith(LLVM.name(caller), "tojlinvoke")
273+
return
274+
end
254275
try
255-
f, args, nargs, meth = arguments(inst)
276+
fun, args, nargs, meth = arguments(inst)
256277
meth = first(operands(meth::ConstantExpr))::ConstantInt
257278
meth = convert(Int, meth)
258279
meth = Ptr{Cvoid}(meth)

test/gcn_tests.jl

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ end
5353
end
5454

5555
asm = sprint(io->GCN.code_native(io, parent, Tuple{Int64}; dump_module=true))
56-
@test occursin(r"s_add_u32.*julia_child_.*@rel32@", asm)
57-
@test occursin(r"s_addc_u32.*julia_child_.*@rel32@", asm)
56+
@test occursin(r"s_add_u32.*(julia|j)_child_.*@rel32@", asm)
57+
@test occursin(r"s_addc_u32.*(julia|j)_child_.*@rel32@", asm)
5858
end
5959

6060
@testset "kernel functions" begin
@@ -89,10 +89,10 @@ end
8989
end
9090

9191
asm = sprint(io->GCN.code_native(io, mod.parent1, Tuple{Int}; dump_module=true))
92-
@test occursin(r"\.type.*julia_[[:alnum:]_.]*child_\d*,@function", asm)
92+
@test occursin(r"\.type.*(julia|j)_[[:alnum:]_.]*child_\d*,@function", asm)
9393

9494
asm = sprint(io->GCN.code_native(io, mod.parent2, Tuple{Int}; dump_module=true))
95-
@test occursin(r"\.type.*julia_[[:alnum:]_.]*child_\d*,@function", asm)
95+
@test occursin(r"\.type.*(julia|j)_[[:alnum:]_.]*child_\d*,@function", asm)
9696
end
9797

9898
@testset "child function reuse bis" begin
@@ -115,12 +115,12 @@ end
115115
end
116116

117117
asm = sprint(io->GCN.code_native(io, mod.parent1, Tuple{Int}; dump_module=true))
118-
@test occursin(r"\.type.*julia_[[:alnum:]_.]*child1_\d*,@function", asm)
119-
@test occursin(r"\.type.*julia_[[:alnum:]_.]*child2_\d*,@function", asm)
118+
@test occursin(r"\.type.*(julia|j)_[[:alnum:]_.]*child1_\d*,@function", asm)
119+
@test occursin(r"\.type.*(julia|j)_[[:alnum:]_.]*child2_\d*,@function", asm)
120120

121121
asm = sprint(io->GCN.code_native(io, mod.parent2, Tuple{Int}; dump_module=true))
122-
@test occursin(r"\.type.*julia_[[:alnum:]_.]*child1_\d*,@function", asm)
123-
@test occursin(r"\.type.*julia_[[:alnum:]_.]*child2_\d*,@function", asm)
122+
@test occursin(r"\.type.*(julia|j)_[[:alnum:]_.]*child1_\d*,@function", asm)
123+
@test occursin(r"\.type.*(julia|j)_[[:alnum:]_.]*child2_\d*,@function", asm)
124124
end
125125

126126
@testset "indirect sysimg function use" begin

test/native_tests.jl

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ using Test
1616
@test contains(ir, "MethodInstance for identity")
1717

1818
ir = sprint(io->GPUCompiler.code_llvm(io, job))
19-
@test contains(ir, "julia_identity")
19+
@test contains(ir, r"(julia|j)_identity")
2020

2121
asm = sprint(io->GPUCompiler.code_native(io, job))
22-
@test contains(asm, "julia_identity")
22+
@test contains(asm, r"(julia|j)_identity")
2323
end
2424

2525
@testset "compilation" begin
@@ -187,7 +187,7 @@ end
187187
ir = sprint(io->Native.code_llvm(io, valid_kernel, Tuple{}; optimize=false, dump_module=true))
188188

189189
# module should contain our function + a generic call wrapper
190-
@test occursin(r"define\ .* void\ @.*julia_valid_kernel.*\(\)"x, ir)
190+
@test occursin(r"define\ .* void\ @.*(julia|j)_valid_kernel.*\(\)"x, ir)
191191
@test !occursin("define %jl_value_t* @jlcall_", ir)
192192

193193
# there should be no debug metadata
@@ -208,7 +208,7 @@ end
208208
parent(i) = child(i)
209209

210210
ir = sprint(io->Native.code_llvm(io, parent, Tuple{Int}))
211-
@test occursin(r"call .+ @julia.+child.+", ir)
211+
@test occursin(r"call .+ @(julia|j).+child.+", ir)
212212
end
213213

214214
@testset "sysimg" begin
@@ -295,18 +295,18 @@ end
295295
end
296296

297297
ir = sprint(io->Native.code_llvm(io, mod.g, Tuple{Int64}; dump_module=true, kernel=true))
298-
@test occursin(r"^define.*julia_f_expensive"m, ir)
298+
@test occursin(r"^define.*(julia|j)_f_expensive"m, ir)
299299

300300
ir = sprint(io->Native.code_llvm(io, mod.g, Tuple{Int64}; dump_module=true, kernel=true,
301301
always_inline=true))
302-
@test !occursin(r"^define.*julia_f_expensive"m, ir)
302+
@test !occursin(r"^define.*(julia|j)_f_expensive"m, ir)
303303

304304
ir = sprint(io->Native.code_llvm(io, mod.h, Tuple{Int64}; dump_module=true, kernel=true,
305305
always_inline=true))
306-
@test !occursin(r"^define.*julia_f_expensive"m, ir)
306+
@test !occursin(r"^define.*(julia|j)_f_expensive"m, ir)
307307

308308
ir = sprint(io->Native.code_llvm(io, mod.h, Tuple{Int64}; dump_module=true, kernel=true))
309-
@test occursin(r"^define.*julia_f_expensive"m, ir)
309+
@test occursin(r"^define.*(julia|j)_f_expensive"m, ir)
310310
end
311311

312312
@testset "function attributes" begin

test/ptx_tests.jl

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ end
2727
end
2828

2929
ir = sprint(io->PTX.code_llvm(io, mod.kernel, Tuple{mod.Aggregate}))
30-
@test occursin(r"@julia_kernel\w*\(({ i64 }|\[1 x i64\])\* ", ir) ||
31-
occursin(r"@julia_kernel\w*\(ptr ", ir)
30+
@test occursin(r"@(julia|j)_kernel\w*\(({ i64 }|\[1 x i64\])\* ", ir) ||
31+
occursin(r"@(julia|j)_kernel\w*\(ptr ", ir)
3232

3333
ir = sprint(io->PTX.code_llvm(io, mod.kernel, Tuple{mod.Aggregate}; kernel=true))
3434
@test occursin(r"@_Z6kernel9Aggregate\(.*({ i64 }|\[1 x i64\]) ", ir)
@@ -89,7 +89,7 @@ end
8989
end
9090

9191
ir = sprint(io->PTX.code_llvm(io, mod.kernel, Tuple{}))
92-
@test occursin(r"@julia_kernel\w*\(\)", ir)
92+
@test occursin(r"@(julia|j)_kernel\w*\(\)", ir)
9393

9494
ir = sprint(io->PTX.code_llvm(io, mod.kernel, Tuple{}; kernel=true))
9595
@test occursin("@_Z6kernel([1 x i64] %state)", ir)
@@ -117,10 +117,10 @@ end
117117
@test occursin(r"@_Z6kernelP5Int64\(\[1 x i64\] %state", ir)
118118

119119
# child1 doesn't use the state
120-
@test occursin(r"@julia_child1\w*\((i64|i8\*|ptr)", ir)
120+
@test occursin(r"@(julia|j)_child1\w*\((i64|i8\*|ptr)", ir)
121121

122122
# child2 does
123-
@test occursin(r"@julia_child2\w*\(\[1 x i64\] %state", ir)
123+
@test occursin(r"@(julia|j)_child2\w*\(\[1 x i64\] %state", ir)
124124

125125
# can't have the unlowered intrinsic
126126
@test !occursin("julia.gpu.state_getter", ir)
@@ -149,7 +149,7 @@ end
149149
end
150150

151151
asm = sprint(io->PTX.code_native(io, mod.parent, Tuple{Int64}))
152-
@test occursin(r"call.uni\s+julia_child_"m, asm)
152+
@test occursin(r"call.uni\s+(julia|j)_child_"m, asm)
153153
end
154154

155155
@testset "kernel functions" begin
@@ -167,8 +167,8 @@ end
167167
asm = sprint(io->PTX.code_native(io, mod.entry, Tuple{Int64};
168168
kernel=true, dump_module=true))
169169
@test occursin(".visible .entry _Z5entry5Int64", asm)
170-
@test !occursin(".visible .func julia_nonentry", asm)
171-
@test occursin(".func julia_nonentry", asm)
170+
@test !occursin(r"\.visible \.func (julia|j)_nonentry", asm)
171+
@test occursin(r"\.func (julia|j)_nonentry", asm)
172172

173173
@testset "property_annotations" begin
174174
asm = sprint(io->PTX.code_native(io, mod.entry, Tuple{Int64}; kernel=true))
@@ -214,10 +214,10 @@ end
214214
end
215215

216216
asm = sprint(io->PTX.code_native(io, mod.parent1, Tuple{Int}))
217-
@test occursin(".func julia_child_", asm)
217+
@test occursin(r"\.func (julia|j)_child_", asm)
218218

219219
asm = sprint(io->PTX.code_native(io, mod.parent2, Tuple{Int}))
220-
@test occursin(".func julia_child_", asm)
220+
@test occursin(r"\.func (julia|j)_child_", asm)
221221
end
222222

223223
@testset "child function reuse bis" begin
@@ -241,12 +241,12 @@ end
241241
end
242242

243243
asm = sprint(io->PTX.code_native(io, mod.parent1, Tuple{Int}))
244-
@test occursin(".func julia_child1_", asm)
245-
@test occursin(".func julia_child2_", asm)
244+
@test occursin(r"\.func (julia|j)_child1_", asm)
245+
@test occursin(r"\.func (julia|j)_child2_", asm)
246246

247247
asm = sprint(io->PTX.code_native(io, mod.parent2, Tuple{Int}))
248-
@test occursin(".func julia_child1_", asm)
249-
@test occursin(".func julia_child2_", asm)
248+
@test occursin(r"\.func (julia|j)_child1_", asm)
249+
@test occursin(r"\.func (julia|j)_child2_", asm)
250250
end
251251

252252
@testset "indirect sysimg function use" begin

test/spirv_tests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ end
8989
end
9090

9191
asm = sprint(io->SPIRV.code_native(io, kernel, Tuple{Bool}; kernel=true))
92-
@test occursin(r"OpFunctionCall %void %julia_error", asm)
92+
@test occursin(r"OpFunctionCall %void %(julia|j)_error", asm)
9393
end
9494

9595
end

0 commit comments

Comments
 (0)