Skip to content

Commit 83bd616

Browse files
committed
optimizer: fix #42840, the performance regression introduced by #42766 (#42841)
1 parent 901a3a5 commit 83bd616

File tree

2 files changed

+44
-9
lines changed

2 files changed

+44
-9
lines changed

base/compiler/ssair/inlining.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1392,7 +1392,7 @@ function assemble_inline_todo!(ir::IRCode, state::InliningState)
13921392
ir, idx, stmt, info, sig,
13931393
state, sig.f === Core.invoke, todo) && continue
13941394
end
1395-
info = info.call
1395+
info = info.call # cascade to the non-constant handling
13961396
end
13971397

13981398
if isa(info, OpaqueClosureCallInfo)

test/compiler/inline.jl

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -393,18 +393,26 @@ let f(x) = (x...,)
393393
@test code_typed(f, Tuple{Union{Int64, CartesianIndex{1}, CartesianIndex{3}}})[1][2] == Tuple{Int64}
394394
end
395395

396-
# check if `x` is a statically-resolved call of a function whose name is `sym`
397-
isinvoke(@nospecialize(x), sym::Symbol) = isinvoke(x, mi->mi.def.name===sym)
398-
function isinvoke(@nospecialize(x), pred)
399-
if Meta.isexpr(x, :invoke)
400-
return pred(x.args[1]::Core.MethodInstance)
396+
import Core.Compiler: argextype, singleton_type
397+
const EMPTY_SPTYPES = Core.Compiler.EMPTY_SLOTTYPES
398+
399+
code_typed1(args...; kwargs...) = first(only(code_typed(args...; kwargs...)))::Core.CodeInfo
400+
get_code(args...; kwargs...) = code_typed1(args...; kwargs...).code
401+
402+
# check if `x` is a dynamic call of a given function
403+
function iscall((src, f)::Tuple{Core.CodeInfo,Function}, @nospecialize(x))
404+
return iscall(x) do @nospecialize x
405+
singleton_type(argextype(x, src, EMPTY_SPTYPES)) === f
401406
end
402-
return false
403407
end
404-
code_typed1(args...; kwargs...) = (first(only(code_typed(args...; kwargs...)))::Core.CodeInfo).code
408+
iscall(pred, @nospecialize(x)) = Meta.isexpr(x, :call) && pred(x.args[1])
409+
410+
# check if `x` is a statically-resolved call of a function whose name is `sym`
411+
isinvoke(sym::Symbol, @nospecialize(x)) = isinvoke(mi->mi.def.name===sym, x)
412+
isinvoke(pred, @nospecialize(x)) = Meta.isexpr(x, :invoke) && pred(x.args[1]::Core.MethodInstance)
405413

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

431439
import Base: @constprop
432440

441+
# test union-split callsite with successful and unsuccessful constant-prop' results
442+
@constprop :aggressive @inline f42840(xs, a::Int) = xs[a] # should be successful, and inlined
443+
@constprop :none @noinline f42840(xs::AbstractVector, a::Int) = xs[a] # should be unsuccessful, but still statically resolved
444+
let src = code_typed((Union{Tuple{Int,Int,Int}, Vector{Int}},)) do xs
445+
f42840(xs, 2)
446+
end |> only |> first
447+
@test count(src.code) do @nospecialize x
448+
iscall((src, getfield), x) # `(xs::Tuple{Int,Int,Int})[a::Const(2)]` => `getfield(xs, 2)`
449+
end == 1
450+
@test count(src.code) do @nospecialize x
451+
isinvoke(:f42840, x)
452+
end == 1
453+
end
454+
# a bit weird, but should handle this kind of case as well
455+
@constprop :aggressive @noinline g42840(xs, a::Int) = xs[a] # should be successful, but only statically resolved
456+
@constprop :none @inline g42840(xs::AbstractVector, a::Int) = xs[a] # should be unsuccessful, still inlined
457+
let src = code_typed((Union{Tuple{Int,Int,Int}, Vector{Int}},)) do xs
458+
g42840(xs, 2)
459+
end |> only |> first
460+
@test count(src.code) do @nospecialize x
461+
iscall((src, Base.arrayref), x) # `(xs::Vector{Int})[a::Const(2)]` => `Base.arrayref(true, xs, 2)`
462+
end == 1
463+
@test count(src.code) do @nospecialize x
464+
isinvoke(:g42840, x)
465+
end == 1
466+
end
467+
433468
# test single, non-dispatchtuple callsite inlining
434469

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

0 commit comments

Comments
 (0)