diff --git a/Compiler/src/optimize.jl b/Compiler/src/optimize.jl index 27fb1e2168639..f71e770a77d34 100644 --- a/Compiler/src/optimize.jl +++ b/Compiler/src/optimize.jl @@ -1472,8 +1472,9 @@ function statement_or_branch_cost(@nospecialize(stmt), line::Int, src::Union{Cod return thiscost end -function inline_cost_model(ir::IRCode, params::OptimizationParams, cost_threshold::Int) +function inline_cost_model(mi::MethodInstance, ir::IRCode, params::OptimizationParams, cost_threshold::Int) bodycost = 0 + uses_sparams = false for i = 1:length(ir.stmts) stmt = ir[SSAValue(i)][:stmt] thiscost = statement_or_branch_cost(stmt, i, ir, ir.sptypes, params) @@ -1481,6 +1482,12 @@ function inline_cost_model(ir::IRCode, params::OptimizationParams, cost_threshol if bodycost > cost_threshold return MAX_INLINE_COST end + uses_sparams |= isexpr(stmt, :static_parameter) + end + if uses_sparams && !validate_sparams(mi.sparam_vals) + # Inlining this would require the use of `_compute_sparams`, + # which is a bit too expensive to reasonably inline. + return MAX_INLINE_COST end return inline_cost_clamp(bodycost) end diff --git a/Compiler/src/typeinfer.jl b/Compiler/src/typeinfer.jl index 9849d22a9ce67..9d80da2f010da 100644 --- a/Compiler/src/typeinfer.jl +++ b/Compiler/src/typeinfer.jl @@ -396,7 +396,7 @@ function inline_cost_model(interp::AbstractInterpreter, result::InferenceResult, cost_threshold += 4*default end end - return inline_cost_model(ir, params, cost_threshold) + return inline_cost_model(mi, ir, params, cost_threshold) end end diff --git a/Compiler/test/inline.jl b/Compiler/test/inline.jl index 0a88907965f5a..83497382eb7b8 100644 --- a/Compiler/test/inline.jl +++ b/Compiler/test/inline.jl @@ -1332,7 +1332,7 @@ mutable struct DoAllocNoEscapeSparam{T} finalizer(finalizer_sparam, new{T}(x)) end end -let src = code_typed1(Tuple{Any}) do x +let src = code_typed1(Tuple{Int}) do x for i = 1:1000 DoAllocNoEscapeSparam(x) end @@ -1341,8 +1341,7 @@ let src = code_typed1(Tuple{Any}) do x nnothrow_invokes = count(isinvoke(:nothrow_side_effect), src.code) @test count(iscall(f->!isa(singleton_type(argextype(f, src)), Core.Builtin)), src.code) == count(iscall((src, nothrow_side_effect)), src.code) == 2 - nnothrow_invokes - # TODO: Our effect modeling is not yet strong enough to fully eliminate this - @test_broken count(isnew, src.code) == 0 + @test count(isnew, src.code) == 0 end # Test finalizer varargs @@ -2314,4 +2313,40 @@ let src = code_typed1(g_noinline_invoke, (Union{Symbol,Nothing},)) @test !any(@nospecialize(x)->isa(x,GlobalRef), src.code) end +# https://github.com/JuliaLang/julia/issues/58915 +f58915(nt) = @inline Base.setindex(nt, 2, :next) +# This function should fully-inline, i.e. it should have only built-in / intrinsic calls +# and no invokes or dynamic calls of user code +let src = code_typed1(f58915, Tuple{@NamedTuple{next::UInt32,prev::UInt32}}) + # Any calls should be built-in calls + @test count(iscall(f->!isa(singleton_type(argextype(f, src)), Core.Builtin)), src.code) == 0 + # There should be no invoke at all + @test count(isinvoke(Returns(true)), src.code) == 0 +end + +# https://github.com/JuliaLang/julia/issues/58915#issuecomment-3061421895 +let src = code_typed1(Base.setindex, (@NamedTuple{next::UInt32,prev::UInt32}, Int, Symbol)) + @test count(isinvoke(:merge_fallback), src.code) == 0 + @test count(iscall((src, Base.merge_fallback)), src.code) == 0 +end + +# https://github.com/JuliaLang/julia/pull/58996#issuecomment-3073496955 +f58996(::Int) = :int +f58996(::String) = :string +call_f58996(x) = f58996(x) +callcall_f58996(x) = call_f58996(x); +let src = code_typed1(callcall_f58996, (Any,)) + # Any calls should be built-in calls + @test count(iscall(f->!isa(singleton_type(argextype(f, src)), Core.Builtin)), src.code) == 0 + # There should be no invoke at all + @test count(isinvoke(Returns(true)), src.code) == 0 +end + +f59013_using_sparams(::T) where {T} = T +f59013(x) = f59013_using_sparams(x) +let src = code_typed1(f59013, (Any,)) + @test length(src.code) == 2 + @test iscall((src, f59013_using_sparams), src.code[1]) +end + end # module inline_tests