@@ -393,18 +393,26 @@ let f(x) = (x...,)
393
393
@test code_typed (f, Tuple{Union{Int64, CartesianIndex{1 }, CartesianIndex{3 }}})[1 ][2 ] == Tuple{Int64}
394
394
end
395
395
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
401
406
end
402
- return false
403
407
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 )
405
413
406
414
# https://github.com/JuliaLang/julia/issues/42754
407
- # inline union-split constant-prop'ed sources
415
+ # inline union-split constant-prop'ed results
408
416
mutable struct X42754
409
417
# NOTE in order to confuse `fieldtype_tfunc`, we need to have at least two fields with different types
410
418
a:: Union{Nothing, Int}
430
438
431
439
import Base: @constprop
432
440
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
+
433
468
# test single, non-dispatchtuple callsite inlining
434
469
435
470
@constprop :none @inline test_single_nondispatchtuple (@nospecialize (t)) =
0 commit comments