Skip to content

Commit 5abfc25

Browse files
committed
optimizer: fix #42840, the performance regression introduced by #42766
1 parent c054dbc commit 5abfc25

File tree

2 files changed

+31
-5
lines changed

2 files changed

+31
-5
lines changed

base/compiler/ssair/inlining.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,9 +1340,8 @@ function assemble_inline_todo!(ir::IRCode, state::InliningState)
13401340
ir, idx, stmt, info, sig,
13411341
state, flag, sig.f === Core.invoke, todo) && continue
13421342
end
1343-
else
1344-
info = info.call
13451343
end
1344+
info = info.call # cascade to the non-constant handling
13461345
end
13471346

13481347
if isa(info, OpaqueClosureCallInfo)

test/compiler/inline.jl

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ using Base.Experimental: @opaque
380380
f_oc_getfield(x) = (@opaque ()->x)()
381381
@test fully_eliminated(f_oc_getfield, Tuple{Int})
382382

383-
import Core.Compiler: argextype
383+
import Core.Compiler: argextype, singleton_type
384384
const EMPTY_SPTYPES = Core.Compiler.EMPTY_SLOTTYPES
385385

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

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

746746
import Base: @constprop
747747

748+
# test union-split callsite with successful and unsuccessful constant-prop' results
749+
@constprop :aggressive @inline f42840(xs, a::Int) = xs[a] # should be successful, and inlined
750+
@constprop :none @noinline f42840(xs::AbstractVector, a::Int) = xs[a] # should be unsuccessful, but still statically resolved
751+
let src = code_typed((Union{Tuple{Int,Int,Int}, Vector{Int}},)) do xs
752+
f42840(xs, 2)
753+
end |> only |> first
754+
@test count(src.code) do @nospecialize x
755+
iscall((src, getfield), x) # `(xs::Tuple{Int,Int,Int})[a::Const(2)]` => `getfield(xs, 2)`
756+
end == 1
757+
@test count(src.code) do @nospecialize x
758+
isinvoke(:f42840, x)
759+
end == 1
760+
end
761+
# a bit weird, but should handle this kind of case as well
762+
@constprop :aggressive @noinline g42840(xs, a::Int) = xs[a] # should be successful, but only statically resolved
763+
@constprop :none @inline g42840(xs::AbstractVector, a::Int) = xs[a] # should be unsuccessful, still inlined
764+
let src = code_typed((Union{Tuple{Int,Int,Int}, Vector{Int}},)) do xs
765+
g42840(xs, 2)
766+
end |> only |> first
767+
@test count(src.code) do @nospecialize x
768+
iscall((src, Base.arrayref), x) # `(xs::Vector{Int})[a::Const(2)]` => `Base.arrayref(true, xs, 2)`
769+
end == 1
770+
@test count(src.code) do @nospecialize x
771+
isinvoke(:g42840, x)
772+
end == 1
773+
end
774+
748775
# test single, non-dispatchtuple callsite inlining
749776

750777
@constprop :none @inline test_single_nondispatchtuple(@nospecialize(t)) =

0 commit comments

Comments
 (0)