@@ -393,24 +393,31 @@ 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
+
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
401
405
end
402
- return false
403
406
end
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 )
405
412
406
413
# https://github.com/JuliaLang/julia/issues/42754
407
- # inline union-split constant-prop'ed sources
414
+ # inline union-split constant-prop'ed results
408
415
mutable struct X42754
409
416
# NOTE in order to confuse `fieldtype_tfunc`, we need to have at least two fields with different types
410
417
a:: Union{Nothing, Int}
411
418
b:: Symbol
412
419
end
413
- let code = code_typed1 ((X42754, Union{Nothing,Int})) do x, a
420
+ let code = get_code ((X42754, Union{Nothing,Int})) do x, a
414
421
# this `setproperty` call would be union-split and constant-prop will happen for
415
422
# each signature: inlining would fail if we don't use constant-prop'ed source
416
423
# since the approximate inlining cost of `convert(fieldtype(X, sym), a)` would
@@ -430,12 +437,39 @@ end
430
437
431
438
import Base: @constprop
432
439
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
+
433
467
# test single, non-dispatchtuple callsite inlining
434
468
435
469
@constprop :none @inline test_single_nondispatchtuple (@nospecialize (t)) =
436
470
isa (t, DataType) && t. name === Type. body. name
437
471
let
438
- code = code_typed1 ((Any,)) do x
472
+ code = get_code ((Any,)) do x
439
473
test_single_nondispatchtuple (x)
440
474
end
441
475
@test all (code) do @nospecialize (x)
451
485
@constprop :aggressive @inline test_single_nondispatchtuple (c, @nospecialize (t)) =
452
486
c && isa (t, DataType) && t. name === Type. body. name
453
487
let
454
- code = code_typed1 ((Any,)) do x
488
+ code = get_code ((Any,)) do x
455
489
test_single_nondispatchtuple (true , x)
456
490
end
457
491
@test all (code) do @nospecialize (x)
@@ -481,7 +515,7 @@ let m = Module()
481
515
end
482
516
end
483
517
484
- $ code_typed1 (setter, (Vector{Foo},))
518
+ $ get_code (setter, (Vector{Foo},))
485
519
end
486
520
487
521
@test ! any (x-> isinvoke (x, :setproperty! ), code)
0 commit comments