Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #16434, superlinear compiler run time on large functions #16634

Merged
merged 1 commit into from
May 29, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 45 additions & 28 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1966,14 +1966,32 @@ function finish(me::InferenceState)
nothing
end

function eval_annotate(e::ANY, vtypes::ANY, sv::InferenceState, undefs)
function record_slot_type!(id, vt::ANY, slottypes)
if vt !== Bottom
otherTy = slottypes[id]
if otherTy === Bottom
slottypes[id] = vt
elseif otherTy !== Any && !typeseq(otherTy, vt)
slottypes[id] = Any
end
end
end

function eval_annotate(e::ANY, vtypes::ANY, sv::InferenceState, undefs, pass)
if isa(e, Slot)
t = abstract_eval(e, vtypes, sv)
s = vtypes[e.id]
if s.undef
undefs[e.id] = true
id = (e::Slot).id
s = vtypes[id]
vt = widenconst(s.typ)
if pass == 1
# first pass: find used-undef variables and type-constant variables
if s.undef
undefs[id] = true
end
record_slot_type!(id, vt, sv.linfo.slottypes)
return e
end
return t === sv.linfo.slottypes[e.id] ? e : TypedSlot(e.id, t)
# second pass: add type annotations where needed
return vt === sv.linfo.slottypes[id] ? e : TypedSlot(id, vt)
end

if !isa(e,Expr)
Expand All @@ -1985,14 +2003,14 @@ function eval_annotate(e::ANY, vtypes::ANY, sv::InferenceState, undefs)
if is(head,:static_typeof) || is(head,:line) || is(head,:const)
return e
elseif is(head,:(=))
e.args[2] = eval_annotate(e.args[2], vtypes, sv, undefs)
e.args[2] = eval_annotate(e.args[2], vtypes, sv, undefs, pass)
return e
end
i0 = is(head,:method) ? 2 : 1
for i=i0:length(e.args)
subex = e.args[i]
if !(isa(subex,Number) || isa(subex,AbstractString))
e.args[i] = eval_annotate(subex, vtypes, sv, undefs)
e.args[i] = eval_annotate(subex, vtypes, sv, undefs, pass)
end
end
return e
Expand All @@ -2013,38 +2031,31 @@ end
# annotate types of all symbols in AST
function type_annotate!(linfo::LambdaInfo, states::Array{Any,1}, sv::ANY, nargs)
nslots = length(states[1])
for i = 1:nslots
nargs = linfo.nargs
for i = 1:nargs
linfo.slottypes[i] = widenconst(states[1][i].typ)
end
for i = nargs+1:nslots
linfo.slottypes[i] = Bottom
end
undefs = fill(false, nslots)
body = linfo.code::Array{Any,1}
nexpr = length(body)
for i=1:nexpr
# identify variables always used as the same type
st_i = states[i]
if st_i !== ()
for j = 1:nslots
vt = widenconst(st_i[j].typ)
if vt !== Bottom
otherTy = linfo.slottypes[j]
if otherTy === Bottom
linfo.slottypes[j] = vt
elseif otherTy !== Any && !typeseq(otherTy, vt)
linfo.slottypes[j] = Any
end
end
end
end
end
i = 1
optimize = sv.optimize::Bool
while i <= nexpr
st_i = states[i]
expr = body[i]
if st_i !== ()
# st_i === () => unreached statement (see issue #7836)
body[i] = eval_annotate(body[i], st_i, sv, undefs)
eval_annotate(expr, st_i, sv, undefs, 1)
if isa(expr, Expr) && expr.head == :(=) && i < nexpr && isa(expr.args[1],Slot) && states[i+1] !== ()
# record type of assigned slot by looking at the next statement.
# this is needed in case the slot is never used (which makes eval_annotate miss it).
id = expr.args[1].id
record_slot_type!(id, widenconst(states[i+1][id].typ), linfo.slottypes)
end
elseif optimize
expr = body[i]
if isa(expr, Expr) && expr_cannot_delete(expr::Expr)
i += 1
continue
Expand All @@ -2058,6 +2069,12 @@ function type_annotate!(linfo::LambdaInfo, states::Array{Any,1}, sv::ANY, nargs)
end
i += 1
end
for i = 1:nexpr
st_i = states[i]
if st_i !== ()
body[i] = eval_annotate(body[i], st_i, sv, undefs, 2)
end
end

# mark used-undef variables
for i = 1:nslots
Expand Down