Skip to content

Commit

Permalink
Merge pull request #23470 from JuliaLang/jn/var-infer
Browse files Browse the repository at this point in the history
better constant variable inference
  • Loading branch information
vtjnash authored Aug 28, 2017
2 parents 5b12051 + de7b893 commit ff706aa
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 40 deletions.
33 changes: 24 additions & 9 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3153,6 +3153,10 @@ function typeinf_work(frame::InferenceState)
# directly forward changes to an SSAValue to the applicable line
record_ssa_assign(changes_var.id + 1, changes.vtype.typ, frame)
end
elseif isa(stmt, NewvarNode)
sn = slot_id(stmt.slot)
changes = changes::VarTable
changes[sn] = VarState(Bottom, true)
elseif isa(stmt, GotoNode)
pc´ = (stmt::GotoNode).label
elseif isa(stmt, Expr)
Expand Down Expand Up @@ -3563,7 +3567,7 @@ function annotate_slot_load!(e::Expr, vtypes::VarTable, sv::InferenceState, unde
elseif isa(subex, Slot)
id = slot_id(subex)
s = vtypes[id]
vt = widenconst(s.typ)
vt = s.typ
if s.undef
# find used-undef variables
undefs[id] = true
Expand Down Expand Up @@ -3680,28 +3684,39 @@ function type_annotate!(sv::InferenceState)
end

# widen all Const elements in type annotations
function _widen_all_consts!(e::Expr, untypedload::Vector{Bool})
function _widen_all_consts!(e::Expr, untypedload::Vector{Bool}, slottypes::Vector{Any})
e.typ = widenconst(e.typ)
for i = 1:length(e.args)
x = e.args[i]
if isa(x, Expr)
_widen_all_consts!(x, untypedload)
elseif isa(x, Slot) && (i != 1 || e.head !== :(=))
untypedload[slot_id(x)] = true
_widen_all_consts!(x, untypedload, slottypes)
elseif isa(x, TypedSlot)
vt = widenconst(x.typ)
if !(vt === x.typ)
if slottypes[x.id] <: vt
x = SlotNumber(x.id)
untypedload[x.id] = true
else
x = TypedSlot(x.id, vt)
end
e.args[i] = x
end
elseif isa(x, SlotNumber) && (i != 1 || e.head !== :(=))
untypedload[x.id] = true
end
end
nothing
end

function widen_all_consts!(src::CodeInfo)
for i = 1:length(src.ssavaluetypes)
src.ssavaluetypes[i] = widenconst(src.ssavaluetypes[i])
end
nslots = length(src.slottypes)
untypedload = fill(false, nslots)
for i = 1:length(src.code)
x = src.code[i]
isa(x, Expr) && _widen_all_consts!(x, untypedload)
end
e = Expr(:body)
e.args = src.code
_widen_all_consts!(e, untypedload, src.slottypes)
for i = 1:nslots
src.slottypes[i] = widen_slot_type(src.slottypes[i], untypedload[i])
end
Expand Down
84 changes: 53 additions & 31 deletions test/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -254,35 +254,6 @@ function foo9222()
end
@test 0.0 == foo9222()

# make sure none of the slottypes are left as Core.Inference.Const objects
function f18679()
for i = 1:2
if i == 1
a = ((),)
else
return a[1]
end
end
end
g18679(x::Tuple) = ()
g18679() = g18679(any_undef_global::Union{Int,Tuple{}})
for code in Any[
@code_typed(f18679())[1]
@code_typed(g18679())[1]]
@test all(x->isa(x, Type), code.slottypes)
local notconst(@nospecialize(other)) = true
notconst(slot::TypedSlot) = @test isa(slot.typ, Type)
function notconst(expr::Expr)
@test isa(expr.typ, Type)
for a in expr.args
notconst(a)
end
end
for e in code.code
notconst(e)
end
end

# branching based on inferrable conditions
let f(x) = isa(x,Int) ? 1 : ""
@test Base.return_types(f, Tuple{Int}) == [Int]
Expand Down Expand Up @@ -470,11 +441,62 @@ function test_inferred_static(arrow::Pair)
end
end

function f18679()
local a
for i = 1:2
if i == 1
a = ((),)
else
return a[1]
end
end
end
g18679(x::Tuple) = ()
g18679() = g18679(any_undef_global::Union{Int, Tuple{}})
function h18679()
for i = 1:2
local a
if i == 1
a = ((),)
else
@isdefined(a) && return "BAD"
end
end
end

function g19348(x)
a, b = x
return a + b
g = 1
g = 2
c = Base.indexed_next(x, g, g)
return a + b + c[1]
end

for codetype in Any[
@code_typed(f18679()),
@code_typed(g18679()),
@code_typed(h18679()),
@code_typed(g19348((1, 2.0)))]
# make sure none of the slottypes are left as Core.Inference.Const objects
code = codetype[1]
@test all(x->isa(x, Type), code.slottypes)
local notconst(@nospecialize(other)) = true
notconst(slot::TypedSlot) = @test isa(slot.typ, Type)
function notconst(expr::Expr)
@test isa(expr.typ, Type)
for a in expr.args
notconst(a)
end
end
for e in code.code
notconst(e)
end
test_inferred_static(code)
end
test_inferred_static(@code_typed g19348((1, 2.0)))
@test f18679() === ()
@test_throws UndefVarError(:any_undef_global) g18679()
@test h18679() === nothing


# issue #5575
f5575() = zeros(Type[Float64][1], 1)
Expand Down

0 comments on commit ff706aa

Please sign in to comment.