Skip to content

Commit

Permalink
optimizer: fix JuliaLang#42840, the performance regression introduced…
Browse files Browse the repository at this point in the history
  • Loading branch information
aviatesk authored and LilithHafner committed Mar 8, 2022
1 parent 03e5379 commit e5af603
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 5 deletions.
3 changes: 1 addition & 2 deletions base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1340,9 +1340,8 @@ function assemble_inline_todo!(ir::IRCode, state::InliningState)
ir, idx, stmt, info, sig,
state, flag, sig.f === Core.invoke, todo) && continue
end
else
info = info.call
end
info = info.call # cascade to the non-constant handling
end

if isa(info, OpaqueClosureCallInfo)
Expand Down
33 changes: 30 additions & 3 deletions test/compiler/inline.jl
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ using Base.Experimental: @opaque
f_oc_getfield(x) = (@opaque ()->x)()
@test fully_eliminated(f_oc_getfield, Tuple{Int})

import Core.Compiler: argextype
import Core.Compiler: argextype, singleton_type
const EMPTY_SPTYPES = Core.Compiler.EMPTY_SLOTTYPES

code_typed1(args...; kwargs...) = first(only(code_typed(args...; kwargs...)))::Core.CodeInfo
Expand All @@ -389,7 +389,7 @@ get_code(args...; kwargs...) = code_typed1(args...; kwargs...).code
# check if `x` is a dynamic call of a given function
function iscall((src, f)::Tuple{Core.CodeInfo,Function}, @nospecialize(x))
return iscall(x) do @nospecialize x
argextype(x, src, EMPTY_SPTYPES) === typeof(f)
singleton_type(argextype(x, src, EMPTY_SPTYPES)) === f
end
end
iscall(pred, @nospecialize(x)) = Meta.isexpr(x, :call) && pred(x.args[1])
Expand Down Expand Up @@ -724,7 +724,7 @@ let f(x) = (x...,)
end

# https://github.com/JuliaLang/julia/issues/42754
# inline union-split constant-prop'ed sources
# inline union-split constant-prop'ed results
mutable struct X42754
# NOTE in order to confuse `fieldtype_tfunc`, we need to have at least two fields with different types
a::Union{Nothing, Int}
Expand All @@ -745,6 +745,33 @@ end

import Base: @constprop

# test union-split callsite with successful and unsuccessful constant-prop' results
@constprop :aggressive @inline f42840(xs, a::Int) = xs[a] # should be successful, and inlined
@constprop :none @noinline f42840(xs::AbstractVector, a::Int) = xs[a] # should be unsuccessful, but still statically resolved
let src = code_typed((Union{Tuple{Int,Int,Int}, Vector{Int}},)) do xs
f42840(xs, 2)
end |> only |> first
@test count(src.code) do @nospecialize x
iscall((src, getfield), x) # `(xs::Tuple{Int,Int,Int})[a::Const(2)]` => `getfield(xs, 2)`
end == 1
@test count(src.code) do @nospecialize x
isinvoke(:f42840, x)
end == 1
end
# a bit weird, but should handle this kind of case as well
@constprop :aggressive @noinline g42840(xs, a::Int) = xs[a] # should be successful, but only statically resolved
@constprop :none @inline g42840(xs::AbstractVector, a::Int) = xs[a] # should be unsuccessful, still inlined
let src = code_typed((Union{Tuple{Int,Int,Int}, Vector{Int}},)) do xs
g42840(xs, 2)
end |> only |> first
@test count(src.code) do @nospecialize x
iscall((src, Base.arrayref), x) # `(xs::Vector{Int})[a::Const(2)]` => `Base.arrayref(true, xs, 2)`
end == 1
@test count(src.code) do @nospecialize x
isinvoke(:g42840, x)
end == 1
end

# test single, non-dispatchtuple callsite inlining

@constprop :none @inline test_single_nondispatchtuple(@nospecialize(t)) =
Expand Down

0 comments on commit e5af603

Please sign in to comment.