From 2646e3be02623461cf48e52f7ed5626d3230f557 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki Date: Fri, 21 Jul 2023 17:18:50 +0900 Subject: [PATCH] inference: continue const-prop' when concrete-eval returns non-inlineable 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. --- base/compiler/abstractinterpretation.jl | 9 +++++++-- test/compiler/inline.jl | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index ed41b43ff95d9..3df9da2b42bfa 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -791,11 +791,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 diff --git a/test/compiler/inline.jl b/test/compiler/inline.jl index 3bc7ab5ccbc82..8be3e0241224f 100644 --- a/test/compiler/inline.jl +++ b/test/compiler/inline.jl @@ -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