Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d7ca737

Browse files
Kenoantoine-levitt
authored andcommittedMay 9, 2021
AbstractInterpreter: Add a hook to opt into more extensive stmt info (JuliaLang#39716)
I'm in the process of updating Cthulhu to make use of an AbstractInterpreter instead of using raw inference queries. Over time Cthulhu has grown many heuristics for trying to reverse engineer what inference did in order to present this to the user. Of course, these heuristics are incomplete and worse, we do already mostly have this information neatly packaged in the stmt_info field, since optimization needs the same information. Switching Cthulhu to an AbstractInterpreter gives it access to this info (as well as allowing it to maintain its own caches, fixing various weirdness around statement order dependence with the base inference caches). However, there are a few places in inference where we drop stmt info that Cthulhu would like to read because the optimizer doesn't need it. This adds a hook for Cthulhu (and other tooling that would like to receive it) to get more verbose stmt info out of inference. My end goal here is to turn Cthulhu entirely into a viewer for inference data structures, and not have it contain any heuristics that duplicate inference functionality. I think we're pretty close to that, but a few tweaks are required. Hopefully the end result should be a much more functional and precise Cthulhu (as well as being easier to maintain, since we get to delete half the code).
1 parent 018c96e commit d7ca737

File tree

4 files changed

+23
-14
lines changed

4 files changed

+23
-14
lines changed
 

‎base/compiler/abstractinterpretation.jl

+1-5
Original file line numberDiff line numberDiff line change
@@ -1007,11 +1007,7 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
10071007
elseif f === Tuple && la == 2 && !isconcretetype(widenconst(argtypes[2]))
10081008
return CallMeta(Tuple, false)
10091009
elseif is_return_type(f)
1010-
rt_rt = return_type_tfunc(interp, argtypes, sv)
1011-
if rt_rt !== nothing
1012-
return CallMeta(rt_rt, nothing)
1013-
end
1014-
return CallMeta(Type, nothing)
1010+
return return_type_tfunc(interp, argtypes, sv)
10151011
elseif la == 2 && istopfunction(f, :!)
10161012
# handle Conditional propagation through !Bool
10171013
aty = argtypes[2]

‎base/compiler/stmtinfo.jl

+10
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,13 @@ This info is illegal on any statement that is not an `_apply_iterate` call.
8181
struct UnionSplitApplyCallInfo
8282
infos::Vector{ApplyCallInfo}
8383
end
84+
85+
# Stmt infos that are used by external consumers, but not by optimization.
86+
# These are not produced by default and must be explicitly opted into by
87+
# the AbstractInterpreter.
88+
89+
struct ReturnTypeCallInfo
90+
# The info corresponding to the call that return_type was supposed to
91+
# analyze.
92+
info::Any
93+
end

‎base/compiler/tfuncs.jl

+11-9
Original file line numberDiff line numberDiff line change
@@ -1642,37 +1642,39 @@ function return_type_tfunc(interp::AbstractInterpreter, argtypes::Vector{Any}, s
16421642
if isa(af_argtype, DataType) && af_argtype <: Tuple
16431643
argtypes_vec = Any[aft, af_argtype.parameters...]
16441644
if contains_is(argtypes_vec, Union{})
1645-
return Const(Union{})
1645+
return CallMeta(Const(Union{}), nothing)
16461646
end
1647-
rt = widenconditional(abstract_call(interp, nothing, argtypes_vec, sv, -1).rt)
1647+
call = abstract_call(interp, nothing, argtypes_vec, sv, -1)
1648+
info = verbose_stmt_info(interp) ? ReturnTypeCallInfo(call.info) : nothing
1649+
rt = widenconditional(call.rt)
16481650
if isa(rt, Const)
16491651
# output was computed to be constant
1650-
return Const(typeof(rt.val))
1652+
return CallMeta(Const(typeof(rt.val)), info)
16511653
end
16521654
rt = widenconst(rt)
16531655
if rt === Bottom || (isconcretetype(rt) && !iskindtype(rt))
16541656
# output cannot be improved so it is known for certain
1655-
return Const(rt)
1657+
return CallMeta(Const(rt), info)
16561658
elseif !isempty(sv.pclimitations)
16571659
# conservatively express uncertainty of this result
16581660
# in two ways: both as being a subtype of this, and
16591661
# because of LimitedAccuracy causes
1660-
return Type{<:rt}
1662+
return CallMeta(Type{<:rt}, info)
16611663
elseif (isa(tt, Const) || isconstType(tt)) &&
16621664
(isa(aft, Const) || isconstType(aft))
16631665
# input arguments were known for certain
16641666
# XXX: this doesn't imply we know anything about rt
1665-
return Const(rt)
1667+
return CallMeta(Const(rt), info)
16661668
elseif isType(rt)
1667-
return Type{rt}
1669+
return CallMeta(Type{rt}, info)
16681670
else
1669-
return Type{<:rt}
1671+
return CallMeta(Type{<:rt}, info)
16701672
end
16711673
end
16721674
end
16731675
end
16741676
end
1675-
return nothing
1677+
return CallMeta(Type, nothing)
16761678
end
16771679

16781680
# N.B.: typename maps type equivalence classes to a single value

‎base/compiler/types.jl

+1
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ add_remark!(ni::NativeInterpreter, sv, s) = nothing
210210
may_optimize(ni::NativeInterpreter) = true
211211
may_compress(ni::NativeInterpreter) = true
212212
may_discard_trees(ni::NativeInterpreter) = true
213+
verbose_stmt_info(ni::NativeInterpreter) = false
213214

214215
method_table(ai::AbstractInterpreter) = InternalMethodTable(get_world_counter(ai))
215216

0 commit comments

Comments
 (0)
Please sign in to comment.