Skip to content

Commit

Permalink
fix problems exposed by previous commit and do a few small optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
vtjnash committed Sep 12, 2023
1 parent f4ac759 commit 416b240
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 29 deletions.
6 changes: 1 addition & 5 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3123,11 +3123,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
ssavaluetypes[currpc] = Any
continue
end
if !isempty(frame.ssavalue_uses[currpc])
record_ssa_assign!(𝕃ᵢ, currpc, type, frame)
else
ssavaluetypes[currpc] = type
end
record_ssa_assign!(𝕃ᵢ, currpc, type, frame)
end # for currpc in bbstart:bbend

# Case 1: Fallthrough termination
Expand Down
7 changes: 2 additions & 5 deletions base/compiler/inferencestate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -584,11 +584,8 @@ _topmod(sv::InferenceState) = _topmod(frame_module(sv))
function record_ssa_assign!(𝕃ᵢ::AbstractLattice, ssa_id::Int, @nospecialize(new), frame::InferenceState)
ssavaluetypes = frame.ssavaluetypes
old = ssavaluetypes[ssa_id]
if old === NOT_FOUND || !(𝕃ᵢ, new, old)
# typically, we expect that old ⊑ new (that output information only
# gets less precise with worse input information), but to actually
# guarantee convergence we need to use tmerge here to ensure that is true
ssavaluetypes[ssa_id] = old === NOT_FOUND ? new : tmerge(𝕃ᵢ, old, new)
if old === NOT_FOUND || !is_lattice_equal(𝕃ᵢ, new, old)
ssavaluetypes[ssa_id] = new
W = frame.ip
for r in frame.ssavalue_uses[ssa_id]
if was_reached(frame, r)
Expand Down
50 changes: 38 additions & 12 deletions base/compiler/typelimits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -305,10 +305,17 @@ union_count_abstract(x::Union) = union_count_abstract(x.a) + union_count_abstrac
union_count_abstract(@nospecialize(x)) = !isdispatchelem(x)

function issimpleenoughtype(@nospecialize t)
ut = unwrap_unionall(t)
ut isa DataType && ut.name.wrapper == t && return true
return unionlen(t) + union_count_abstract(t) <= MAX_TYPEUNION_LENGTH &&
unioncomplexity(t) <= MAX_TYPEUNION_COMPLEXITY
end

# We may want to apply a stricter limit than issimpleenoughtype to
# tupleelements individually, to try to keep the whole tuple under the limit,
# even after complicated recursion and other operations on it elsewhere
const issimpleenoughtupleelem(@nospecialize t) = issimpleenoughtype

# A simplified type_more_complex query over the extended lattice
# (assumes typeb ⊑ typea)
@nospecializeinfer function issimplertype(𝕃::AbstractLattice, @nospecialize(typea), @nospecialize(typeb))
Expand Down Expand Up @@ -742,6 +749,7 @@ end
# see if any of the union elements have the same TypeName
# in which case, simplify this tmerge by replacing it with
# the widest possible version of itself (the wrapper)
havetuples = false
for i in 1:length(types)
typenames[i] === Any.name && continue
ti = types[i]
Expand All @@ -764,6 +772,7 @@ end
# see 4ee2b41552a6bc95465c12ca66146d69b354317b, be59686f7613a2ccfd63491c7b354d0b16a95c05,
widen = tuplemerge(unwrap_unionall(ti)::DataType, unwrap_unionall(tj)::DataType)
widen = rewrap_unionall(rewrap_unionall(widen, ti), tj)
havetuples = true
else
wr = ijname.wrapper
uw = unwrap_unionall(wr)::DataType
Expand All @@ -776,15 +785,20 @@ end
uj = uj.super
end
merged = Vector{Any}(undef, length(uw.parameters))
use_merged = true
widen = wr
for k = 1:length(uw.parameters)
ui_k = ui.parameters[k]
if ui_k === uj.parameters[k] && !has_free_typevars(ui_k)
merged[k] = ui_k
use_merged = true
else
merged[k] = uw.parameters[k]
end
end
widen = rewrap_unionall(wr{merged...}, wr)
if use_merged
widen = rewrap_unionall(wr{merged...}, wr)
end
end
types[i] = Union{}
typenames[i] = Any.name
Expand All @@ -796,22 +810,28 @@ end
end
# don't let elements of the union get too big, if the above didn't reduce something
# Specifically widen Tuple{..., Union{lots of stuff}...} to Tuple{..., Any, ...}
# Even if there was only one element of the base type, don't let Val{<:Val{<:Val}} keep nesting abstract levels
for i in 1:length(types)
# this element is too complicated, so
# just return the widest possible type now
issimpleenoughtype(types[i]) && continue
if typenames[i] === Tuple.name
ti = types[i]
tip = (unwrap_unionall(types[i])::DataType).parameters
tn = typenames[i]
ti = types[i]
if tn === Any.name || issimpleenoughtype(ti)
continue
elseif tn === Tuple.name
havetuples && continue # multiple-tuples case was already handled by tuplemerge above
# otherwise we need to do a simple version of tuplemerge for one element now
tip = (unwrap_unionall(ti)::DataType).parameters
lt = length(tip)
p = Vector{Any}(undef, lt)
for j = 1:lt
ui = tip[j]
p[j] = issimpleenoughtype(unwrapva(ui)) ? ui : isvarargtype(ui) ? Vararg : Any
p[j] = issimpleenoughtupleelem(unwrapva(ui)) ? ui : isvarargtype(ui) ? Vararg : Any
end
types[i] = rewrap_unionall(Tuple{p...}, ti)
else
issimpleenoughtype(types[i]) || return Any
# this element is not simple enough yet, make it so now
types[i] = tn.wrapper
end
end
u = Union{types...}
Expand All @@ -837,7 +857,7 @@ function tuplemerge(a::DataType, b::DataType)
p = Vector{Any}(undef, lt + vt)
for i = 1:lt
ui = Union{ap[i], bp[i]}
p[i] = issimpleenoughtype(ui) ? ui : Any
p[i] = issimpleenoughtupleelem(ui) ? ui : Any
end
# merge the remaining tail into a single, simple Tuple{Vararg{T}} (#22120)
if vt
Expand All @@ -855,8 +875,9 @@ function tuplemerge(a::DataType, b::DataType)
# or (equivalently?) iteratively took super-types until reaching a common wrapper
# e.g. consider the results of `tuplemerge(Tuple{Complex}, Tuple{Number, Int})` and of
# `tuplemerge(Tuple{Int}, Tuple{String}, Tuple{Int, String})`
if !(ti <: tail)
if tail <: ti
hasfree = has_free_typevars(ti)
if hasfree || !(ti <: tail)
if !hasfree && tail <: ti
tail = ti # widen to ti
else
uw = unwrap_unionall(tail)
Expand Down Expand Up @@ -884,11 +905,16 @@ function tuplemerge(a::DataType, b::DataType)
end
end
end
tail === Any && return Tuple # short-circuit loop
tail === Any && return Tuple # short-circuit loops
end
end
@assert !(tail === Union{})
p[lt + 1] = Vararg{tail}
if !issimpleenoughtupleelem(tail) || tail === Any
p[lt + 1] = Vararg
lt == 0 && return Tuple
else
p[lt + 1] = Vararg{tail}
end
end
return Tuple{p...}
end
4 changes: 2 additions & 2 deletions base/compiler/typeutils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ end
unioncomplexity(@nospecialize x) = _unioncomplexity(x)::Int
function _unioncomplexity(@nospecialize x)
if isa(x, DataType)
x.name === Tuple.name || isvarargtype(x) || return 0
x.name === Tuple.name || return 0
c = 0
for ti in x.parameters
c = max(c, unioncomplexity(ti))
Expand All @@ -302,7 +302,7 @@ function _unioncomplexity(@nospecialize x)
elseif isa(x, UnionAll)
return max(unioncomplexity(x.body), unioncomplexity(x.var.ub))
elseif isa(x, TypeofVararg)
return isdefined(x, :T) ? unioncomplexity(x.T) : 0
return isdefined(x, :T) ? unioncomplexity(x.T) + 1 : 1
else
return 0
end
Expand Down
32 changes: 27 additions & 5 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,11 @@ Base.ndims(g::e43296) = ndims(typeof(g))
@test Core.Compiler.unioncomplexity(Tuple{Union{Int8, Int16, Int32, Int64}}) == 3
@test Core.Compiler.unioncomplexity(Union{Int8, Int16, Int32, T} where T) == 3
@test Core.Compiler.unioncomplexity(Tuple{Val{T}, Union{Int8, Int16}, Int8} where T<:Union{Int8, Int16, Int32, Int64}) == 3
@test Core.Compiler.unioncomplexity(Tuple{Vararg{Tuple{Union{Int8, Int16}}}}) == 1
@test Core.Compiler.unioncomplexity(Tuple{Vararg{Symbol}}) == 0
@test Core.Compiler.unioncomplexity(Tuple{Vararg{Union{Symbol, Tuple{Vararg{Symbol}}}}}) == 1
@test Core.Compiler.unioncomplexity(Tuple{Vararg{Union{Symbol, Tuple{Vararg{Union{Symbol, Tuple{Vararg{Symbol}}}}}}}}) == 2
@test Core.Compiler.unioncomplexity(Tuple{Vararg{Union{Symbol, Tuple{Vararg{Union{Symbol, Tuple{Vararg{Union{Symbol, Tuple{Vararg{Symbol}}}}}}}}}}}) == 3
@test Core.Compiler.unioncomplexity(Tuple{Vararg{Tuple{Union{Int8, Int16}}}}) == 2
@test Core.Compiler.unioncomplexity(Tuple{Vararg{Symbol}}) == 1
@test Core.Compiler.unioncomplexity(Tuple{Vararg{Union{Symbol, Tuple{Vararg{Symbol}}}}}) == 3
@test Core.Compiler.unioncomplexity(Tuple{Vararg{Union{Symbol, Tuple{Vararg{Union{Symbol, Tuple{Vararg{Symbol}}}}}}}}) == 5
@test Core.Compiler.unioncomplexity(Tuple{Vararg{Union{Symbol, Tuple{Vararg{Union{Symbol, Tuple{Vararg{Union{Symbol, Tuple{Vararg{Symbol}}}}}}}}}}}) == 7


# PR 22120
Expand Down Expand Up @@ -3511,6 +3511,18 @@ end
@test only(Base.return_types(pickvarnames, (Vector{Any},))) == Tuple
@test only(Base.code_typed(pickvarnames, (Vector{Any},), optimize=false))[2] == Tuple{Vararg{Union{Symbol, Tuple}}}

# make sure this converges in a reasonable amount of time
function pickvarnames2(x::Vector{Any})
varnames = ()
for a in x
varnames = (varnames..., pickvarnames(a) )
end
return varnames
end
@test only(Base.return_types(pickvarnames2, (Vector{Any},))) == Tuple{Vararg{Union{Symbol, Tuple}}}
@test only(Base.code_typed(pickvarnames2, (Vector{Any},), optimize=false))[2] == Tuple{Vararg{Union{Symbol, Tuple}}}


@test map(>:, [Int], [Int]) == [true]

# issue 35566
Expand Down Expand Up @@ -4604,6 +4616,16 @@ end
a = Core.Compiler.tmerge(Core.Compiler.JLTypeLattice(), Val{<:a}, a)
@test_broken a != Val{<:Val{Union{}}}
@test_broken a == Val{<:Val} || a == Val

a = Tuple{Vararg{Tuple{}}}
a = Core.Compiler.tmerge(Core.Compiler.JLTypeLattice(), Tuple{a}, a)
@test a == Tuple{Vararg{Tuple{Vararg{Tuple{}}}}}
a = Core.Compiler.tmerge(Core.Compiler.JLTypeLattice(), Tuple{a}, a)
@test a == Tuple{Vararg{Tuple{Vararg{Tuple{Vararg{Tuple{}}}}}}}
a = Core.Compiler.tmerge(Core.Compiler.JLTypeLattice(), Tuple{a}, a)
@test a == Tuple{Vararg{Tuple{Vararg{Tuple{Vararg{Tuple{Vararg{Tuple{}}}}}}}}}
a = Core.Compiler.tmerge(Core.Compiler.JLTypeLattice(), Tuple{a}, a)
@test a == Tuple
end

# Test that a function-wise `@max_methods` works as expected
Expand Down

0 comments on commit 416b240

Please sign in to comment.