Skip to content

Commit

Permalink
experiment @nospecializeinfer on Core.Compiler
Browse files Browse the repository at this point in the history
This commit adds `@nospecializeinfer` macro on various `Core.Compiler`
functions and achieves the following sysimage size reduction:

|                                   | this commit | master      | %       |
| --------------------------------- | ----------- | ----------- | ------- |
| `Core.Compiler` compilation (sec) | `66.4551`   | `71.0846`   | `0.935` |
| `corecompiler.jl` (KB)            | `17638080`  | `18407248`  | `0.958` |
| `sys.jl` (KB)                     | `88736432`  | `89361280`  | `0.993` |
| `sys-o.a` (KB)                    | `189484400` | `189907096` | `0.998` |
  • Loading branch information
aviatesk committed May 12, 2023
1 parent ce2275c commit 1dc2ed6
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 87 deletions.
30 changes: 15 additions & 15 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2645,18 +2645,18 @@ struct BestguessInfo{Interp<:AbstractInterpreter}
end
end

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

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

function widenreturn(𝕃ᡒ::MustAliasesLattice, @nospecialize(rt), info::BestguessInfo)
@nospecializeinfer function widenreturn(𝕃ᡒ::MustAliasesLattice, @nospecialize(rt), info::BestguessInfo)
if isa(rt, MustAlias)
if 1 ≀ rt.slot ≀ info.nargs
rt = InterMustAlias(rt)
Expand All @@ -2668,7 +2668,7 @@ function widenreturn(𝕃ᡒ::MustAliasesLattice, @nospecialize(rt), info::Bestg
return widenreturn(widenlattice(𝕃ᡒ), rt, info)
end

function widenreturn(𝕃ᡒ::ConditionalsLattice, @nospecialize(rt), info::BestguessInfo)
@nospecializeinfer 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 @@ -2705,7 +2705,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)
@nospecializeinfer 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 @@ -2723,7 +2723,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)
@nospecializeinfer 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 @@ -2742,13 +2742,13 @@ function bool_rt_to_conditional(@nospecialize(rt), slot_id::Int, info::Bestguess
return rt
end

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

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

function widenreturn(::JLTypeLattice, @nospecialize(rt), ::BestguessInfo)
@nospecializeinfer function widenreturn(::JLTypeLattice, @nospecialize(rt), ::BestguessInfo)
return widenconst(rt)
end
function widenreturn_noslotwrapper(::JLTypeLattice, @nospecialize(rt), ::BestguessInfo)
@nospecializeinfer 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
@nospecializeinfer βŠ‘(::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)
@nospecializeinfer ⊏(𝕃::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)
@nospecializeinfer β‹€(𝕃::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))
@nospecializeinfer 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) =
@nospecializeinfer has_nontrivial_extended_info(𝕃::AbstractLattice, @nospecialize t) =
has_nontrivial_extended_info(widenlattice(𝕃), t)
function has_nontrivial_extended_info(𝕃::PartialsLattice, @nospecialize t)
@nospecializeinfer 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)
@nospecializeinfer 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
@nospecializeinfer 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) =
@nospecializeinfer is_const_prop_profitable_arg(𝕃::AbstractLattice, @nospecialize t) =
is_const_prop_profitable_arg(widenlattice(𝕃), t)
function is_const_prop_profitable_arg(𝕃::PartialsLattice, @nospecialize t)
@nospecializeinfer 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)
@nospecializeinfer 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
@nospecializeinfer is_const_prop_profitable_arg(::JLTypeLattice, @nospecialize t) = false

is_forwardable_argtype(𝕃::AbstractLattice, @nospecialize(x)) =
@nospecializeinfer is_forwardable_argtype(𝕃::AbstractLattice, @nospecialize(x)) =
is_forwardable_argtype(widenlattice(𝕃), x)
function is_forwardable_argtype(𝕃::ConditionalsLattice, @nospecialize x)
@nospecializeinfer 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)
@nospecializeinfer 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)
@nospecializeinfer 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)
@nospecializeinfer 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)) =
@nospecializeinfer 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)
@nospecializeinfer 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)
@nospecializeinfer @nospecialize(a) βŠ‘ @nospecialize(b) = βŠ‘(fallback_lattice, a, b)
@nospecializeinfer @nospecialize(a) ⊏ @nospecialize(b) = ⊏(fallback_lattice, a, b)
@nospecializeinfer @nospecialize(a) β‹€ @nospecialize(b) = β‹€(fallback_lattice, a, b)
@nospecializeinfer tmeet(@nospecialize(a), @nospecialize(b)) = tmeet(fallback_lattice, a, b)
@nospecializeinfer tmerge(@nospecialize(a), @nospecialize(b)) = tmerge(fallback_lattice, a, b)
@nospecializeinfer 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
Loading

0 comments on commit 1dc2ed6

Please sign in to comment.