Skip to content

Commit

Permalink
inference: some optimization improvements (#43447)
Browse files Browse the repository at this point in the history
- cut off allocation in `tmerge`
- improve type instabilities
  • Loading branch information
aviatesk authored Dec 17, 2021
1 parent a957953 commit 7855e85
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 34 deletions.
4 changes: 1 addition & 3 deletions base/compiler/ssair/legacy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ function inflate_ir(ci::CodeInfo, sptypes::Vector{Any}, argtypes::Vector{Any})
elseif isa(stmt, PhiNode)
code[i] = PhiNode(Int32[block_for_inst(cfg, Int(edge)) for edge in stmt.edges], stmt.values)
elseif isa(stmt, Expr) && stmt.head === :enter
stmt.args[1] = block_for_inst(cfg, stmt.args[1])
code[i] = stmt
else
stmt.args[1] = block_for_inst(cfg, stmt.args[1]::Int)
code[i] = stmt
end
end
Expand Down
41 changes: 22 additions & 19 deletions base/compiler/typelimits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ function tmerge(@nospecialize(typea), @nospecialize(typeb))
if is_same_conditionals(typea, typeb)
vtype = tmerge(typea.vtype, typeb.vtype)
elsetype = tmerge(typea.elsetype, typeb.elsetype)
if vtype != elsetype
if vtype !== elsetype
return Conditional(typea.var, vtype, elsetype)
end
end
Expand Down Expand Up @@ -388,7 +388,7 @@ function tmerge(@nospecialize(typea), @nospecialize(typeb))
if is_same_conditionals(typea, typeb)
vtype = tmerge(typea.vtype, typeb.vtype)
elsetype = tmerge(typea.elsetype, typeb.elsetype)
if vtype != elsetype
if vtype !== elsetype
return InterConditional(typea.slot, vtype, elsetype)
end
end
Expand All @@ -400,24 +400,27 @@ function tmerge(@nospecialize(typea), @nospecialize(typeb))
end
# type-lattice for Const and PartialStruct wrappers
if ((isa(typea, PartialStruct) || isa(typea, Const)) &&
(isa(typeb, PartialStruct) || isa(typeb, Const)) &&
widenconst(typea) === widenconst(typeb))

typea_nfields = nfields_tfunc(typea)
typeb_nfields = nfields_tfunc(typeb)
if !isa(typea_nfields, Const) || !isa(typeb_nfields, Const) || typea_nfields.val !== typeb_nfields.val
return widenconst(typea)
(isa(typeb, PartialStruct) || isa(typeb, Const)))
aty = widenconst(typea)
bty = widenconst(typeb)
if aty === bty
typea_nfields = nfields_tfunc(typea)
typeb_nfields = nfields_tfunc(typeb)
isa(typea_nfields, Const) || return aty
isa(typeb_nfields, Const) || return aty
type_nfields = typea_nfields.val::Int
type_nfields === typeb_nfields.val::Int || return aty
type_nfields == 0 && return aty
fields = Vector{Any}(undef, type_nfields)
anyconst = false
for i = 1:type_nfields
ity = tmerge(getfield_tfunc(typea, Const(i)),
getfield_tfunc(typeb, Const(i)))
fields[i] = ity
anyconst |= has_nontrivial_const_info(ity)
end
return anyconst ? PartialStruct(aty, fields) : aty
end

type_nfields = typea_nfields.val::Int
fields = Vector{Any}(undef, type_nfields)
anyconst = false
for i = 1:type_nfields
fields[i] = tmerge(getfield_tfunc(typea, Const(i)),
getfield_tfunc(typeb, Const(i)))
anyconst |= has_nontrivial_const_info(fields[i])
end
return anyconst ? PartialStruct(widenconst(typea), fields) : widenconst(typea)
end
if isa(typea, PartialOpaque) && isa(typeb, PartialOpaque) && widenconst(typea) == widenconst(typeb)
if !(typea.source === typeb.source &&
Expand Down
29 changes: 17 additions & 12 deletions base/compiler/typeutils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -263,20 +263,25 @@ end

# unioncomplexity estimates the number of calls to `tmerge` to obtain the given type by
# counting the Union instances, taking also into account those hidden in a Tuple or UnionAll
function unioncomplexity(u::Union)
return unioncomplexity(u.a)::Int + unioncomplexity(u.b)::Int + 1
end
function unioncomplexity(t::DataType)
t.name === Tuple.name || isvarargtype(t) || return 0
c = 0
for ti in t.parameters
c = max(c, unioncomplexity(ti)::Int)
unioncomplexity(@nospecialize x) = _unioncomplexity(x)::Int
function _unioncomplexity(@nospecialize x)
if isa(x, DataType)
x.name === Tuple.name || isvarargtype(x) || return 0
c = 0
for ti in x.parameters
c = max(c, unioncomplexity(ti))
end
return c
elseif isa(x, Union)
return unioncomplexity(x.a) + unioncomplexity(x.b) + 1
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
else
return 0
end
return c
end
unioncomplexity(u::UnionAll) = max(unioncomplexity(u.body)::Int, unioncomplexity(u.var.ub)::Int)
unioncomplexity(t::TypeofVararg) = isdefined(t, :T) ? unioncomplexity(t.T)::Int : 0
unioncomplexity(@nospecialize(x)) = 0

# convert a Union of Tuple types to a Tuple of Unions
function unswitchtupleunion(u::Union)
Expand Down

0 comments on commit 7855e85

Please sign in to comment.