Skip to content

Commit

Permalink
transform InterConditional in abstract_call
Browse files Browse the repository at this point in the history
  • Loading branch information
aviatesk committed Dec 18, 2020
1 parent 4e39251 commit b13fbcc
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 24 deletions.
48 changes: 29 additions & 19 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1033,9 +1033,35 @@ function abstract_call(interp::AbstractInterpreter, fargs::Union{Nothing,Vector{
add_remark!(interp, sv, "Could not identify method table for call")
return CallMeta(Any, false)
end
return abstract_call_gf_by_type(interp, nothing, argtypes, argtypes_to_type(argtypes), sv, max_methods)
callinfo = abstract_call_gf_by_type(interp, nothing, argtypes, argtypes_to_type(argtypes), sv, max_methods)
return callinfo_from_interprocedural(callinfo, fargs)
end
callinfo = abstract_call_known(interp, f, fargs, argtypes, sv, max_methods)
return callinfo_from_interprocedural(callinfo, fargs)
end

function callinfo_from_interprocedural(callinfo::CallMeta, ea::Union{Nothing,Vector{Any}})
if ea === nothing
return callinfo
end

rt = callinfo.rt
if isa(rt, InterConditional)
# try to convert interprocedural conditional constraint from callee into the constraint
# on slots of the current frame
i = rt.slot
if checkbounds(Bool, ea, i)
# `InterConditional` is supposed to be passed here only after "valid" `abstract_call`,
# and thus `i` should always be in bounds of `ea`, but just for safety
e = @inbounds ea[i]
if isa(e, Slot)
return CallMeta(Conditional(e, rt.vtype, rt.elsetype), callinfo.info)
end
end
return CallMeta(widenconditional(rt), callinfo.info)
else
return callinfo
end
return abstract_call_known(interp, f, fargs, argtypes, sv, max_methods)
end

function sp_type_rewrap(@nospecialize(T), linfo::MethodInstance, isreturn::Bool)
Expand Down Expand Up @@ -1144,10 +1170,7 @@ function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e),
end
callinfo = abstract_call(interp, ea, argtypes, sv)
sv.stmt_info[sv.currpc] = callinfo.info
rt = callinfo.rt
t = isa(rt, InterConditional) ?
transform_from_interconditional(rt, ea) :
rt
t = callinfo.rt
elseif e.head === :new
t = instanceof_tfunc(abstract_eval_value(interp, e.args[1], vtypes, sv))[1]
if isconcretetype(t) && !t.mutable
Expand Down Expand Up @@ -1258,19 +1281,6 @@ function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e),
return t
end

# try to convert interprocedural-conditional constraint from callee into constraints for
# the current frame
function transform_from_interconditional(rt::InterConditional, ea::Vector{Any})
i = rt.slot
if checkbounds(Bool, ea, i)
e = @inbounds ea[i]
if isa(e, Slot)
return Conditional(e, rt.vtype, rt.elsetype)
end
end
return widenconditional(rt)
end

function abstract_eval_global(M::Module, s::Symbol)
if isdefined(M,s) && isconst(M,s)
return Const(getfield(M,s))
Expand Down
5 changes: 1 addition & 4 deletions base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1648,10 +1648,7 @@ function return_type_tfunc(interp::AbstractInterpreter, argtypes::Vector{Any}, s
if contains_is(argtypes_vec, Union{})
return Const(Union{})
end
rt = abstract_call(interp, nothing, argtypes_vec, sv, -1).rt
if isa(rt, InterConditional)
rt = widenconditional(rt)
end
rt = widenconditional(abstract_call(interp, nothing, argtypes_vec, sv, -1).rt)
if isa(rt, Const)
# output was computed to be constant
return Const(typeof(rt.val))
Expand Down
2 changes: 1 addition & 1 deletion base/compiler/typeinfer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ function finish(me::InferenceState, interp::AbstractInterpreter)
nothing
end

bestguess_to_interprocedural(@nospecialize(bestguess), _) = bestguess
bestguess_to_interprocedural(@nospecialize(bestguess), _::Int) = bestguess
function bestguess_to_interprocedural(bestguess::Conditional, nargs::Int)
# keep `Conditional` return type only when it constrains any of call argument
i = slot_id(bestguess.var)
Expand Down

0 comments on commit b13fbcc

Please sign in to comment.