Skip to content

Commit

Permalink
Inital addressing of review
Browse files Browse the repository at this point in the history
  • Loading branch information
Ian Atol committed Aug 31, 2022
1 parent 8dc5d87 commit bdd0d25
Show file tree
Hide file tree
Showing 9 changed files with 41 additions and 64 deletions.
20 changes: 14 additions & 6 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,8 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
f, this_arginfo, match, sv)
const_result = nothing
if const_call_result !== nothing
const_rt = const_call_result.rt
if const_rt rt
rt = const_rt
if const_call_result.rt rt
rt = const_call_result.rt
(; effects, const_result) = const_call_result
end
end
Expand Down Expand Up @@ -388,7 +387,7 @@ function collect_limitations!(@nospecialize(typ), sv::InferenceState)
end

function collect_limitations!(@nospecialize(typ), ::IRCode)
@assert !isa(typ, LimitedAccuracy)
@assert !isa(typ, LimitedAccuracy) "semi-concrete eval on recursive call graph"
return typ
end

Expand Down Expand Up @@ -813,8 +812,16 @@ function is_all_const_arg(argtypes::Vector{Any})
return true
end

collect_const_args((; argtypes)::ArgInfo) = collect_const_args(argtypes)
collect_const_args(arginfo::ArgInfo, start::Int=2) = collect_const_args(arginfo.argtypes, start)
function collect_const_args(argtypes::Vector{Any}, start::Int=2)
return Any[ let a = widenconditional(argtypes[i])
isa(a, Const) ? a.val :
isconstType(a) ? (a::DataType).parameters[1] :
(a::DataType).instance
end for i = 2:length(argtypes) ]
end

function collect_semi_const_args(argtypes::Vector{Any}, start::Int=2)
return Any[ let a = widenconditional(argtypes[i])
isa(a, Const) ? a.val :
isconstType(a) ? (a::DataType).parameters[1] :
Expand All @@ -823,6 +830,7 @@ function collect_const_args(argtypes::Vector{Any}, start::Int=2)
end for i in start:length(argtypes) ]
end


function invoke_signature(invokesig::Vector{Any})
ft, argtyps = widenconst(invokesig[2]), instanceof_tfunc(widenconst(invokesig[3]))[1]
return rewrap_unionall(Tuple{ft, unwrap_unionall(argtyps).parameters...}, argtyps)
Expand Down Expand Up @@ -886,7 +894,7 @@ function abstract_call_method_with_const_args(interp::AbstractInterpreter, resul
end
res = concrete_eval_call(interp, f, result, arginfo, sv)
if isa(res, ConstCallResults)
add_backedge!(result.edge, sv)
add_backedge!(res.const_result.mi, sv)
return res
end
mi = maybe_get_const_prop_profitable(interp, result, f, arginfo, match, sv)
Expand Down
5 changes: 1 addition & 4 deletions base/compiler/inferencestate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,7 @@ end

merge_effects!(interp::AbstractInterpreter, caller::InferenceState, callee::InferenceState) =
merge_effects!(interp, caller, Effects(callee))

function merge_effects!(interp::AbstractInterpreter, caller::IRCode, effects::Effects)
nothing
end
merge_effects!(interp::AbstractInterpreter, caller::IRCode, effects::Effects) = nothing

is_effect_overridden(sv::InferenceState, effect::Symbol) = is_effect_overridden(sv.linfo, effect)
function is_effect_overridden(linfo::MethodInstance, effect::Symbol)
Expand Down
12 changes: 5 additions & 7 deletions base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1137,7 +1137,7 @@ function inline_invoke!(
end
result = info.result
if isa(result, ConcreteResult)
item = const_result_item(result, state)
item = concrete_result_item(result, state)
else
invokesig = invoke_signature(sig.argtypes)
argtypes = invoke_rewrite(sig.argtypes)
Expand Down Expand Up @@ -1367,14 +1367,12 @@ function compute_inlining_cases(info::ConstCallInfo,
result = results[j]
any_fully_covered |= match.fully_covers
if isa(result, ConcreteResult)
case = const_result_item(result, state)
case = concrete_result_item(result, state)
push!(cases, InliningCase(result.mi.specTypes, case))
elseif isa(result, ConstPropResult)
handled_all_cases &= handle_const_prop_result!(result, argtypes, flag, state, cases, #=allow_abstract=#true)
elseif isa(result, InferenceResult)
handled_all_cases &= handle_inf_result!(result, argtypes, flag, state, cases, true)
elseif isa(result, SemiConcreteResult)
handled_all_cases &= handle_semi_concrete_result!(result, cases, true)
handled_all_cases &= handle_semi_concrete_result!(result, cases, #=allow_abstract=#true)
else
@assert result === nothing
handled_all_cases &= handle_match!(match, argtypes, flag, state, cases, #=allow_abstract=#true, #=allow_typevars=#false)
Expand Down Expand Up @@ -1447,7 +1445,7 @@ function handle_semi_concrete_result!(result::SemiConcreteResult, cases::Vector{
return true
end

function const_result_item(result::ConstResult, state::InliningState)
function concrete_result_item(result::ConcreteResult, state::InliningState)
if !isdefined(result, :result) || !is_inlineable_constant(result.result)
case = compileable_specialization(state.et, result.mi, result.effects)
@assert case !== nothing "concrete evaluation should never happen for uncompileable callsite"
Expand Down Expand Up @@ -1573,7 +1571,7 @@ function assemble_inline_todo!(ir::IRCode, state::InliningState)
sig, state, todo)
else
if isa(result, ConcreteResult)
item = const_result_item(result, state)
item = concrete_result_item(result, state)
else
item = analyze_method!(info.match, sig.argtypes, nothing, flag, state)
end
Expand Down
19 changes: 10 additions & 9 deletions base/compiler/ssair/irinterp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ function codeinst_to_ir(interp::AbstractInterpreter, code::CodeInstance)
mi = code.def

if isa(src, Vector{UInt8})
src = ccall(:jl_uncompress_ir, Any, (Any, Ptr{Cvoid}, Any), mi.def, C_NULL, src::Vector{UInt8})::CodeInfo
src = ccall(:jl_uncompress_ir, Any, (Any, Ptr{Cvoid}, Any), mi.def, C_NULL, src)::CodeInfo
end

isa(src, CodeInfo) || return src
Expand Down Expand Up @@ -111,7 +111,7 @@ function concrete_eval_invoke(interp::AbstractInterpreter, ir::IRCode, mi_cache,
argtypes = collect_argtypes(interp, inst.args[2:end], nothing, ir)
effects = decode_effects(code.ipo_purity_bits)
if is_foldable(effects) && is_all_const_arg(argtypes)
args = collect_const_args(argtypes, 1)
args = collect_semi_const_args(argtypes, 1)
world = get_world_counter(interp)
value = try
Core._call_in_world_total(world, args...)
Expand All @@ -137,8 +137,8 @@ function reprocess_instruction!(interp::AbstractInterpreter, ir::IRCode, mi::Met
mi_cache, sv::InferenceState,
tpdum::TwoPhaseDefUseMap, idx::Int, bb::Union{Int, Nothing},
@nospecialize(inst), @nospecialize(typ),
phi_revisit)
function update_phi!(from, to)
phi_revisit::BitSet)
function update_phi!(from::Int, to::Int)
if length(ir.cfg.blocks[to].preds) == 0
return
end
Expand Down Expand Up @@ -224,14 +224,14 @@ function reprocess_instruction!(interp::AbstractInterpreter, ir::IRCode, mi::Met
return false
end

function _ir_abstract_constant_propagation(interp::AbstractInterpreter, mi_cache, frame::InferenceState, mi::MethodInstance, ir, argtypes)
function _ir_abstract_constant_propagation(interp::AbstractInterpreter, mi_cache,
frame::InferenceState, mi::MethodInstance, ir::IRCode, argtypes::Vector{Any})
argtypes = va_process_argtypes(argtypes, mi)
argtypes_refined = Bool[!(ir.argtypes[i] argtypes[i]) for i = 1:length(argtypes)]
empty!(ir.argtypes)
append!(ir.argtypes, argtypes)
ssa_refined = BitSet()

ultimate_rt = Union{}
bbs = ir.cfg.blocks
ip = BitSetBoundedMinPrioritySet(length(bbs))
push!(ip, 1)
Expand All @@ -245,7 +245,7 @@ function _ir_abstract_constant_propagation(interp::AbstractInterpreter, mi_cache
Process the terminator and add the successor to `ip`. Returns whether a
backedge was seen.
"""
function process_terminator!(ip, bb, idx)
function process_terminator!(ip::BitSetBoundedMinPrioritySet, bb::Int, idx::Int)
inst = ir.stmts[idx][:inst]
if isa(inst, ReturnNode)
if isdefined(inst, :val)
Expand Down Expand Up @@ -378,14 +378,15 @@ function _ir_abstract_constant_propagation(interp::AbstractInterpreter, mi_cache
# Could have discovered this block is dead after the initial scan
continue
end
inst = ir.stmts[idx][:inst]
inst = ir.stmts[idx][:inst]::ReturnNode
rt = argextype(inst.val, ir)
ultimate_rt = tmerge(ultimate_rt, rt)
end
return ultimate_rt
end

function ir_abstract_constant_propagation(interp::AbstractInterpreter, mi_cache, frame::InferenceState, mi::MethodInstance, ir, argtypes)
function ir_abstract_constant_propagation(interp::AbstractInterpreter, mi_cache,
frame::InferenceState, mi::MethodInstance, ir::IRCode, argtypes::Vector{Any})
if __measure_typeinf__[]
inf_frame = Timings.InferenceFrameInfo(mi, frame.world, Any[], Any[], length(ir.argtypes))
Timings.enter_new_timer(inf_frame)
Expand Down
1 change: 1 addition & 0 deletions base/compiler/stmtinfo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ struct SemiConcreteResult
end

const ConstResult = Union{ConstPropResult,ConcreteResult, SemiConcreteResult}

"""
info::ConstCallInfo
Expand Down
2 changes: 1 addition & 1 deletion base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2020,7 +2020,7 @@ function builtin_nothrow(@nospecialize(f), argtypes::Vector{Any}, @nospecialize(
return _builtin_nothrow(f, argtypes, rt)
end

function builtin_tfunction(interp::AbstractInterpreter, @nospecialize(f), argtypes::Array{Any,1},
function builtin_tfunction(interp::AbstractInterpreter, @nospecialize(f), argtypes::Vector{Any},
sv::Union{InferenceState,IRCode,Nothing})
if f === tuple
return tuple_tfunc(argtypes)
Expand Down
10 changes: 6 additions & 4 deletions base/compiler/utilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,12 @@ function singleton_type(@nospecialize(ft))
end

function maybe_singleton_const(@nospecialize(t))
if isa(t, DataType) && isdefined(t, :instance)
return Const(t.instance)
elseif isconstType(t)
return Const(t.parameters[1])
if isa(t, DataType)
if isdefined(t, :instance)
return Const(t.instance)
elseif isconstType(t)
return Const(t.parameters[1])
end
end
return t
end
Expand Down
8 changes: 2 additions & 6 deletions base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -763,11 +763,6 @@ struct Colon <: Function
end
const (:) = Colon()

# TODO: Change lowering to do this automatically
@eval struct Val{x}
(T::Type{Val{x}} where x)() = $(Expr(:new, :T))
end


"""
Val(c)
Expand All @@ -789,7 +784,8 @@ julia> f(Val(true))
"Good"
```
"""
Val
struct Val{x}
end

Val(x) = Val{x}()

Expand Down
28 changes: 1 addition & 27 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4116,7 +4116,6 @@ end
f45780() = Val{Issue45780(@Base.Experimental.opaque ()->1).oc()}()
@test (@inferred f45780()) == Val{1}()


# issue #45600
@test only(code_typed() do
while true
Expand Down Expand Up @@ -4192,31 +4191,6 @@ end

# Test that Const ⊑ PartialStruct respects vararg
@test Const((1,2)) PartialStruct(Tuple{Vararg{Int}}, [Const(1), Vararg{Int}])
# backedge insertion for Any-typed, effect-free frame
const CONST_DICT = let d = Dict()
for c in 'A':'z'
push!(d, c => Int(c))
end
d
end
Base.@assume_effects :foldable getcharid(c) = CONST_DICT[c]
@noinline callf(f, args...) = f(args...)
function entry_to_be_invalidated(c)
return callf(getcharid, c)
end
@test Base.infer_effects((Char,)) do x
entry_to_be_invalidated(x)
end |> Core.Compiler.is_foldable
@test fully_eliminated(; retval=97) do
entry_to_be_invalidated('a')
end
getcharid(c) = CONST_DICT[c] # now this is not eligible for concrete evaluation
@test Base.infer_effects((Char,)) do x
entry_to_be_invalidated(x)
end |> !Core.Compiler.is_foldable
@test !fully_eliminated() do
entry_to_be_invalidated('a')
end

# Test that semi-concrete interpretation doesn't break on functions with while loops in them.
@Base.assume_effects :consistent :effect_free :terminates_globally function pure_annotated_loop(x::Int, y::Int)
Expand All @@ -4226,4 +4200,4 @@ end
return y
end
call_pure_annotated_loop(x) = Val{pure_annotated_loop(x, 1)}()
@test Core.Compiler.return_type(call_pure_annotated_loop, Tuple{Int}) == Val{1}
@test only(Base.return_types(call_pure_annotated_loop, Tuple{Int})) === Val{1}

0 comments on commit bdd0d25

Please sign in to comment.