Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optimizer: fix #42840, the performance regression introduced by #42766 #42841

Merged
merged 1 commit into from
Oct 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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