Skip to content

Commit

Permalink
inference: continue const-prop' when concrete-eval returns non-inline…
Browse files Browse the repository at this point in the history
…able

This commit fixes the regression in the following example:
```julia
julia> stritr() = iterate(("1", '2'), 1);

julia> @time stritr();
  0.000001 seconds (2 allocations: 64 bytes) # on master
  0.000000 seconds                           # on 1.9
```

The problem is that currently we don't inline result of concrete-eval
when its result is not inlineable, although const-prop' or semi-concrete
eval may be able to optimize and inline the method body.
To improve the situation, this commit simply allows
`abstract_call_method_with_const_args` to continue to semi-concrete
eval and const-prop' when concrete-eval returned non-inlineable result.
  • Loading branch information
aviatesk committed Aug 1, 2023
1 parent 7b587ac commit 143d463
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 3 deletions.
11 changes: 8 additions & 3 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -785,11 +785,16 @@ function abstract_call_method_with_const_args(interp::AbstractInterpreter,
return nothing
end
eligibility = concrete_eval_eligible(interp, f, result, arginfo, sv)
concrete_eval_result = nothing
if eligibility === :concrete_eval
return concrete_eval_call(interp, f, result, arginfo, sv; invokecall)
concrete_eval_result = concrete_eval_call(interp, f, result, arginfo, sv, invokecall)
if !may_optimize(interp) || may_inline_concrete_result(concrete_eval_result.const_result::ConcreteResult)
return concrete_eval_result
end
# give semi-concrete-eval or const-prop' a chance to inline a better method body
end
mi = maybe_get_const_prop_profitable(interp, result, f, arginfo, si, match, sv)
mi === nothing && return nothing
mi === nothing && return concrete_eval_result
if is_constprop_recursed(result, mi, sv)
add_remark!(interp, sv, "[constprop] Edge cycle encountered")
return nothing
Expand Down Expand Up @@ -881,7 +886,7 @@ function collect_const_args(argtypes::Vector{Any}, start::Int)
end

function concrete_eval_call(interp::AbstractInterpreter,
@nospecialize(f), result::MethodCallResult, arginfo::ArgInfo, sv::AbsIntState;
@nospecialize(f), result::MethodCallResult, arginfo::ArgInfo, sv::AbsIntState,
invokecall::Union{InvokeCall,Nothing}=nothing)
args = collect_const_args(arginfo, #=start=#2)
if invokecall !== nothing
Expand Down
14 changes: 14 additions & 0 deletions test/compiler/inline.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2065,3 +2065,17 @@ end
# https://github.com/JuliaLang/julia/issues/50612
f50612(x) = UInt32(x)
@test all(!isinvoke(:UInt32),get_code(f50612,Tuple{Char}))

# continue const-prop' when concrete-eval result is too big
const THE_BIG_TUPLE_2 = ntuple(identity, 1024)
return_the_big_tuple2(a) = (a, THE_BIG_TUPLE_2)
let src = code_typed1() do
return return_the_big_tuple2(42)[2]
end
@test count(isinvoke(:return_the_big_tuple2), src.code) == 0
end
let src = code_typed1() do
return iterate(("1", '2'), 1)
end
@test count(isinvoke(:iterate), src.code) == 0
end

0 comments on commit 143d463

Please sign in to comment.