@@ -393,24 +393,31 @@ let f(x) = (x...,)
393393 @test code_typed (f, Tuple{Union{Int64, CartesianIndex{1 }, CartesianIndex{3 }}})[1 ][2 ] == Tuple{Int64}
394394end
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+
398+ code_typed1 (args... ; kwargs... ) = first (only (code_typed (args... ; kwargs... ))):: Core.CodeInfo
399+ get_code (args... ; kwargs... ) = code_typed1 (args... ; kwargs... ). code
400+
401+ # check if `x` is a dynamic call of a given function
402+ function iscall ((src, f):: Tuple{Core.CodeInfo,Function} , @nospecialize (x))
403+ return iscall (x) do @nospecialize x
404+ singleton_type (argextype (x, src, Any[])) === f
401405 end
402- return false
403406end
404- code_typed1 (args... ; kwargs... ) = (first (only (code_typed (args... ; kwargs... ))):: Core.CodeInfo ). code
407+ iscall (pred, @nospecialize (x)) = Meta. isexpr (x, :call ) && pred (x. args[1 ])
408+
409+ # check if `x` is a statically-resolved call of a function whose name is `sym`
410+ isinvoke (sym:: Symbol , @nospecialize (x)) = isinvoke (mi-> mi. def. name=== sym, x)
411+ isinvoke (pred, @nospecialize (x)) = Meta. isexpr (x, :invoke ) && pred (x. args[1 ]:: Core.MethodInstance )
405412
406413# https://github.com/JuliaLang/julia/issues/42754
407- # inline union-split constant-prop'ed sources
414+ # inline union-split constant-prop'ed results
408415mutable struct X42754
409416 # NOTE in order to confuse `fieldtype_tfunc`, we need to have at least two fields with different types
410417 a:: Union{Nothing, Int}
411418 b:: Symbol
412419end
413- let code = code_typed1 ((X42754, Union{Nothing,Int})) do x, a
420+ let code = get_code ((X42754, Union{Nothing,Int})) do x, a
414421 # this `setproperty` call would be union-split and constant-prop will happen for
415422 # each signature: inlining would fail if we don't use constant-prop'ed source
416423 # since the approximate inlining cost of `convert(fieldtype(X, sym), a)` would
@@ -430,12 +437,39 @@ end
430437
431438import Base: @constprop
432439
440+ # test union-split callsite with successful and unsuccessful constant-prop' results
441+ @constprop :aggressive @inline f42840 (xs, a:: Int ) = xs[a] # should be successful, and inlined
442+ @constprop :none @noinline f42840 (xs:: AbstractVector , a:: Int ) = xs[a] # should be unsuccessful, but still statically resolved
443+ let src = code_typed1 ((Union{Tuple{Int,Int,Int}, Vector{Int}},)) do xs
444+ f42840 (xs, 2 )
445+ end
446+ @test count (src. code) do @nospecialize x
447+ iscall ((src, getfield), x) # `(xs::Tuple{Int,Int,Int})[a::Const(2)]` => `getfield(xs, 2)`
448+ end == 1
449+ @test count (src. code) do @nospecialize x
450+ isinvoke (:f42840 , x)
451+ end == 1
452+ end
453+ # a bit weird, but should handle this kind of case as well
454+ @constprop :aggressive @noinline g42840 (xs, a:: Int ) = xs[a] # should be successful, but only statically resolved
455+ @constprop :none @inline g42840 (xs:: AbstractVector , a:: Int ) = xs[a] # should be unsuccessful, still inlined
456+ let src = code_typed1 ((Union{Tuple{Int,Int,Int}, Vector{Int}},)) do xs
457+ g42840 (xs, 2 )
458+ end
459+ @test count (src. code) do @nospecialize x
460+ iscall ((src, Base. arrayref), x) # `(xs::Vector{Int})[a::Const(2)]` => `Base.arrayref(true, xs, 2)`
461+ end == 1
462+ @test count (src. code) do @nospecialize x
463+ isinvoke (:g42840 , x)
464+ end == 1
465+ end
466+
433467# test single, non-dispatchtuple callsite inlining
434468
435469@constprop :none @inline test_single_nondispatchtuple (@nospecialize (t)) =
436470 isa (t, DataType) && t. name === Type. body. name
437471let
438- code = code_typed1 ((Any,)) do x
472+ code = get_code ((Any,)) do x
439473 test_single_nondispatchtuple (x)
440474 end
441475 @test all (code) do @nospecialize (x)
451485@constprop :aggressive @inline test_single_nondispatchtuple (c, @nospecialize (t)) =
452486 c && isa (t, DataType) && t. name === Type. body. name
453487let
454- code = code_typed1 ((Any,)) do x
488+ code = get_code ((Any,)) do x
455489 test_single_nondispatchtuple (true , x)
456490 end
457491 @test all (code) do @nospecialize (x)
@@ -481,7 +515,7 @@ let m = Module()
481515 end
482516 end
483517
484- $ code_typed1 (setter, (Vector{Foo},))
518+ $ get_code (setter, (Vector{Foo},))
485519 end
486520
487521 @test ! any (x-> isinvoke (x, :setproperty! ), code)
0 commit comments