Skip to content

Commit

Permalink
complete the tests for Compiler.jl as the stdlib.
Browse files Browse the repository at this point in the history
With #56632, Compiler.jl as the stdlib can now be tested.
However, the PR was incomplete, and when tests are actually run on
`Compiler`, which is `!== Base.Compiler`, various errors occur,
including issues caused by #56647.

This commit resolves all these issues:
- manage the code for loading `Compiler` in `setup_Compiler.jl`,
  ensuring that the stdlib version of `Compiler` is loaded when
  `@activate Compiler` is used beforehand
- replace `Base.IRShow` with `Compiler.IRShow`
- test `Base.Compiler.return_type` instead of `Compiler.return_type`

This was split off from #56636.
  • Loading branch information
aviatesk committed Nov 22, 2024
1 parent e624440 commit 5f2dd1b
Show file tree
Hide file tree
Showing 18 changed files with 79 additions and 118 deletions.
2 changes: 1 addition & 1 deletion Compiler/src/ssair/verify.jl
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ function verify_ir(ir::IRCode, print::Bool=true,
error_args = Any["IR verification failed."]
if isdefined(Core, :Main) && isdefined(Core.Main, :Base)
# ensure we use I/O that does not yield, as this gets called during compilation
firstline = invokelatest(Core.Main.Base.IRShow.debuginfo_firstline, ir.debuginfo)
firstline = invokelatest(IRShow.debuginfo_firstline, ir.debuginfo)
else
firstline = nothing
end
Expand Down
8 changes: 0 additions & 8 deletions Compiler/test/AbstractInterpreter.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,6 @@

using Test

if !@isdefined(Compiler)
if Base.identify_package("Compiler") === nothing
import Base.Compiler: Compiler
else
import Compiler
end
end

include("irutils.jl")
include("newinterp.jl")

Expand Down
18 changes: 6 additions & 12 deletions Compiler/test/EAUtils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,7 @@ module EAUtils

export code_escapes, @code_escapes, __clear_cache!

if !@isdefined(Compiler)
if Base.identify_package("Compiler") === nothing
import Base.Compiler: Compiler
else
import Compiler
end
end
include("setup_Compiler.jl")

using ..EscapeAnalysis
const EA = EscapeAnalysis
Expand Down Expand Up @@ -267,22 +261,22 @@ end

function print_with_info(preprint, postprint, io::IO, ir::IRCode, source::Bool)
io = IOContext(io, :displaysize=>displaysize(io))
used = Base.IRShow.stmts_used(io, ir)
used = Compiler.IRShow.stmts_used(io, ir)
if source
line_info_preprinter = function (io::IO, indent::String, idx::Int)
r = Base.IRShow.inline_linfo_printer(ir)(io, indent, idx)
r = Compiler.IRShow.inline_linfo_printer(ir)(io, indent, idx)
idx 0 && preprint(io, idx)
return r
end
else
line_info_preprinter = Base.IRShow.lineinfo_disabled
line_info_preprinter = Compiler.IRShow.lineinfo_disabled
end
line_info_postprinter = Base.IRShow.default_expr_type_printer
line_info_postprinter = Compiler.IRShow.default_expr_type_printer
preprint(io)
bb_idx_prev = bb_idx = 1
for idx = 1:length(ir.stmts)
preprint(io, idx)
bb_idx = Base.IRShow.show_ir_stmt(io, ir, idx, line_info_preprinter, line_info_postprinter, ir.sptypes, used, ir.cfg, bb_idx)
bb_idx = Compiler.IRShow.show_ir_stmt(io, ir, idx, line_info_preprinter, line_info_postprinter, ir.sptypes, used, ir.cfg, bb_idx)
postprint(io, idx, bb_idx != bb_idx_prev)
bb_idx_prev = bb_idx
end
Expand Down
9 changes: 2 additions & 7 deletions Compiler/test/codegen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,9 @@
using Random
using InteractiveUtils
using Libdl
using Test

if !@isdefined(Compiler)
if Base.identify_package("Compiler") === nothing
import Base.Compiler: Compiler
else
import Compiler
end
end
include("setup_Compiler.jl")

const opt_level = Base.JLOptions().opt_level
const coverage = (Base.JLOptions().code_coverage > 0) || (Base.JLOptions().malloc_log > 0)
Expand Down
12 changes: 5 additions & 7 deletions Compiler/test/compact.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
if !@isdefined(Compiler)
if Base.identify_package("Compiler") === nothing
import Base.Compiler: Compiler
else
import Compiler
end
end
# This file is a part of Julia. License is MIT: https://julialang.org/license

using Test

include("irutils.jl")

using .Compiler: IncrementalCompact, insert_node_here!, finish,
NewInstruction, verify_ir, ReturnNode, SSAValue
Expand Down
9 changes: 1 addition & 8 deletions Compiler/test/contextual.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,7 @@

# N.B.: This file is also run from interpreter.jl, so needs to be standalone-executable
using Test

if !@isdefined(Compiler)
if Base.identify_package("Compiler") === nothing
import Base.Compiler: Compiler
else
import Compiler
end
end
include("setup_Compiler.jl")

# Cassette
# ========
Expand Down
10 changes: 2 additions & 8 deletions Compiler/test/datastructures.jl
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
using Test
# This file is a part of Julia. License is MIT: https://julialang.org/license

if !@isdefined(Compiler)
if Base.identify_package("Compiler") === nothing
import Base.Compiler: Compiler
else
import Compiler
end
end
include("setup_Compiler.jl")

@testset "CachedMethodTable" begin
# cache result should be separated per `limit` and `sig`
Expand Down
2 changes: 2 additions & 0 deletions Compiler/test/effects.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

using Test
include("irutils.jl")

Expand Down
57 changes: 30 additions & 27 deletions Compiler/test/inference.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

using Test

include("irutils.jl")

# tests for Compiler correctness and precision
import .Compiler: Const, Conditional, , ReturnNode, GotoIfNot
using .Compiler: Conditional,
isdispatchelem(@nospecialize x) = !isa(x, Type) || Compiler.isdispatchelem(x)

using Random, Core.IR
Expand Down Expand Up @@ -823,7 +825,7 @@ end

# Issue 19641
foo19641() = let a = 1.0
Compiler.return_type(x -> x + a, Tuple{Float64})
Base.Compiler.return_type(x -> x + a, Tuple{Float64})
end
@inferred foo19641()

Expand Down Expand Up @@ -977,15 +979,15 @@ test_no_apply(::Any) = true

# issue #20033
# check return_type_tfunc for calls where no method matches
bcast_eltype_20033(f, A) = Compiler.return_type(f, Tuple{eltype(A)})
bcast_eltype_20033(f, A) = Base.Compiler.return_type(f, Tuple{eltype(A)})
err20033(x::Float64...) = prod(x)
@test bcast_eltype_20033(err20033, [1]) === Union{}
@test Base.return_types(bcast_eltype_20033, (typeof(err20033), Vector{Int},)) == Any[Type{Union{}}]
# return_type on builtins
@test Compiler.return_type(tuple, Tuple{Int,Int8,Int}) === Tuple{Int,Int8,Int}
@test Base.Compiler.return_type(tuple, Tuple{Int,Int8,Int}) === Tuple{Int,Int8,Int}

# issue #21088
@test Compiler.return_type(typeof, Tuple{Int}) == Type{Int}
@test Base.Compiler.return_type(typeof, Tuple{Int}) == Type{Int}

# Inference of constant svecs
@eval fsvecinf() = $(QuoteNode(Core.svec(Tuple{Int,Int}, Int)))[1]
Expand Down Expand Up @@ -1535,7 +1537,7 @@ let nfields_tfunc(@nospecialize xs...) =
@test sizeof_nothrow(String)
@test !sizeof_nothrow(Type{String})
@test sizeof_tfunc(Type{Union{Int64, Int32}}) == Const(Core.sizeof(Union{Int64, Int32}))
let PT = Core.PartialStruct(Base.Compiler.fallback_lattice, Tuple{Int64,UInt64}, Any[Const(10), UInt64])
let PT = Core.PartialStruct(Compiler.fallback_lattice, Tuple{Int64,UInt64}, Any[Const(10), UInt64])
@test sizeof_tfunc(PT) === Const(16)
@test nfields_tfunc(PT) === Const(2)
@test sizeof_nothrow(PT)
Expand Down Expand Up @@ -1721,7 +1723,7 @@ g_test_constant() = (f_constant(3) == 3 && f_constant(4) == 4 ? true : "BAD")
f_pure_add() = (1 + 1 == 2) ? true : "FAIL"
@test @inferred f_pure_add()

import Core: Const
using Core: Const
mutable struct ARef{T}
@atomic x::T
end
Expand Down Expand Up @@ -1762,7 +1764,7 @@ let getfield_tfunc(@nospecialize xs...) =
@test getfield_tfunc(ARef{Int},Const(:x),Bool,Bool) === Union{}
end

import .Compiler: Const
using Core: Const
mutable struct XY{X,Y}
x::X
y::Y
Expand Down Expand Up @@ -2235,7 +2237,7 @@ end
end |> only == Int
# the `fargs = nothing` edge case
@test Base.return_types((Any,)) do a
Compiler.return_type(invoke, Tuple{typeof(ispositive), Type{Tuple{Any}}, Any})
Base.Compiler.return_type(invoke, Tuple{typeof(ispositive), Type{Tuple{Any}}, Any})
end |> only == Type{Bool}

# `InterConditional` handling: `abstract_call_opaque_closure`
Expand Down Expand Up @@ -2765,10 +2767,9 @@ end |> only === Int

# `apply_type_tfunc` accuracy for constrained type construction
# https://github.com/JuliaLang/julia/issues/47089
import Core: Const
import .Compiler: apply_type_tfunc
struct Issue47089{A<:Number,B<:Number} end
let 𝕃 = Compiler.fallback_lattice
let apply_type_tfunc = Compiler.apply_type_tfunc
𝕃 = Compiler.fallback_lattice
A = Type{<:Integer}
@test apply_type_tfunc(𝕃, Const(Issue47089), A, A) <: (Type{Issue47089{A,B}} where {A<:Integer, B<:Integer})
@test apply_type_tfunc(𝕃, Const(Issue47089), Const(Int), Const(Int), Const(Int)) === Union{}
Expand Down Expand Up @@ -3324,8 +3325,8 @@ _rttf_test(::Int16) = 0
_rttf_test(::Int32) = 0
_rttf_test(::Int64) = 0
_rttf_test(::Int128) = 0
_call_rttf_test() = Compiler.return_type(_rttf_test, Tuple{Any})
@test Compiler.return_type(_rttf_test, Tuple{Any}) === Int
_call_rttf_test() = Base.Compiler.return_type(_rttf_test, Tuple{Any})
@test Base.Compiler.return_type(_rttf_test, Tuple{Any}) === Int
@test _call_rttf_test() === Int

f_with_Type_arg(::Type{T}) where {T} = T
Expand Down Expand Up @@ -3379,9 +3380,9 @@ struct FooPartial
b::Int
c::Int
end
let PT1 = PartialStruct(Base.Compiler.fallback_lattice, FooPartial, Any[Const(1), Const(2), Int]),
PT2 = PartialStruct(Base.Compiler.fallback_lattice, FooPartial, Any[Const(1), Int, Int]),
PT3 = PartialStruct(Base.Compiler.fallback_lattice, FooPartial, Any[Const(1), Int, Const(3)])
let PT1 = PartialStruct(Compiler.fallback_lattice, FooPartial, Any[Const(1), Const(2), Int]),
PT2 = PartialStruct(Compiler.fallback_lattice, FooPartial, Any[Const(1), Int, Int]),
PT3 = PartialStruct(Compiler.fallback_lattice, FooPartial, Any[Const(1), Int, Const(3)])

@test PT1 PT2
@test !(PT1 PT3) && !(PT2 PT1)
Expand Down Expand Up @@ -4554,7 +4555,8 @@ end |> only == Tuple{Int,Int}
end |> only == Int

# form PartialStruct for mutables with `const` field
import .Compiler: Const,
using Core: Const
using .Compiler:
mutable struct PartialMutable{S,T}
const s::S
t::T
Expand Down Expand Up @@ -4787,7 +4789,7 @@ end
# at top level.
@test let
Base.Experimental.@force_compile
Compiler.return_type(+, NTuple{2, Rational})
Base.Compiler.return_type(+, NTuple{2, Rational})
end == Rational

# vararg-tuple comparison within `Compiler.PartialStruct`
Expand Down Expand Up @@ -5185,9 +5187,9 @@ end |> only === Tuple{Int,Symbol}
end
end) == Type{Nothing}

# Test that Compiler.return_type inference works for the 1-arg version
# Test that Base.Compiler.return_type inference works for the 1-arg version
@test Base.return_types() do
Compiler.return_type(Tuple{typeof(+), Int, Int})
Base.Compiler.return_type(Tuple{typeof(+), Int, Int})
end |> only == Type{Int}

# Test that NamedTuple abstract iteration works for PartialStruct/Const
Expand Down Expand Up @@ -5700,7 +5702,8 @@ let x = 1, _Any = Any
end

# Issue #51927
let 𝕃 = Compiler.fallback_lattice
let apply_type_tfunc = Compiler.apply_type_tfunc
𝕃 = Compiler.fallback_lattice
@test apply_type_tfunc(𝕃, Const(Tuple{Vararg{Any,N}} where N), Int) == Type{NTuple{_A, Any}} where _A
end

Expand All @@ -5723,7 +5726,7 @@ end
@eval function has_tuin()
$(Expr(:throw_undef_if_not, :x, false))
end
@test Compiler.return_type(has_tuin, Tuple{}) === Union{}
@test Base.infer_return_type(has_tuin, Tuple{}) === Union{}
@test_throws UndefVarError has_tuin()

function gen_tuin_from_arg(world::UInt, source, _, _)
Expand Down Expand Up @@ -5778,7 +5781,7 @@ end

# We want to make sure that both this returns `Tuple` and that
# it doesn't infinite loop inside inference.
@test Compiler.return_type(gen_infinite_loop_ssa, Tuple{}) === Tuple
@test Base.infer_return_type(gen_infinite_loop_ssa, Tuple{}) === Tuple

# inference local cache lookup with extended lattice elements that may be transformed
# by `matching_cache_argtypes`
Expand Down Expand Up @@ -5814,7 +5817,7 @@ function foo54341(a, b, c, d, args...)
end
bar54341(args...) = foo54341(4, args...)

@test Compiler.return_type(bar54341, Tuple{Vararg{Int}}) === Int
@test Base.infer_return_type(bar54341, Tuple{Vararg{Int}}) === Int

# `PartialStruct` for partially initialized structs:
struct PartiallyInitialized1
Expand Down Expand Up @@ -5951,7 +5954,7 @@ end
# InterConditional rt with Vararg argtypes
fcondvarargs(a, b, c, d) = isa(d, Int64)
gcondvarargs(a, x...) = return fcondvarargs(a, x...) ? isa(a, Int64) : !isa(a, Int64)
@test Compiler.return_type(gcondvarargs, Tuple{Vararg{Any}}) === Bool
@test Base.infer_return_type(gcondvarargs, Tuple{Vararg{Any}}) === Bool

# JuliaLang/julia#55627: argtypes check in `abstract_call_opaque_closure`
issue55627_make_oc() = Base.Experimental.@opaque (x::Int) -> 2x
Expand Down Expand Up @@ -6098,4 +6101,4 @@ function func_swapglobal!_must_throw(x)
swapglobal!(@__MODULE__, :swapglobal!_must_throw, x)
end
@test Base.infer_return_type(func_swapglobal!_must_throw, (Int,); interp=SwapGlobalInterp()) === Union{}
@test !Base.Compiler.is_effect_free(Base.infer_effects(func_swapglobal!_must_throw, (Int,); interp=SwapGlobalInterp()) )
@test !Compiler.is_effect_free(Base.infer_effects(func_swapglobal!_must_throw, (Int,); interp=SwapGlobalInterp()) )
4 changes: 2 additions & 2 deletions Compiler/test/inline.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1857,7 +1857,7 @@ let i::Int, continue_::Bool
ir = Compiler.ssa_inlining_pass!(ir, inlining, false)
@test findfirst(isinvoke(:func_mul_int), ir.stmts.stmt) === nothing
@test (i = findfirst(iscall((ir, Core.Intrinsics.mul_int)), ir.stmts.stmt)) !== nothing
lins = Base.IRShow.buildLineInfoNode(ir.debuginfo, nothing, i)
lins = Compiler.IRShow.buildLineInfoNode(ir.debuginfo, nothing, i)
@test (continue_ = length(lins) == 2) # :multi_inlining1 -> :func_mul_int
if continue_
def1 = lins[1].method
Expand All @@ -1881,7 +1881,7 @@ let i::Int, continue_::Bool
ir = Compiler.ssa_inlining_pass!(ir, inlining, false)
@test findfirst(isinvoke(:func_mul_int), ir.stmts.stmt) === nothing
@test (i = findfirst(iscall((ir, Core.Intrinsics.mul_int)), ir.stmts.stmt)) !== nothing
lins = Base.IRShow.buildLineInfoNode(ir.debuginfo, nothing, i)
lins = Compiler.IRShow.buildLineInfoNode(ir.debuginfo, nothing, i)
@test_broken (continue_ = length(lins) == 3) # see TODO in `ir_inline_linetable!`
if continue_
def1 = lins[1].method
Expand Down
10 changes: 2 additions & 8 deletions Compiler/test/interpreter_exec.jl
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

# tests that interpreter matches codegen
include("setup_Compiler.jl")

using Test
using Core.IR

if !@isdefined(Compiler)
if Base.identify_package("Compiler") === nothing
import Base.Compiler: Compiler
else
import Compiler
end
end

# test that interpreter correctly handles PhiNodes (#29262)
let m = Meta.@lower 1 + 1
@assert Meta.isexpr(m, :thunk)
Expand Down
6 changes: 3 additions & 3 deletions Compiler/test/invalidation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ begin
let rt = only(Base.return_types(pr48932_callee, (Any,)))
@test rt === Any
effects = Base.infer_effects(pr48932_callee, (Any,))
@test Compiler.Effects(effects) == Compiler.Effects()
@test effects == Compiler.Effects()
end

# run inference on both `pr48932_caller` and `pr48932_callee`
Expand Down Expand Up @@ -171,7 +171,7 @@ begin take!(GLOBAL_BUFFER)
let rt = only(Base.return_types(pr48932_callee_inferable, (Any,)))
@test rt === Int
effects = Base.infer_effects(pr48932_callee_inferable, (Any,))
@test Compiler.Effects(effects) == Compiler.Effects()
@test effects == Compiler.Effects()
end

# run inference on both `pr48932_caller` and `pr48932_callee`:
Expand Down Expand Up @@ -233,7 +233,7 @@ begin take!(GLOBAL_BUFFER)
let rt = only(Base.return_types(pr48932_callee_inlined, (Any,)))
@test rt === Any
effects = Base.infer_effects(pr48932_callee_inlined, (Any,))
@test Compiler.Effects(effects) == Compiler.Effects()
@test effects == Compiler.Effects()
end

# run inference on `pr48932_caller_inlined` and `pr48932_callee_inlined`
Expand Down
Loading

0 comments on commit 5f2dd1b

Please sign in to comment.