Skip to content

Commit

Permalink
Merge 61b6236 into b4cc5c2
Browse files Browse the repository at this point in the history
  • Loading branch information
aviatesk authored Apr 12, 2023
2 parents b4cc5c2 + 61b6236 commit b9a74e0
Show file tree
Hide file tree
Showing 18 changed files with 291 additions and 115 deletions.
40 changes: 24 additions & 16 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,10 @@ function abstract_call_method(interp::AbstractInterpreter,
sigtuple = unwrap_unionall(sig)
sigtuple isa DataType || return MethodCallResult(Any, false, false, nothing, Effects())

if is_noinfer(method)
sig = get_nospecialize_sig(method, sig, sparams)
end

# Limit argument type tuple growth of functions:
# look through the parents list to see if there's a call to the same method
# and from the same method.
Expand Down Expand Up @@ -1075,7 +1079,11 @@ function maybe_get_const_prop_profitable(interp::AbstractInterpreter,
return nothing
end
force |= all_overridden
mi = specialize_method(match; preexisting=!force)
if is_noinfer(method)
mi = specialize_method_noinfer(match; preexisting=!force)
else
mi = specialize_method(match; preexisting=!force)
end
if mi === nothing
add_remark!(interp, sv, "[constprop] Failed to specialize")
return nothing
Expand Down Expand Up @@ -2659,18 +2667,18 @@ struct BestguessInfo{Interp<:AbstractInterpreter}
end
end

function widenreturn(@nospecialize(rt), info::BestguessInfo)
@noinfer function widenreturn(@nospecialize(rt), info::BestguessInfo)
return widenreturn(typeinf_lattice(info.interp), rt, info)
end

function widenreturn(𝕃ᵢ::AbstractLattice, @nospecialize(rt), info::BestguessInfo)
@noinfer function widenreturn(𝕃ᵢ::AbstractLattice, @nospecialize(rt), info::BestguessInfo)
return widenreturn(widenlattice(𝕃ᵢ), rt, info)
end
function widenreturn_noslotwrapper(𝕃ᵢ::AbstractLattice, @nospecialize(rt), info::BestguessInfo)
@noinfer function widenreturn_noslotwrapper(𝕃ᵢ::AbstractLattice, @nospecialize(rt), info::BestguessInfo)
return widenreturn_noslotwrapper(widenlattice(𝕃ᵢ), rt, info)
end

function widenreturn(𝕃ᵢ::MustAliasesLattice, @nospecialize(rt), info::BestguessInfo)
@noinfer function widenreturn(𝕃ᵢ::MustAliasesLattice, @nospecialize(rt), info::BestguessInfo)
if isa(rt, MustAlias)
if 1 rt.slot info.nargs
rt = InterMustAlias(rt)
Expand All @@ -2682,7 +2690,7 @@ function widenreturn(𝕃ᵢ::MustAliasesLattice, @nospecialize(rt), info::Bestg
return widenreturn(widenlattice(𝕃ᵢ), rt, info)
end

function widenreturn(𝕃ᵢ::ConditionalsLattice, @nospecialize(rt), info::BestguessInfo)
@noinfer function widenreturn(𝕃ᵢ::ConditionalsLattice, @nospecialize(rt), info::BestguessInfo)
= (𝕃ᵢ)
if !((ipo_lattice(info.interp), info.bestguess, Bool)) || info.bestguess === Bool
# give up inter-procedural constraint back-propagation
Expand Down Expand Up @@ -2719,7 +2727,7 @@ function widenreturn(𝕃ᵢ::ConditionalsLattice, @nospecialize(rt), info::Best
isa(rt, InterConditional) && return rt
return widenreturn(widenlattice(𝕃ᵢ), rt, info)
end
function bool_rt_to_conditional(@nospecialize(rt), info::BestguessInfo)
@noinfer function bool_rt_to_conditional(@nospecialize(rt), info::BestguessInfo)
bestguess = info.bestguess
if isa(bestguess, InterConditional)
# if the bestguess so far is already `Conditional`, try to convert
Expand All @@ -2737,7 +2745,7 @@ function bool_rt_to_conditional(@nospecialize(rt), info::BestguessInfo)
end
return rt
end
function bool_rt_to_conditional(@nospecialize(rt), slot_id::Int, info::BestguessInfo)
@noinfer function bool_rt_to_conditional(@nospecialize(rt), slot_id::Int, info::BestguessInfo)
= (typeinf_lattice(info.interp))
old = info.slottypes[slot_id]
new = widenslotwrapper(info.changes[slot_id].typ) # avoid nested conditional
Expand All @@ -2756,13 +2764,13 @@ function bool_rt_to_conditional(@nospecialize(rt), slot_id::Int, info::Bestguess
return rt
end

function widenreturn(𝕃ᵢ::PartialsLattice, @nospecialize(rt), info::BestguessInfo)
@noinfer function widenreturn(𝕃ᵢ::PartialsLattice, @nospecialize(rt), info::BestguessInfo)
return widenreturn_partials(𝕃ᵢ, rt, info)
end
function widenreturn_noslotwrapper(𝕃ᵢ::PartialsLattice, @nospecialize(rt), info::BestguessInfo)
@noinfer function widenreturn_noslotwrapper(𝕃ᵢ::PartialsLattice, @nospecialize(rt), info::BestguessInfo)
return widenreturn_partials(𝕃ᵢ, rt, info)
end
function widenreturn_partials(𝕃ᵢ::PartialsLattice, @nospecialize(rt), info::BestguessInfo)
@noinfer function widenreturn_partials(𝕃ᵢ::PartialsLattice, @nospecialize(rt), info::BestguessInfo)
if isa(rt, PartialStruct)
fields = copy(rt.fields)
local anyrefine = false
Expand All @@ -2785,21 +2793,21 @@ function widenreturn_partials(𝕃ᵢ::PartialsLattice, @nospecialize(rt), info:
return widenreturn(widenlattice(𝕃ᵢ), rt, info)
end

function widenreturn(::ConstsLattice, @nospecialize(rt), ::BestguessInfo)
@noinfer function widenreturn(::ConstsLattice, @nospecialize(rt), ::BestguessInfo)
return widenreturn_consts(rt)
end
function widenreturn_noslotwrapper(::ConstsLattice, @nospecialize(rt), ::BestguessInfo)
@noinfer function widenreturn_noslotwrapper(::ConstsLattice, @nospecialize(rt), ::BestguessInfo)
return widenreturn_consts(rt)
end
function widenreturn_consts(@nospecialize(rt))
@noinfer function widenreturn_consts(@nospecialize(rt))
isa(rt, Const) && return rt
return widenconst(rt)
end

function widenreturn(::JLTypeLattice, @nospecialize(rt), ::BestguessInfo)
@noinfer function widenreturn(::JLTypeLattice, @nospecialize(rt), ::BestguessInfo)
return widenconst(rt)
end
function widenreturn_noslotwrapper(::JLTypeLattice, @nospecialize(rt), ::BestguessInfo)
@noinfer function widenreturn_noslotwrapper(::JLTypeLattice, @nospecialize(rt), ::BestguessInfo)
return widenconst(rt)
end

Expand Down
50 changes: 25 additions & 25 deletions base/compiler/abstractlattice.jl
Original file line number Diff line number Diff line change
Expand Up @@ -161,23 +161,23 @@ If `𝕃` is `JLTypeLattice`, this is equivalent to subtyping.
"""
function end

(::JLTypeLattice, @nospecialize(a::Type), @nospecialize(b::Type)) = a <: b
@noinfer (::JLTypeLattice, @nospecialize(a::Type), @nospecialize(b::Type)) = a <: b

"""
⊏(𝕃::AbstractLattice, a, b) -> Bool
The strict partial order over the type inference lattice.
This is defined as the irreflexive kernel of `⊑`.
"""
(𝕃::AbstractLattice, @nospecialize(a), @nospecialize(b)) = (𝕃, a, b) && !(𝕃, b, a)
@noinfer (𝕃::AbstractLattice, @nospecialize(a), @nospecialize(b)) = (𝕃, a, b) && !(𝕃, b, a)

"""
⋤(𝕃::AbstractLattice, a, b) -> Bool
This order could be used as a slightly more efficient version of the strict order `⊏`,
where we can safely assume `a ⊑ b` holds.
"""
(𝕃::AbstractLattice, @nospecialize(a), @nospecialize(b)) = !(𝕃, b, a)
@noinfer (𝕃::AbstractLattice, @nospecialize(a), @nospecialize(b)) = !(𝕃, b, a)

"""
is_lattice_equal(𝕃::AbstractLattice, a, b) -> Bool
Expand All @@ -186,7 +186,7 @@ Check if two lattice elements are partial order equivalent.
This is basically `a ⊑ b && b ⊑ a` in the lattice of `𝕃`
but (optionally) with extra performance optimizations.
"""
function is_lattice_equal(𝕃::AbstractLattice, @nospecialize(a), @nospecialize(b))
@noinfer function is_lattice_equal(𝕃::AbstractLattice, @nospecialize(a), @nospecialize(b))
a === b && return true
return (𝕃, a, b) && (𝕃, b, a)
end
Expand All @@ -197,32 +197,32 @@ end
Determines whether the given lattice element `t` of `𝕃` has non-trivial extended lattice
information that would not be available from the type itself.
"""
has_nontrivial_extended_info(𝕃::AbstractLattice, @nospecialize t) =
@noinfer has_nontrivial_extended_info(𝕃::AbstractLattice, @nospecialize t) =
has_nontrivial_extended_info(widenlattice(𝕃), t)
function has_nontrivial_extended_info(𝕃::PartialsLattice, @nospecialize t)
@noinfer function has_nontrivial_extended_info(𝕃::PartialsLattice, @nospecialize t)
isa(t, PartialStruct) && return true
isa(t, PartialOpaque) && return true
return has_nontrivial_extended_info(widenlattice(𝕃), t)
end
function has_nontrivial_extended_info(𝕃::ConstsLattice, @nospecialize t)
@noinfer function has_nontrivial_extended_info(𝕃::ConstsLattice, @nospecialize t)
isa(t, PartialTypeVar) && return true
if isa(t, Const)
val = t.val
return !issingletontype(typeof(val)) && !(isa(val, Type) && hasuniquerep(val))
end
return has_nontrivial_extended_info(widenlattice(𝕃), t)
end
has_nontrivial_extended_info(::JLTypeLattice, @nospecialize(t)) = false
@noinfer has_nontrivial_extended_info(::JLTypeLattice, @nospecialize(t)) = false

"""
is_const_prop_profitable_arg(𝕃::AbstractLattice, t) -> Bool
Determines whether the given lattice element `t` of `𝕃` has new extended lattice information
that should be forwarded along with constant propagation.
"""
is_const_prop_profitable_arg(𝕃::AbstractLattice, @nospecialize t) =
@noinfer is_const_prop_profitable_arg(𝕃::AbstractLattice, @nospecialize t) =
is_const_prop_profitable_arg(widenlattice(𝕃), t)
function is_const_prop_profitable_arg(𝕃::PartialsLattice, @nospecialize t)
@noinfer function is_const_prop_profitable_arg(𝕃::PartialsLattice, @nospecialize t)
if isa(t, PartialStruct)
return true # might be a bit aggressive, may want to enable some check like follows:
# for i = 1:length(t.fields)
Expand All @@ -236,7 +236,7 @@ function is_const_prop_profitable_arg(𝕃::PartialsLattice, @nospecialize t)
isa(t, PartialOpaque) && return true
return is_const_prop_profitable_arg(widenlattice(𝕃), t)
end
function is_const_prop_profitable_arg(𝕃::ConstsLattice, @nospecialize t)
@noinfer function is_const_prop_profitable_arg(𝕃::ConstsLattice, @nospecialize t)
if isa(t, Const)
# don't consider mutable values useful constants
val = t.val
Expand All @@ -245,24 +245,24 @@ function is_const_prop_profitable_arg(𝕃::ConstsLattice, @nospecialize t)
isa(t, PartialTypeVar) && return false # this isn't forwardable
return is_const_prop_profitable_arg(widenlattice(𝕃), t)
end
is_const_prop_profitable_arg(::JLTypeLattice, @nospecialize t) = false
@noinfer is_const_prop_profitable_arg(::JLTypeLattice, @nospecialize t) = false

is_forwardable_argtype(𝕃::AbstractLattice, @nospecialize(x)) =
@noinfer is_forwardable_argtype(𝕃::AbstractLattice, @nospecialize(x)) =
is_forwardable_argtype(widenlattice(𝕃), x)
function is_forwardable_argtype(𝕃::ConditionalsLattice, @nospecialize x)
@noinfer function is_forwardable_argtype(𝕃::ConditionalsLattice, @nospecialize x)
isa(x, Conditional) && return true
return is_forwardable_argtype(widenlattice(𝕃), x)
end
function is_forwardable_argtype(𝕃::PartialsLattice, @nospecialize x)
@noinfer function is_forwardable_argtype(𝕃::PartialsLattice, @nospecialize x)
isa(x, PartialStruct) && return true
isa(x, PartialOpaque) && return true
return is_forwardable_argtype(widenlattice(𝕃), x)
end
function is_forwardable_argtype(𝕃::ConstsLattice, @nospecialize x)
@noinfer function is_forwardable_argtype(𝕃::ConstsLattice, @nospecialize x)
isa(x, Const) && return true
return is_forwardable_argtype(widenlattice(𝕃), x)
end
function is_forwardable_argtype(::JLTypeLattice, @nospecialize x)
@noinfer function is_forwardable_argtype(::JLTypeLattice, @nospecialize x)
return false
end

Expand All @@ -281,9 +281,9 @@ External lattice `𝕃ᵢ::ExternalLattice` may overload:
"""
function widenreturn end, function widenreturn_noslotwrapper end

is_valid_lattice(𝕃::AbstractLattice, @nospecialize(elem)) =
@noinfer is_valid_lattice(𝕃::AbstractLattice, @nospecialize(elem)) =
is_valid_lattice_norec(𝕃, elem) && is_valid_lattice(widenlattice(𝕃), elem)
is_valid_lattice(𝕃::JLTypeLattice, @nospecialize(elem)) = is_valid_lattice_norec(𝕃, elem)
@noinfer is_valid_lattice(𝕃::JLTypeLattice, @nospecialize(elem)) = is_valid_lattice_norec(𝕃, elem)

has_conditional(𝕃::AbstractLattice) = has_conditional(widenlattice(𝕃))
has_conditional(::AnyConditionalsLattice) = true
Expand All @@ -306,12 +306,12 @@ has_extended_unionsplit(::JLTypeLattice) = false
const fallback_lattice = InferenceLattice(BaseInferenceLattice.instance)
const fallback_ipo_lattice = InferenceLattice(IPOResultLattice.instance)

(@nospecialize(a), @nospecialize(b)) = (fallback_lattice, a, b)
tmeet(@nospecialize(a), @nospecialize(b)) = tmeet(fallback_lattice, a, b)
tmerge(@nospecialize(a), @nospecialize(b)) = tmerge(fallback_lattice, a, b)
(@nospecialize(a), @nospecialize(b)) = (fallback_lattice, a, b)
(@nospecialize(a), @nospecialize(b)) = (fallback_lattice, a, b)
is_lattice_equal(@nospecialize(a), @nospecialize(b)) = is_lattice_equal(fallback_lattice, a, b)
@noinfer @nospecialize(a) @nospecialize(b) = (fallback_lattice, a, b)
@noinfer @nospecialize(a) @nospecialize(b) = (fallback_lattice, a, b)
@noinfer @nospecialize(a) @nospecialize(b) = (fallback_lattice, a, b)
@noinfer tmeet(@nospecialize(a), @nospecialize(b)) = tmeet(fallback_lattice, a, b)
@noinfer tmerge(@nospecialize(a), @nospecialize(b)) = tmerge(fallback_lattice, a, b)
@noinfer is_lattice_equal(@nospecialize(a), @nospecialize(b)) = is_lattice_equal(fallback_lattice, a, b)

# Widenlattice with argument
widenlattice(::JLTypeLattice, @nospecialize(t)) = widenconst(t)
Expand Down
6 changes: 5 additions & 1 deletion base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,11 @@ function analyze_method!(match::MethodMatch, argtypes::Vector{Any},
end

# See if there exists a specialization for this method signature
mi = specialize_method(match; preexisting=true) # Union{Nothing, MethodInstance}
if is_noinfer(method)
mi = specialize_method_noinfer(match; preexisting=true)
else
mi = specialize_method(match; preexisting=true)
end
if mi === nothing
et = InliningEdgeTracker(state.et, invokesig)
effects = info_effects(nothing, match, state)
Expand Down
Loading

0 comments on commit b9a74e0

Please sign in to comment.