Skip to content

Commit

Permalink
Re-tighten Inference information for Const boolean converted to Condi…
Browse files Browse the repository at this point in the history
…tional

fix #26417
fix #26339
  • Loading branch information
vtjnash committed Jul 9, 2018
1 parent 86be87e commit 068bf3d
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 17 deletions.
56 changes: 41 additions & 15 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -532,13 +532,16 @@ function abstract_call(@nospecialize(f), fargs::Union{Tuple{},Vector{Any}}, argt

if isa(f, Builtin) || isa(f, IntrinsicFunction)
if f === ifelse && fargs isa Vector{Any} && length(argtypes) == 4 && argtypes[2] isa Conditional
cnd = argtypes[2]
# try to simulate this as a real conditional (`cnd ? x : y`), so that the penalty for using `ifelse` instead isn't too high
cnd = argtypes[2]::Conditional
tx = argtypes[3]
ty = argtypes[4]
if isa(fargs[3], Slot) && slot_id(cnd.var) == slot_id(fargs[3])
a = ssa_def_expr(fargs[3], sv)
b = ssa_def_expr(fargs[4], sv)
if isa(a, Slot) && slot_id(cnd.var) == slot_id(a)
tx = typeintersect(tx, cnd.vtype)
end
if isa(fargs[4], Slot) && slot_id(cnd.var) == slot_id(fargs[4])
if isa(b, Slot) && slot_id(cnd.var) == slot_id(b)
ty = typeintersect(ty, cnd.elsetype)
end
return tmerge(tx, ty)
Expand All @@ -556,18 +559,20 @@ function abstract_call(@nospecialize(f), fargs::Union{Tuple{},Vector{Any}}, argt
a = ssa_def_expr(fargs[2], sv)
if isa(a, Slot)
aty = widenconst(argtypes[2])
if rt === Const(false)
return Conditional(a, Union{}, aty)
elseif rt === Const(true)
return Conditional(a, aty, Union{})
end
tty_ub, isexact_tty = instanceof_tfunc(argtypes[3])
if isexact_tty && !isa(tty_ub, TypeVar)
tty_lb = tty_ub # TODO: this would be wrong if !isexact_tty, but instanceof_tfunc doesn't preserve this info
if !has_free_typevars(tty_lb) && !has_free_typevars(tty_ub)
ifty = typeintersect(aty, tty_ub)
elsety = typesubtract(aty, tty_lb)
if ifty != elsety
return Conditional(a, ifty, elsety)
end
elty = typesubtract(aty, tty_lb)
return Conditional(a, ifty, elty)
end
end
return Bool
end
elseif f === (===)
a = ssa_def_expr(fargs[2], sv)
Expand All @@ -576,21 +581,42 @@ function abstract_call(@nospecialize(f), fargs::Union{Tuple{},Vector{Any}}, argt
bty = argtypes[3]
# if doing a comparison to a singleton, consider returning a `Conditional` instead
if isa(aty, Const) && isa(b, Slot)
if isdefined(typeof(aty.val), :instance) # can only widen a if it is a singleton
return Conditional(b, aty, typesubtract(widenconst(bty), typeof(aty.val)))
if rt === Const(false)
aty = Union{}
elseif rt === Const(true)
bty = Union{}
elseif bty isa Type && isdefined(typeof(aty.val), :instance) # can only widen a if it is a singleton
bty = typesubtract(bty, typeof(aty.val))
end
return isa(rt, Const) ? rt : Conditional(b, aty, bty)
return Conditional(b, aty, bty)
end
if isa(bty, Const) && isa(a, Slot)
if isdefined(typeof(bty.val), :instance) # same for b
return Conditional(a, bty, typesubtract(widenconst(aty), typeof(bty.val)))
if rt === Const(false)
bty = Union{}
elseif rt === Const(true)
aty = Union{}
elseif aty isa Type && isdefined(typeof(bty.val), :instance) # same for b
aty = typesubtract(aty, typeof(bty.val))
end
return isa(rt, Const) ? rt : Conditional(a, bty, aty)
return Conditional(a, bty, aty)
end
if isa(b, Slot)
return Conditional(b, bty, bty)
end
if isa(a, Slot)
return Conditional(a, aty, aty)
end
elseif f === Core.Compiler.not_int
aty = argtypes[2]
if isa(aty, Conditional)
return Conditional(aty.var, aty.elsetype, aty.vtype)
ifty = aty.elsetype
elty = aty.vtype
if rt === Const(false)
ifty = Union{}
elseif rt === Const(true)
elty = Union{}
end
return Conditional(aty.var, ifty, elty)
end
end
end
Expand Down
2 changes: 0 additions & 2 deletions base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,6 @@ function assemble_inline_todo!(ir::IRCode, linetable::Vector{LineInfoNode}, sv::

ft = argextype(arg1, ir, sv.sp)
has_free_typevars(ft) && continue
isa(ft, Conditional) && (ft = Bool)
f = singleton_type(ft)
# TODO: llvmcall can contain other calls as arguments, so this code doesn't work on it
f === Core.Intrinsics.llvmcall && continue
Expand Down Expand Up @@ -786,7 +785,6 @@ function assemble_inline_todo!(ir::IRCode, linetable::Vector{LineInfoNode}, sv::
new_atypes = Any[]
ft = argextype(stmt.args[2], ir, sv.sp)
has_free_typevars(ft) && continue
isa(ft, Conditional) && (ft = Bool)
f = singleton_type(ft)
# Push function type
push!(new_atypes, ft)
Expand Down
4 changes: 4 additions & 0 deletions base/compiler/typelimits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,10 @@ function tmerge(@nospecialize(typea), @nospecialize(typeb))
return Conditional(typea.var, vtype, elsetype)
end
end
val = maybe_extract_const_bool(typea)
if val isa Bool && val === maybe_extract_const_bool(typeb)
return Const(val)
end
return Bool
end
# no special type-inference lattice, join the types
Expand Down
13 changes: 13 additions & 0 deletions test/compiler/compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1468,6 +1468,19 @@ result = f24852_kernel(x, y)
# TODO: test that `expand_early = true` + inflated `method_for_inference_limit_heuristics`
# can be used to tighten up some inference result.

f26339(T) = T === Union{} ? 1 : ""
g26339(T) = T === Int ? 1 : ""
@test Base.return_types(f26339, (Int,)) == Any[String]
@test Base.return_types(g26339, (Int,)) == Any[String]
@test Base.return_types(f26339, (Type{Int},)) == Any[String]
@test Base.return_types(g26339, (Type{Int},)) == Any[Int]
@test Base.return_types(f26339, (Type{Union{}},)) == Any[Int]
@test Base.return_types(g26339, (Type{Union{}},)) == Any[String]
@test Base.return_types(f26339, (typeof(Union{}),)) == Any[Int]
@test Base.return_types(g26339, (typeof(Union{}),)) == Any[String]
@test Base.return_types(f26339, (Type,)) == Any[Union{Int, String}]
@test Base.return_types(g26339, (Type,)) == Any[Union{Int, String}]

# Test that Conditional doesn't get widened to Bool too quickly
f25261() = (1, 1)
f25261(s) = i == 1 ? (1, 2) : nothing
Expand Down

0 comments on commit 068bf3d

Please sign in to comment.