From 8109be1ee5d42430d4c017e8505c3bbe7df17fab Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Fri, 12 Apr 2024 16:18:16 -0400 Subject: [PATCH 01/16] Add a testsuite for inference caching --- test/Native/Project.toml | 6 +++ test/Native/src/Native.jl | 5 ++ test/Native/src/compiler.jl | 69 ++++++++++++++++++++++++++ test/native_testsetup.jl | 73 +-------------------------- test/precompile_tests.jl | 99 +++++++++++++++++++++++++++++++++++++ test/runtests.jl | 5 ++ 6 files changed, 185 insertions(+), 72 deletions(-) create mode 100644 test/Native/Project.toml create mode 100644 test/Native/src/Native.jl create mode 100644 test/Native/src/compiler.jl create mode 100644 test/precompile_tests.jl diff --git a/test/Native/Project.toml b/test/Native/Project.toml new file mode 100644 index 00000000..70cffe42 --- /dev/null +++ b/test/Native/Project.toml @@ -0,0 +1,6 @@ +name = "Native" +uuid = "fdcda96a-3e7d-4dd7-839b-bda323ec0835" +version = "0.1.0" + +[deps] +GPUCompiler = "61eb1bfa-7361-4325-ad38-22787b887f55" diff --git a/test/Native/src/Native.jl b/test/Native/src/Native.jl new file mode 100644 index 00000000..deeba469 --- /dev/null +++ b/test/Native/src/Native.jl @@ -0,0 +1,5 @@ +module Native + +include("compiler.jl") + +end # module Native diff --git a/test/Native/src/compiler.jl b/test/Native/src/compiler.jl new file mode 100644 index 00000000..b3645765 --- /dev/null +++ b/test/Native/src/compiler.jl @@ -0,0 +1,69 @@ +using GPUCompiler + +# create a native test compiler, and generate reflection methods for it + +include("../../runtime.jl") + +# local method table for device functions +Base.Experimental.@MethodTable(test_method_table) + +struct CompilerParams <: AbstractCompilerParams + entry_safepoint::Bool + method_table + + CompilerParams(entry_safepoint::Bool=false, method_table=test_method_table) = + new(entry_safepoint, method_table) +end + +NativeCompilerJob = CompilerJob{NativeCompilerTarget,CompilerParams} +GPUCompiler.runtime_module(::NativeCompilerJob) = TestRuntime + +GPUCompiler.method_table(@nospecialize(job::NativeCompilerJob)) = job.config.params.method_table +GPUCompiler.can_safepoint(@nospecialize(job::NativeCompilerJob)) = job.config.params.entry_safepoint + +function create_job(@nospecialize(func), @nospecialize(types); kernel::Bool=false, + entry_abi=:specfunc, entry_safepoint::Bool=false, always_inline=false, + method_table=test_method_table, kwargs...) + source = methodinstance(typeof(func), Base.to_tuple_type(types), Base.get_world_counter()) + target = NativeCompilerTarget() + params = CompilerParams(entry_safepoint, method_table) + config = CompilerConfig(target, params; kernel, entry_abi, always_inline) + CompilerJob(source, config), kwargs +end + +function code_typed(@nospecialize(func), @nospecialize(types); kwargs...) + job, kwargs = create_job(func, types; kwargs...) + GPUCompiler.code_typed(job; kwargs...) +end + +function code_warntype(io::IO, @nospecialize(func), @nospecialize(types); kwargs...) + job, kwargs = create_job(func, types; kwargs...) + GPUCompiler.code_warntype(io, job; kwargs...) +end + +function code_llvm(io::IO, @nospecialize(func), @nospecialize(types); kwargs...) + job, kwargs = create_job(func, types; kwargs...) + GPUCompiler.code_llvm(io, job; kwargs...) +end + +function code_native(io::IO, @nospecialize(func), @nospecialize(types); kwargs...) + job, kwargs = create_job(func, types; kwargs...) + GPUCompiler.code_native(io, job; kwargs...) +end + +# aliases without ::IO argument +for method in (:code_warntype, :code_llvm, :code_native) + method = Symbol("$(method)") + @eval begin + $method(@nospecialize(func), @nospecialize(types); kwargs...) = + $method(stdout, func, types; kwargs...) + end +end + +# simulates codegen for a kernel function: validates by default +function code_execution(@nospecialize(func), @nospecialize(types); kwargs...) + job, kwargs = create_job(func, types; kernel=true, kwargs...) + JuliaContext() do ctx + GPUCompiler.compile(:asm, job; kwargs...) + end +end \ No newline at end of file diff --git a/test/native_testsetup.jl b/test/native_testsetup.jl index 973b300d..d82c8ccf 100644 --- a/test/native_testsetup.jl +++ b/test/native_testsetup.jl @@ -1,74 +1,3 @@ @testsetup module Native - -using GPUCompiler - - -# create a native test compiler, and generate reflection methods for it - -include("runtime.jl") - -# local method table for device functions -Base.Experimental.@MethodTable(test_method_table) - -struct CompilerParams <: AbstractCompilerParams - entry_safepoint::Bool - method_table - - CompilerParams(entry_safepoint::Bool=false, method_table=test_method_table) = - new(entry_safepoint, method_table) -end - -NativeCompilerJob = CompilerJob{NativeCompilerTarget,CompilerParams} -GPUCompiler.runtime_module(::NativeCompilerJob) = TestRuntime - -GPUCompiler.method_table(@nospecialize(job::NativeCompilerJob)) = job.config.params.method_table -GPUCompiler.can_safepoint(@nospecialize(job::NativeCompilerJob)) = job.config.params.entry_safepoint - -function create_job(@nospecialize(func), @nospecialize(types); kernel::Bool=false, - entry_abi=:specfunc, entry_safepoint::Bool=false, always_inline=false, - method_table=test_method_table, kwargs...) - source = methodinstance(typeof(func), Base.to_tuple_type(types), Base.get_world_counter()) - target = NativeCompilerTarget() - params = CompilerParams(entry_safepoint, method_table) - config = CompilerConfig(target, params; kernel, entry_abi, always_inline) - CompilerJob(source, config), kwargs -end - -function code_typed(@nospecialize(func), @nospecialize(types); kwargs...) - job, kwargs = create_job(func, types; kwargs...) - GPUCompiler.code_typed(job; kwargs...) -end - -function code_warntype(io::IO, @nospecialize(func), @nospecialize(types); kwargs...) - job, kwargs = create_job(func, types; kwargs...) - GPUCompiler.code_warntype(io, job; kwargs...) -end - -function code_llvm(io::IO, @nospecialize(func), @nospecialize(types); kwargs...) - job, kwargs = create_job(func, types; kwargs...) - GPUCompiler.code_llvm(io, job; kwargs...) -end - -function code_native(io::IO, @nospecialize(func), @nospecialize(types); kwargs...) - job, kwargs = create_job(func, types; kwargs...) - GPUCompiler.code_native(io, job; kwargs...) -end - -# aliases without ::IO argument -for method in (:code_warntype, :code_llvm, :code_native) - method = Symbol("$(method)") - @eval begin - $method(@nospecialize(func), @nospecialize(types); kwargs...) = - $method(stdout, func, types; kwargs...) - end -end - -# simulates codegen for a kernel function: validates by default -function code_execution(@nospecialize(func), @nospecialize(types); kwargs...) - job, kwargs = create_job(func, types; kernel=true, kwargs...) - JuliaContext() do ctx - GPUCompiler.compile(:asm, job; kwargs...) - end -end - + include("Native/src/compiler.jl") end diff --git a/test/precompile_tests.jl b/test/precompile_tests.jl new file mode 100644 index 00000000..4af777df --- /dev/null +++ b/test/precompile_tests.jl @@ -0,0 +1,99 @@ +@testitem "Precompile" begin + +using GPUCompiler +pushfirst!(LOAD_PATH, joinpath(@__DIR__, "Native")) + +import Native + +function precompile_test_harness(@nospecialize(f), testset::String) + @testset "$testset" begin + precompile_test_harness(f, true) + end +end +function precompile_test_harness(@nospecialize(f), separate::Bool) + load_path = mktempdir() + load_cache_path = separate ? mktempdir() : load_path + try + pushfirst!(LOAD_PATH, load_path) + pushfirst!(DEPOT_PATH, load_cache_path) + f(load_path) + finally + try + rm(load_path, force=true, recursive=true) + catch err + @show err + end + if separate + try + rm(load_cache_path, force=true, recursive=true) + catch err + @show err + end + end + filter!((≠)(load_path), LOAD_PATH) + separate && filter!((≠)(load_cache_path), DEPOT_PATH) + end + nothing +end + +function check_presence(mi, token) + found = false + ci = isdefined(mi, :cache) ? mi.cache : nothing + while ci !== nothing + if ci.owner === token && ci.max_world == typemax(UInt) + found = true + break + end + ci = isdefined(ci, :next) ? ci.next : nothing + end + return found +end + +precompile_test_harness("Inference caching") do load_path + write(joinpath(load_path, "InferenceCaching.jl"), :(module InferenceCaching + import Native + import GPUCompiler + + function kernel() + return + end + + let + job, _ = Native.create_job(kernel, ()) + GPUCompiler.code_typed(job) + end + + # identity is foreign + # Maybe https://github.com/JuliaLang/julia/pull/49391 + job, _ = Native.create_job(identity, (Int,)) + GPUCompiler.code_typed(job) + end) |> string) + + Base.compilecache(Base.PkgId("InferenceCaching")) + @eval let + # Check that no cached entry is present + identity_mi = GPUCompiler.methodinstance(typeof(identity), Tuple{Int}) + + token = let + job, _ = Native.create_job(identity, (Int,)) + GPUCompiler.ci_cache_token(job) + end + ci = isdefined(identity_mi, :cache) ? identity_mi.cache : nothing + while ci !== nothing + @test ci.owner === nothing + @test ci.owner !== token + ci = isdefined(ci, :next) ? ci.next : nothing + end + + using InferenceCaching + + # Check that kernel survived + kernel_mi = GPUCompiler.methodinstance(typeof(InferenceCaching.kernel), Tuple{}) + @test check_presence(kernel_mi, token) + + # check that identity survived + @test_broken check_presence(identity_mi, token) + end +end + +end # testitem diff --git a/test/runtests.jl b/test/runtests.jl index 57b75fbc..199990e8 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -31,5 +31,10 @@ runtests(GPUCompiler; nworkers=min(Sys.CPU_THREADS,4), nworker_threads=1, # SPIRV needs it's tools to be available return false end + + if ti.name == "Precompile" && VERSION < v"1.11.0-" + return false + end + true end From 76505a0b6092ad18cf837eea8d3b00cba95c394e Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Fri, 12 Apr 2024 16:29:09 -0400 Subject: [PATCH 02/16] fixup! Add a testsuite for inference caching --- test/precompile_tests.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/precompile_tests.jl b/test/precompile_tests.jl index 4af777df..51a720af 100644 --- a/test/precompile_tests.jl +++ b/test/precompile_tests.jl @@ -1,6 +1,7 @@ @testitem "Precompile" begin using GPUCompiler +pushfirst!(LOAD_PATH, joinpath(@__DIR__, "..")) pushfirst!(LOAD_PATH, joinpath(@__DIR__, "Native")) import Native From ef449c4a704898c6baf4a8c0e1e6da986d0b373d Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Fri, 12 Apr 2024 16:51:44 -0400 Subject: [PATCH 03/16] write package out to disk --- test/Native/Project.toml | 6 --- test/Native/src/Native.jl | 5 --- test/Native/src/compiler.jl | 69 ----------------------------------- test/native_testsetup.jl | 73 ++++++++++++++++++++++++++++++++++++- test/precompile_tests.jl | 15 ++++++-- 5 files changed, 83 insertions(+), 85 deletions(-) delete mode 100644 test/Native/Project.toml delete mode 100644 test/Native/src/Native.jl delete mode 100644 test/Native/src/compiler.jl diff --git a/test/Native/Project.toml b/test/Native/Project.toml deleted file mode 100644 index 70cffe42..00000000 --- a/test/Native/Project.toml +++ /dev/null @@ -1,6 +0,0 @@ -name = "Native" -uuid = "fdcda96a-3e7d-4dd7-839b-bda323ec0835" -version = "0.1.0" - -[deps] -GPUCompiler = "61eb1bfa-7361-4325-ad38-22787b887f55" diff --git a/test/Native/src/Native.jl b/test/Native/src/Native.jl deleted file mode 100644 index deeba469..00000000 --- a/test/Native/src/Native.jl +++ /dev/null @@ -1,5 +0,0 @@ -module Native - -include("compiler.jl") - -end # module Native diff --git a/test/Native/src/compiler.jl b/test/Native/src/compiler.jl deleted file mode 100644 index b3645765..00000000 --- a/test/Native/src/compiler.jl +++ /dev/null @@ -1,69 +0,0 @@ -using GPUCompiler - -# create a native test compiler, and generate reflection methods for it - -include("../../runtime.jl") - -# local method table for device functions -Base.Experimental.@MethodTable(test_method_table) - -struct CompilerParams <: AbstractCompilerParams - entry_safepoint::Bool - method_table - - CompilerParams(entry_safepoint::Bool=false, method_table=test_method_table) = - new(entry_safepoint, method_table) -end - -NativeCompilerJob = CompilerJob{NativeCompilerTarget,CompilerParams} -GPUCompiler.runtime_module(::NativeCompilerJob) = TestRuntime - -GPUCompiler.method_table(@nospecialize(job::NativeCompilerJob)) = job.config.params.method_table -GPUCompiler.can_safepoint(@nospecialize(job::NativeCompilerJob)) = job.config.params.entry_safepoint - -function create_job(@nospecialize(func), @nospecialize(types); kernel::Bool=false, - entry_abi=:specfunc, entry_safepoint::Bool=false, always_inline=false, - method_table=test_method_table, kwargs...) - source = methodinstance(typeof(func), Base.to_tuple_type(types), Base.get_world_counter()) - target = NativeCompilerTarget() - params = CompilerParams(entry_safepoint, method_table) - config = CompilerConfig(target, params; kernel, entry_abi, always_inline) - CompilerJob(source, config), kwargs -end - -function code_typed(@nospecialize(func), @nospecialize(types); kwargs...) - job, kwargs = create_job(func, types; kwargs...) - GPUCompiler.code_typed(job; kwargs...) -end - -function code_warntype(io::IO, @nospecialize(func), @nospecialize(types); kwargs...) - job, kwargs = create_job(func, types; kwargs...) - GPUCompiler.code_warntype(io, job; kwargs...) -end - -function code_llvm(io::IO, @nospecialize(func), @nospecialize(types); kwargs...) - job, kwargs = create_job(func, types; kwargs...) - GPUCompiler.code_llvm(io, job; kwargs...) -end - -function code_native(io::IO, @nospecialize(func), @nospecialize(types); kwargs...) - job, kwargs = create_job(func, types; kwargs...) - GPUCompiler.code_native(io, job; kwargs...) -end - -# aliases without ::IO argument -for method in (:code_warntype, :code_llvm, :code_native) - method = Symbol("$(method)") - @eval begin - $method(@nospecialize(func), @nospecialize(types); kwargs...) = - $method(stdout, func, types; kwargs...) - end -end - -# simulates codegen for a kernel function: validates by default -function code_execution(@nospecialize(func), @nospecialize(types); kwargs...) - job, kwargs = create_job(func, types; kernel=true, kwargs...) - JuliaContext() do ctx - GPUCompiler.compile(:asm, job; kwargs...) - end -end \ No newline at end of file diff --git a/test/native_testsetup.jl b/test/native_testsetup.jl index d82c8ccf..973b300d 100644 --- a/test/native_testsetup.jl +++ b/test/native_testsetup.jl @@ -1,3 +1,74 @@ @testsetup module Native - include("Native/src/compiler.jl") + +using GPUCompiler + + +# create a native test compiler, and generate reflection methods for it + +include("runtime.jl") + +# local method table for device functions +Base.Experimental.@MethodTable(test_method_table) + +struct CompilerParams <: AbstractCompilerParams + entry_safepoint::Bool + method_table + + CompilerParams(entry_safepoint::Bool=false, method_table=test_method_table) = + new(entry_safepoint, method_table) +end + +NativeCompilerJob = CompilerJob{NativeCompilerTarget,CompilerParams} +GPUCompiler.runtime_module(::NativeCompilerJob) = TestRuntime + +GPUCompiler.method_table(@nospecialize(job::NativeCompilerJob)) = job.config.params.method_table +GPUCompiler.can_safepoint(@nospecialize(job::NativeCompilerJob)) = job.config.params.entry_safepoint + +function create_job(@nospecialize(func), @nospecialize(types); kernel::Bool=false, + entry_abi=:specfunc, entry_safepoint::Bool=false, always_inline=false, + method_table=test_method_table, kwargs...) + source = methodinstance(typeof(func), Base.to_tuple_type(types), Base.get_world_counter()) + target = NativeCompilerTarget() + params = CompilerParams(entry_safepoint, method_table) + config = CompilerConfig(target, params; kernel, entry_abi, always_inline) + CompilerJob(source, config), kwargs +end + +function code_typed(@nospecialize(func), @nospecialize(types); kwargs...) + job, kwargs = create_job(func, types; kwargs...) + GPUCompiler.code_typed(job; kwargs...) +end + +function code_warntype(io::IO, @nospecialize(func), @nospecialize(types); kwargs...) + job, kwargs = create_job(func, types; kwargs...) + GPUCompiler.code_warntype(io, job; kwargs...) +end + +function code_llvm(io::IO, @nospecialize(func), @nospecialize(types); kwargs...) + job, kwargs = create_job(func, types; kwargs...) + GPUCompiler.code_llvm(io, job; kwargs...) +end + +function code_native(io::IO, @nospecialize(func), @nospecialize(types); kwargs...) + job, kwargs = create_job(func, types; kwargs...) + GPUCompiler.code_native(io, job; kwargs...) +end + +# aliases without ::IO argument +for method in (:code_warntype, :code_llvm, :code_native) + method = Symbol("$(method)") + @eval begin + $method(@nospecialize(func), @nospecialize(types); kwargs...) = + $method(stdout, func, types; kwargs...) + end +end + +# simulates codegen for a kernel function: validates by default +function code_execution(@nospecialize(func), @nospecialize(types); kwargs...) + job, kwargs = create_job(func, types; kernel=true, kwargs...) + JuliaContext() do ctx + GPUCompiler.compile(:asm, job; kwargs...) + end +end + end diff --git a/test/precompile_tests.jl b/test/precompile_tests.jl index 51a720af..2fae4722 100644 --- a/test/precompile_tests.jl +++ b/test/precompile_tests.jl @@ -1,10 +1,8 @@ @testitem "Precompile" begin using GPUCompiler -pushfirst!(LOAD_PATH, joinpath(@__DIR__, "..")) -pushfirst!(LOAD_PATH, joinpath(@__DIR__, "Native")) - -import Native +using ReTestItems +using Test function precompile_test_harness(@nospecialize(f), testset::String) @testset "$testset" begin @@ -51,6 +49,13 @@ function check_presence(mi, token) end precompile_test_harness("Inference caching") do load_path + TS_Native = include("native_testsetup.jl") + cp("runtime.jl", joinpath(load_path, "runtime.jl")) + + # Write out the Native test harness as a micro package + write(joinpath(load_path, "Native.jl"), string(:(module Native $(TS_Native.code) end))) + Base.compilecache(Base.PkgId("Native")) + write(joinpath(load_path, "InferenceCaching.jl"), :(module InferenceCaching import Native import GPUCompiler @@ -72,6 +77,8 @@ precompile_test_harness("Inference caching") do load_path Base.compilecache(Base.PkgId("InferenceCaching")) @eval let + import Native + # Check that no cached entry is present identity_mi = GPUCompiler.methodinstance(typeof(identity), Tuple{Int}) From f25773e07762dd774a2f2ca81591dd5032684608 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Fri, 12 Apr 2024 21:08:31 -0400 Subject: [PATCH 04/16] Handle foreign CI --- src/jlgen.jl | 11 +++++++++++ test/Project.toml | 1 + test/precompile_tests.jl | 13 ++++++++++--- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/jlgen.jl b/src/jlgen.jl index 518924b2..c09af674 100644 --- a/src/jlgen.jl +++ b/src/jlgen.jl @@ -749,3 +749,14 @@ function compile_method_instance(@nospecialize(job::CompilerJob)) return llvm_mod, compiled end + +function CC.typeinf(interp::GPUInterpreter, frame::CC.InferenceState) + if CC.__measure_typeinf__[] + CC.Timings.enter_new_timer(frame) + v = CC._typeinf(interp, frame) + CC.Timings.exit_current_timer(frame) + return v + else + return CC._typeinf(interp, frame) + end +end diff --git a/test/Project.toml b/test/Project.toml index ba189bc9..c5be5973 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -2,6 +2,7 @@ Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" LLVM = "929cbde3-209d-540e-8aea-75f648917ca0" +PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" ReTestItems = "817f1d60-ba6b-4fd5-9520-3cf149f6a823" SPIRV_LLVM_Translator_unified_jll = "85f0d8ed-5b39-5caa-b1ae-7472de402361" diff --git a/test/precompile_tests.jl b/test/precompile_tests.jl index 2fae4722..6b08c125 100644 --- a/test/precompile_tests.jl +++ b/test/precompile_tests.jl @@ -59,6 +59,7 @@ precompile_test_harness("Inference caching") do load_path write(joinpath(load_path, "InferenceCaching.jl"), :(module InferenceCaching import Native import GPUCompiler + using PrecompileTools function kernel() return @@ -71,8 +72,12 @@ precompile_test_harness("Inference caching") do load_path # identity is foreign # Maybe https://github.com/JuliaLang/julia/pull/49391 - job, _ = Native.create_job(identity, (Int,)) - GPUCompiler.code_typed(job) + @setup_workload begin + job, _ = Native.create_job(identity, (Int,)) + @compile_workload begin + GPUCompiler.code_typed(job) + end + end end) |> string) Base.compilecache(Base.PkgId("InferenceCaching")) @@ -100,8 +105,10 @@ precompile_test_harness("Inference caching") do load_path @test check_presence(kernel_mi, token) # check that identity survived - @test_broken check_presence(identity_mi, token) + @test check_presence(identity_mi, token) end end +# TODO test PTX to check for https://github.com/timholy/SnoopCompile.jl/issues/338 + end # testitem From 1fe18674f8b24e4069c5efae8b88aa797316638c Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Sat, 13 Apr 2024 07:59:27 -0400 Subject: [PATCH 05/16] Also test PTX --- test/native_tests.jl | 63 ++++++++++++++++++- test/precompile_tests.jl | 114 ----------------------------------- test/precompile_testsetup.jl | 51 ++++++++++++++++ test/ptx_tests.jl | 61 ++++++++++++++++++- 4 files changed, 173 insertions(+), 116 deletions(-) delete mode 100644 test/precompile_tests.jl create mode 100644 test/precompile_testsetup.jl diff --git a/test/native_tests.jl b/test/native_tests.jl index d9f3ab9f..9888bc01 100644 --- a/test/native_tests.jl +++ b/test/native_tests.jl @@ -1,4 +1,4 @@ -@testitem "native" setup=[Native, Helpers] begin +@testitem "native" setup=[Native, Helpers, Precompile] begin using Test @@ -536,6 +536,67 @@ end "inttoptr", "apply_type"]) broken=VERSION>=v"1.11.0-DEV.392" end +precompile_test_harness("Inference caching") do load_path + TS_Native = include("native_testsetup.jl") + cp("runtime.jl", joinpath(load_path, "runtime.jl")) + + # Write out the Native test setup as a micro package + write(joinpath(load_path, "NativeCompiler.jl"), string(:(module NativeCompiler $(TS_Native.code) end))) + Base.compilecache(Base.PkgId("NativeCompiler")) + + write(joinpath(load_path, "InferenceCaching.jl"), :(module InferenceCaching + import NativeCompiler + import GPUCompiler + using PrecompileTools + + function kernel() + return + end + + let + job, _ = NativeCompiler.create_job(kernel, ()) + GPUCompiler.code_typed(job) + end + + # identity is foreign + # Maybe https://github.com/JuliaLang/julia/pull/49391 + @setup_workload begin + job, _ = NativeCompiler.create_job(identity, (Int,)) + @compile_workload begin + GPUCompiler.code_typed(job) + end + end + end) |> string) + + Base.compilecache(Base.PkgId("InferenceCaching")) + @eval let + import NativeCompiler + + # Check that no cached entry is present + identity_mi = GPUCompiler.methodinstance(typeof(identity), Tuple{Int}) + + token = let + job, _ = NativeCompiler.create_job(identity, (Int,)) + GPUCompiler.ci_cache_token(job) + end + ci = isdefined(identity_mi, :cache) ? identity_mi.cache : nothing + while ci !== nothing + @test ci.owner === nothing + @test ci.owner !== token + ci = isdefined(ci, :next) ? ci.next : nothing + end + + using InferenceCaching + + # Check that kernel survived + kernel_mi = GPUCompiler.methodinstance(typeof(InferenceCaching.kernel), Tuple{}) + @test check_presence(kernel_mi, token) + + # check that identity survived + @test check_presence(identity_mi, token) + end +end + ############################################################################################ end diff --git a/test/precompile_tests.jl b/test/precompile_tests.jl deleted file mode 100644 index 6b08c125..00000000 --- a/test/precompile_tests.jl +++ /dev/null @@ -1,114 +0,0 @@ -@testitem "Precompile" begin - -using GPUCompiler -using ReTestItems -using Test - -function precompile_test_harness(@nospecialize(f), testset::String) - @testset "$testset" begin - precompile_test_harness(f, true) - end -end -function precompile_test_harness(@nospecialize(f), separate::Bool) - load_path = mktempdir() - load_cache_path = separate ? mktempdir() : load_path - try - pushfirst!(LOAD_PATH, load_path) - pushfirst!(DEPOT_PATH, load_cache_path) - f(load_path) - finally - try - rm(load_path, force=true, recursive=true) - catch err - @show err - end - if separate - try - rm(load_cache_path, force=true, recursive=true) - catch err - @show err - end - end - filter!((≠)(load_path), LOAD_PATH) - separate && filter!((≠)(load_cache_path), DEPOT_PATH) - end - nothing -end - -function check_presence(mi, token) - found = false - ci = isdefined(mi, :cache) ? mi.cache : nothing - while ci !== nothing - if ci.owner === token && ci.max_world == typemax(UInt) - found = true - break - end - ci = isdefined(ci, :next) ? ci.next : nothing - end - return found -end - -precompile_test_harness("Inference caching") do load_path - TS_Native = include("native_testsetup.jl") - cp("runtime.jl", joinpath(load_path, "runtime.jl")) - - # Write out the Native test harness as a micro package - write(joinpath(load_path, "Native.jl"), string(:(module Native $(TS_Native.code) end))) - Base.compilecache(Base.PkgId("Native")) - - write(joinpath(load_path, "InferenceCaching.jl"), :(module InferenceCaching - import Native - import GPUCompiler - using PrecompileTools - - function kernel() - return - end - - let - job, _ = Native.create_job(kernel, ()) - GPUCompiler.code_typed(job) - end - - # identity is foreign - # Maybe https://github.com/JuliaLang/julia/pull/49391 - @setup_workload begin - job, _ = Native.create_job(identity, (Int,)) - @compile_workload begin - GPUCompiler.code_typed(job) - end - end - end) |> string) - - Base.compilecache(Base.PkgId("InferenceCaching")) - @eval let - import Native - - # Check that no cached entry is present - identity_mi = GPUCompiler.methodinstance(typeof(identity), Tuple{Int}) - - token = let - job, _ = Native.create_job(identity, (Int,)) - GPUCompiler.ci_cache_token(job) - end - ci = isdefined(identity_mi, :cache) ? identity_mi.cache : nothing - while ci !== nothing - @test ci.owner === nothing - @test ci.owner !== token - ci = isdefined(ci, :next) ? ci.next : nothing - end - - using InferenceCaching - - # Check that kernel survived - kernel_mi = GPUCompiler.methodinstance(typeof(InferenceCaching.kernel), Tuple{}) - @test check_presence(kernel_mi, token) - - # check that identity survived - @test check_presence(identity_mi, token) - end -end - -# TODO test PTX to check for https://github.com/timholy/SnoopCompile.jl/issues/338 - -end # testitem diff --git a/test/precompile_testsetup.jl b/test/precompile_testsetup.jl new file mode 100644 index 00000000..f71e2bf9 --- /dev/null +++ b/test/precompile_testsetup.jl @@ -0,0 +1,51 @@ +@testsetup module + +using ReTestItems + +export precompile_test_harness, check_presence + +function precompile_test_harness(@nospecialize(f), testset::String) + @testset "$testset" begin + precompile_test_harness(f, true) + end +end +function precompile_test_harness(@nospecialize(f), separate::Bool) + load_path = mktempdir() + load_cache_path = separate ? mktempdir() : load_path + try + pushfirst!(LOAD_PATH, load_path) + pushfirst!(DEPOT_PATH, load_cache_path) + f(load_path) + finally + try + rm(load_path, force=true, recursive=true) + catch err + @show err + end + if separate + try + rm(load_cache_path, force=true, recursive=true) + catch err + @show err + end + end + filter!((≠)(load_path), LOAD_PATH) + separate && filter!((≠)(load_cache_path), DEPOT_PATH) + end + nothing +end + +function check_presence(mi, token) + found = false + ci = isdefined(mi, :cache) ? mi.cache : nothing + while ci !== nothing + if ci.owner === token && ci.max_world == typemax(UInt) + found = true + break + end + ci = isdefined(ci, :next) ? ci.next : nothing + end + return found +end + +end diff --git a/test/ptx_tests.jl b/test/ptx_tests.jl index 10b40db8..9844cdaa 100644 --- a/test/ptx_tests.jl +++ b/test/ptx_tests.jl @@ -1,4 +1,4 @@ -@testitem "PTX" setup=[PTX, Helpers] begin +@testitem "PTX" setup=[PTX, Helpers, Precompile] begin using LLVM @@ -322,6 +322,65 @@ end end +precompile_test_harness("Inference caching") do load_path + TS_PTX = include("ptx_testsetup.jl") + cp("runtime.jl", joinpath(load_path, "runtime.jl")) + + # Write out the PTX test setup as a micro package + write(joinpath(load_path, "PTXCompiler.jl"), string(:(module PTXCompiler $(TS_PTX.code) end))) + Base.compilecache(Base.PkgId("PTXCompiler")) + + write(joinpath(load_path, "InferenceCaching.jl"), :(module InferenceCaching + import PTXCompiler + import GPUCompiler + using PrecompileTools + + function kernel() + return + end + + let + job, _ = PTXCompiler.create_job(kernel, ()) + GPUCompiler.code_typed(job) + end + + # identity is foreign + @setup_workload begin + job, _ = PTXCompiler.create_job(identity, (Int,)) + @compile_workload begin + GPUCompiler.code_typed(job) + end + end + end) |> string) + + Base.compilecache(Base.PkgId("InferenceCaching")) + @eval let + import PTXCompiler + + # Check that no cached entry is present + identity_mi = GPUCompiler.methodinstance(typeof(identity), Tuple{Int}) + + token = let + job, _ = PTXCompiler.create_job(identity, (Int,)) + GPUCompiler.ci_cache_token(job) + end + ci = isdefined(identity_mi, :cache) ? identity_mi.cache : nothing + while ci !== nothing + @test ci.owner === nothing + @test ci.owner !== token + ci = isdefined(ci, :next) ? ci.next : nothing + end + + using InferenceCaching + + # Check that kernel survived + kernel_mi = GPUCompiler.methodinstance(typeof(InferenceCaching.kernel), Tuple{}) + @test check_presence(kernel_mi, token) + + # check that identity survived + @test check_presence(identity_mi, token) + end +end ############################################################################################ From af3468983983aa586f13559ce639fba36b258c7d Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Sat, 13 Apr 2024 08:00:09 -0400 Subject: [PATCH 06/16] fixup! Also test PTX --- test/native_tests.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/test/native_tests.jl b/test/native_tests.jl index 9888bc01..dc161492 100644 --- a/test/native_tests.jl +++ b/test/native_tests.jl @@ -559,7 +559,6 @@ precompile_test_harness("Inference caching") do load_path end # identity is foreign - # Maybe https://github.com/JuliaLang/julia/pull/49391 @setup_workload begin job, _ = NativeCompiler.create_job(identity, (Int,)) @compile_workload begin From f62f940a3e6fcca9986e9982ec2f04c43997dad3 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Sat, 13 Apr 2024 08:01:01 -0400 Subject: [PATCH 07/16] fixup! Also test PTX --- test/precompile_testsetup.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/precompile_testsetup.jl b/test/precompile_testsetup.jl index f71e2bf9..86780c4e 100644 --- a/test/precompile_testsetup.jl +++ b/test/precompile_testsetup.jl @@ -1,4 +1,4 @@ -@testsetup module +@testsetup module Precompile using ReTestItems From 90e90ab6d35cbb7b212e6da523418db84cc0e0c4 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Sat, 13 Apr 2024 08:04:35 -0400 Subject: [PATCH 08/16] fixup! Also test PTX --- test/native_tests.jl | 1 + test/precompile_testsetup.jl | 2 +- test/ptx_tests.jl | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/test/native_tests.jl b/test/native_tests.jl index dc161492..0fb6a612 100644 --- a/test/native_tests.jl +++ b/test/native_tests.jl @@ -1,6 +1,7 @@ @testitem "native" setup=[Native, Helpers, Precompile] begin using Test +using ReTestItems ############################################################################################ diff --git a/test/precompile_testsetup.jl b/test/precompile_testsetup.jl index 86780c4e..4078f4ee 100644 --- a/test/precompile_testsetup.jl +++ b/test/precompile_testsetup.jl @@ -1,6 +1,6 @@ @testsetup module Precompile -using ReTestItems +using Test export precompile_test_harness, check_presence diff --git a/test/ptx_tests.jl b/test/ptx_tests.jl index 9844cdaa..0b58d824 100644 --- a/test/ptx_tests.jl +++ b/test/ptx_tests.jl @@ -1,6 +1,7 @@ @testitem "PTX" setup=[PTX, Helpers, Precompile] begin using LLVM +using ReTestItems ############################################################################################ From 9f3fb47ebb12969b8072599de843d3017710784d Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Sat, 13 Apr 2024 08:14:22 -0400 Subject: [PATCH 09/16] Test no longer runs in isolation --- test/native_tests.jl | 1 - test/ptx_tests.jl | 1 - 2 files changed, 2 deletions(-) diff --git a/test/native_tests.jl b/test/native_tests.jl index 0fb6a612..26aad610 100644 --- a/test/native_tests.jl +++ b/test/native_tests.jl @@ -581,7 +581,6 @@ precompile_test_harness("Inference caching") do load_path end ci = isdefined(identity_mi, :cache) ? identity_mi.cache : nothing while ci !== nothing - @test ci.owner === nothing @test ci.owner !== token ci = isdefined(ci, :next) ? ci.next : nothing end diff --git a/test/ptx_tests.jl b/test/ptx_tests.jl index 0b58d824..8dea2f5c 100644 --- a/test/ptx_tests.jl +++ b/test/ptx_tests.jl @@ -367,7 +367,6 @@ precompile_test_harness("Inference caching") do load_path end ci = isdefined(identity_mi, :cache) ? identity_mi.cache : nothing while ci !== nothing - @test ci.owner === nothing @test ci.owner !== token ci = isdefined(ci, :next) ? ci.next : nothing end From 268d89144a5678c5050703b7c53c87ec1f1736d4 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Sat, 13 Apr 2024 08:18:35 -0400 Subject: [PATCH 10/16] Don't run tests on 1.9&co --- test/native_tests.jl | 2 +- test/ptx_tests.jl | 2 +- test/runtests.jl | 4 ---- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/test/native_tests.jl b/test/native_tests.jl index 26aad610..035e2a95 100644 --- a/test/native_tests.jl +++ b/test/native_tests.jl @@ -537,7 +537,7 @@ end "inttoptr", "apply_type"]) broken=VERSION>=v"1.11.0-DEV.392" end -precompile_test_harness("Inference caching") do load_path +VERSION >= v"1.11.0-" && precompile_test_harness("Inference caching") do load_path TS_Native = include("native_testsetup.jl") cp("runtime.jl", joinpath(load_path, "runtime.jl")) diff --git a/test/ptx_tests.jl b/test/ptx_tests.jl index 8dea2f5c..691ebd79 100644 --- a/test/ptx_tests.jl +++ b/test/ptx_tests.jl @@ -323,7 +323,7 @@ end end -precompile_test_harness("Inference caching") do load_path +VERSION >= v"1.11.0-" && precompile_test_harness("Inference caching") do load_path TS_PTX = include("ptx_testsetup.jl") cp("runtime.jl", joinpath(load_path, "runtime.jl")) diff --git a/test/runtests.jl b/test/runtests.jl index 199990e8..b86d2484 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -32,9 +32,5 @@ runtests(GPUCompiler; nworkers=min(Sys.CPU_THREADS,4), nworker_threads=1, return false end - if ti.name == "Precompile" && VERSION < v"1.11.0-" - return false - end - true end From aaab1b308c261deb1ab44159686d255dafc7be86 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 15 Apr 2024 11:18:04 -0400 Subject: [PATCH 11/16] fixup the testsetup logic --- test/native_tests.jl | 7 +------ test/precompile_testsetup.jl | 17 ++++++++++++++++- test/ptx_tests.jl | 7 +------ 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/test/native_tests.jl b/test/native_tests.jl index 035e2a95..df509e9a 100644 --- a/test/native_tests.jl +++ b/test/native_tests.jl @@ -1,7 +1,6 @@ @testitem "native" setup=[Native, Helpers, Precompile] begin using Test -using ReTestItems ############################################################################################ @@ -538,12 +537,8 @@ end end VERSION >= v"1.11.0-" && precompile_test_harness("Inference caching") do load_path - TS_Native = include("native_testsetup.jl") - cp("runtime.jl", joinpath(load_path, "runtime.jl")) - # Write out the Native test setup as a micro package - write(joinpath(load_path, "NativeCompiler.jl"), string(:(module NativeCompiler $(TS_Native.code) end))) - Base.compilecache(Base.PkgId("NativeCompiler")) + create_standalone(load_path, "NativeCompiler", "native_testsetup.jl") write(joinpath(load_path, "InferenceCaching.jl"), :(module InferenceCaching import NativeCompiler diff --git a/test/precompile_testsetup.jl b/test/precompile_testsetup.jl index 4078f4ee..4c8f5bcd 100644 --- a/test/precompile_testsetup.jl +++ b/test/precompile_testsetup.jl @@ -1,8 +1,9 @@ @testsetup module Precompile using Test +using ReTestItems -export precompile_test_harness, check_presence +export precompile_test_harness, check_presence, create_standalone function precompile_test_harness(@nospecialize(f), testset::String) @testset "$testset" begin @@ -48,4 +49,18 @@ function check_presence(mi, token) return found end +function create_standalone(load_path, name::String, file) + cp(joinpath(@__DIR__, "runtime.jl"), joinpath(load_path, "runtime.jl"), force=true) + + TS = include(file) + code = TS.code + if code.head == :begin + code.head = :block + end + @assert code.head == :block + code = Expr(:module, true, Symbol(name), code) + + # Write out the test setup as a micro package + write(joinpath(load_path, "$name.jl"), string(code)) + Base.compilecache(Base.PkgId(name))) end diff --git a/test/ptx_tests.jl b/test/ptx_tests.jl index 691ebd79..cd5396e7 100644 --- a/test/ptx_tests.jl +++ b/test/ptx_tests.jl @@ -1,7 +1,6 @@ @testitem "PTX" setup=[PTX, Helpers, Precompile] begin using LLVM -using ReTestItems ############################################################################################ @@ -324,12 +323,8 @@ end end VERSION >= v"1.11.0-" && precompile_test_harness("Inference caching") do load_path - TS_PTX = include("ptx_testsetup.jl") - cp("runtime.jl", joinpath(load_path, "runtime.jl")) - # Write out the PTX test setup as a micro package - write(joinpath(load_path, "PTXCompiler.jl"), string(:(module PTXCompiler $(TS_PTX.code) end))) - Base.compilecache(Base.PkgId("PTXCompiler")) + create_standalone(load_path, "PTXCompiler", "ptx_testsetup.jl") write(joinpath(load_path, "InferenceCaching.jl"), :(module InferenceCaching import PTXCompiler From 97594ea4c327fce4698e09dcd98074b67549c03b Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 15 Apr 2024 13:12:42 -0400 Subject: [PATCH 12/16] fixup! fixup the testsetup logic --- test/precompile_testsetup.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/precompile_testsetup.jl b/test/precompile_testsetup.jl index 4c8f5bcd..203157ad 100644 --- a/test/precompile_testsetup.jl +++ b/test/precompile_testsetup.jl @@ -64,3 +64,5 @@ function create_standalone(load_path, name::String, file) write(joinpath(load_path, "$name.jl"), string(code)) Base.compilecache(Base.PkgId(name))) end + +end # testsetup From 090a9525d5a669f4ea9f87664a498179cd40b1df Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 15 Apr 2024 13:27:34 -0400 Subject: [PATCH 13/16] fixup! fixup! fixup the testsetup logic --- test/precompile_testsetup.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/precompile_testsetup.jl b/test/precompile_testsetup.jl index 203157ad..ee3bec06 100644 --- a/test/precompile_testsetup.jl +++ b/test/precompile_testsetup.jl @@ -62,7 +62,7 @@ function create_standalone(load_path, name::String, file) # Write out the test setup as a micro package write(joinpath(load_path, "$name.jl"), string(code)) - Base.compilecache(Base.PkgId(name))) + Base.compilecache(Base.PkgId(name)) end end # testsetup From 86211b20248e82330cea56584815063bfd2c3372 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 15 Apr 2024 13:37:45 -0400 Subject: [PATCH 14/16] don't define runtime_module twice --- test/ptx_testsetup.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/test/ptx_testsetup.jl b/test/ptx_testsetup.jl index 7d7db554..ed5026f1 100644 --- a/test/ptx_testsetup.jl +++ b/test/ptx_testsetup.jl @@ -9,7 +9,6 @@ include("runtime.jl") struct CompilerParams <: AbstractCompilerParams end PTXCompilerJob = CompilerJob{PTXCompilerTarget,CompilerParams} -GPUCompiler.runtime_module(::PTXCompilerJob) = TestRuntime struct PTXKernelState data::Int64 From 1b35376face34d1c9e425080ee5181e466310f07 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 15 Apr 2024 16:47:20 -0400 Subject: [PATCH 15/16] breakup precompilation tests into their own testitem --- test/native_tests.jl | 6 +++++- test/ptx_tests.jl | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/test/native_tests.jl b/test/native_tests.jl index df509e9a..fcb47a55 100644 --- a/test/native_tests.jl +++ b/test/native_tests.jl @@ -1,4 +1,4 @@ -@testitem "native" setup=[Native, Helpers, Precompile] begin +@testitem "native" setup=[Native, Helpers] begin using Test @@ -535,7 +535,11 @@ end ["jl_invoke", "apply_iterate", "inttoptr", "apply_type"]) broken=VERSION>=v"1.11.0-DEV.392" end +end # testitem +@testitem "native precompile" setup=[Precompile,] begin + +using Test VERSION >= v"1.11.0-" && precompile_test_harness("Inference caching") do load_path # Write out the Native test setup as a micro package create_standalone(load_path, "NativeCompiler", "native_testsetup.jl") diff --git a/test/ptx_tests.jl b/test/ptx_tests.jl index cd5396e7..4d12e25b 100644 --- a/test/ptx_tests.jl +++ b/test/ptx_tests.jl @@ -1,4 +1,4 @@ -@testitem "PTX" setup=[PTX, Helpers, Precompile] begin +@testitem "PTX" setup=[PTX, Helpers] begin using LLVM @@ -321,7 +321,9 @@ end end end +end # testitem +@testitem "PTX precompile" setup=[Precompile,] begin VERSION >= v"1.11.0-" && precompile_test_harness("Inference caching") do load_path # Write out the PTX test setup as a micro package create_standalone(load_path, "PTXCompiler", "ptx_testsetup.jl") From d786ac6192ef6fe43f603d473285088e433b40b9 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 15 Apr 2024 18:16:48 -0400 Subject: [PATCH 16/16] filter in runtests --- test/native_tests.jl | 2 +- test/ptx_tests.jl | 2 +- test/runtests.jl | 8 +++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/test/native_tests.jl b/test/native_tests.jl index fcb47a55..ad753bde 100644 --- a/test/native_tests.jl +++ b/test/native_tests.jl @@ -540,7 +540,7 @@ end # testitem @testitem "native precompile" setup=[Precompile,] begin using Test -VERSION >= v"1.11.0-" && precompile_test_harness("Inference caching") do load_path +precompile_test_harness("Inference caching") do load_path # Write out the Native test setup as a micro package create_standalone(load_path, "NativeCompiler", "native_testsetup.jl") diff --git a/test/ptx_tests.jl b/test/ptx_tests.jl index 4d12e25b..e0a692c4 100644 --- a/test/ptx_tests.jl +++ b/test/ptx_tests.jl @@ -324,7 +324,7 @@ end end # testitem @testitem "PTX precompile" setup=[Precompile,] begin -VERSION >= v"1.11.0-" && precompile_test_harness("Inference caching") do load_path +precompile_test_harness("Inference caching") do load_path # Write out the PTX test setup as a micro package create_standalone(load_path, "PTXCompiler", "ptx_testsetup.jl") diff --git a/test/runtests.jl b/test/runtests.jl index b86d2484..9411dbc7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -22,15 +22,21 @@ runtests(GPUCompiler; nworkers=min(Sys.CPU_THREADS,4), nworker_threads=1, end end - if ti.name in ["PTX", "GCN"] && Sys.isapple() && VERSION >= v"1.10-" + if ti.name in ["PTX", "GCN", "PTX precompile"] && Sys.isapple() && VERSION >= v"1.10-" # support for AMDGPU and NVTX on macOS has been removed from Julia's LLVM build return false end + if ti.name in ["SPIRV"] && !(SPIRV_LLVM_Translator_unified_jll.is_available() && SPIRV_Tools_jll.is_available()) # SPIRV needs it's tools to be available return false end + if ti.name in ["PTX precompile", "native precompile"] && VERSION < v"1.11-" + # precompile needs v1.11 + return false + end + true end