@@ -380,15 +380,23 @@ using Base.Experimental: @opaque
380380f_oc_getfield (x) = (@opaque ()-> x)()
381381@test fully_eliminated (f_oc_getfield, Tuple{Int})
382382
383- # check if `x` is a statically-resolved call of a function whose name is `sym`
384- isinvoke (@nospecialize (x), sym:: Symbol ) = isinvoke (x, mi-> mi. def. name=== sym)
385- function isinvoke (@nospecialize (x), pred)
386- if Meta. isexpr (x, :invoke )
387- return pred (x. args[1 ]:: Core.MethodInstance )
383+ import Core. Compiler: argextype
384+ const EMPTY_SPTYPES = Core. Compiler. EMPTY_SLOTTYPES
385+
386+ code_typed1 (args... ; kwargs... ) = first (only (code_typed (args... ; kwargs... ))):: Core.CodeInfo
387+ get_code (args... ; kwargs... ) = code_typed1 (args... ; kwargs... ). code
388+
389+ # check if `x` is a dynamic call of a given function
390+ function iscall ((src, f):: Tuple{Core.CodeInfo,Function} , @nospecialize (x))
391+ return iscall (x) do @nospecialize x
392+ argextype (x, src, EMPTY_SPTYPES) === typeof (f)
388393 end
389- return false
390394end
391- code_typed1 (args... ; kwargs... ) = (first (only (code_typed (args... ; kwargs... ))):: Core.CodeInfo ). code
395+ iscall (pred, @nospecialize (x)) = Meta. isexpr (x, :call ) && pred (x. args[1 ])
396+
397+ # check if `x` is a statically-resolved call of a function whose name is `sym`
398+ isinvoke (sym:: Symbol , @nospecialize (x)) = isinvoke (mi-> mi. def. name=== sym, x)
399+ isinvoke (pred, @nospecialize (x)) = Meta. isexpr (x, :invoke ) && pred (x. args[1 ]:: Core.MethodInstance )
392400
393401@testset " @inline/@noinline annotation before definition" begin
394402 M = Module ()
@@ -413,25 +421,25 @@ code_typed1(args...; kwargs...) = (first(only(code_typed(args...; kwargs...)))::
413421 def_noinline_noconflict (x) = _def_noinline_noconflict (x)
414422 end
415423
416- let code = code_typed1 (M. def_inline, (Int,))
417- @test all (code) do x
418- ! isinvoke (x, :_def_inline )
424+ let code = get_code (M. def_inline, (Int,))
425+ @test all (code) do @nospecialize x
426+ ! isinvoke (:_def_inline , x )
419427 end
420428 end
421- let code = code_typed1 (M. def_noinline, (Int,))
422- @test any (code) do x
423- isinvoke (x, :_def_noinline )
429+ let code = get_code (M. def_noinline, (Int,))
430+ @test any (code) do @nospecialize x
431+ isinvoke (:_def_noinline , x )
424432 end
425433 end
426434 # test that they don't conflict with other "before-definition" macros
427- let code = code_typed1 (M. def_inline_noconflict, (Int,))
428- @test all (code) do x
429- ! isinvoke (x, :_def_inline_noconflict )
435+ let code = get_code (M. def_inline_noconflict, (Int,))
436+ @test all (code) do @nospecialize x
437+ ! isinvoke (:_def_inline_noconflict , x )
430438 end
431439 end
432- let code = code_typed1 (M. def_noinline_noconflict, (Int,))
433- @test any (code) do x
434- isinvoke (x, :_def_noinline_noconflict )
440+ let code = get_code (M. def_noinline_noconflict, (Int,))
441+ @test any (code) do @nospecialize x
442+ isinvoke (:_def_noinline_noconflict , x )
435443 end
436444 end
437445end
@@ -470,29 +478,33 @@ end
470478 end
471479 end
472480
473- let code = code_typed1 (M. body_inline, (Int,))
474- @test all (code) do x
475- ! isinvoke (x, :_body_inline )
481+ let code = get_code (M. body_inline, (Int,))
482+ @test all (code) do @nospecialize x
483+ ! isinvoke (:_body_inline , x )
476484 end
477485 end
478- let code = code_typed1 (M. body_noinline, (Int,))
479- @test any (code) do x
480- isinvoke (x, :_body_noinline )
486+ let code = get_code (M. body_noinline, (Int,))
487+ @test any (code) do @nospecialize x
488+ isinvoke (:_body_noinline , x )
481489 end
482490 end
483491 # test annotations for `do` blocks
484- let code = code_typed1 (M. do_inline, (Int,))
492+ let code = get_code (M. do_inline, (Int,))
485493 # what we test here is that both `simple_caller` and the anonymous function that the
486494 # `do` block creates should inlined away, and as a result there is only the unresolved call
487- @test all (code) do x
488- ! isinvoke (x, :simple_caller ) &&
489- ! isinvoke (x, mi-> startswith (string (mi. def. name), ' #' ))
495+ @test all (code) do @nospecialize x
496+ ! isinvoke (:simple_caller , x) &&
497+ ! isinvoke (x) do mi
498+ startswith (string (mi. def. name), ' #' )
499+ end
490500 end
491501 end
492- let code = code_typed1 (M. do_noinline, (Int,))
502+ let code = get_code (M. do_noinline, (Int,))
493503 # the anonymous function that the `do` block created shouldn't be inlined here
494- @test any (code) do x
495- isinvoke (x, mi-> startswith (string (mi. def. name), ' #' ))
504+ @test any (code) do @nospecialize x
505+ isinvoke (x) do mi
506+ startswith (string (mi. def. name), ' #' )
507+ end
496508 end
497509 end
498510end
@@ -520,14 +532,14 @@ end
520532 # test callsite annotations for constant-prop'ed calls
521533
522534 @noinline Base. @constprop :aggressive noinlined_constprop_explicit (a) = a+ g
523- force_inline_constprop_explicit () = @inline noinlined_constprop_explicit (0 )
535+ force_inline_constprop_explicit () = @inline noinlined_constprop_explicit (0 )
524536 Base. @constprop :aggressive noinlined_constprop_implicit (a) = a+ g
525- force_inline_constprop_implicit () = @inline noinlined_constprop_implicit (0 )
537+ force_inline_constprop_implicit () = @inline noinlined_constprop_implicit (0 )
526538
527539 @inline Base. @constprop :aggressive inlined_constprop_explicit (a) = a+ g
528- force_noinline_constprop_explicit () = @noinline inlined_constprop_explicit (0 )
540+ force_noinline_constprop_explicit () = @noinline inlined_constprop_explicit (0 )
529541 @inline Base. @constprop :aggressive inlined_constprop_implicit (a) = a+ g
530- force_noinline_constprop_implicit () = @noinline inlined_constprop_implicit (0 )
542+ force_noinline_constprop_implicit () = @noinline inlined_constprop_implicit (0 )
531543
532544 @noinline notinlined (a) = a
533545 function nested (a0, b0)
@@ -539,51 +551,75 @@ end
539551 end
540552 end
541553
542- let code = code_typed1 (M. force_inline_explicit, (Int,))
543- @test all (x-> ! isinvoke (x, :noinlined_explicit ), code)
554+ let code = get_code (M. force_inline_explicit, (Int,))
555+ @test all (code) do @nospecialize x
556+ ! isinvoke (:noinlined_explicit , x)
557+ end
544558 end
545- let code = code_typed1 (M. force_inline_block_explicit, (Int,))
546- @test all (code) do x
547- ! isinvoke (x, :noinlined_explicit ) &&
548- ! isinvoke (x, :(+ ))
559+ let code = get_code (M. force_inline_block_explicit, (Int,))
560+ @test all (code) do @nospecialize x
561+ ! isinvoke (:noinlined_explicit , x ) &&
562+ ! isinvoke (:(+ ), x )
549563 end
550564 end
551- let code = code_typed1 (M. force_inline_implicit, (Int,))
552- @test all (x-> ! isinvoke (x, :noinlined_implicit ), code)
565+ let code = get_code (M. force_inline_implicit, (Int,))
566+ @test all (code) do @nospecialize x
567+ ! isinvoke (:noinlined_implicit , x)
568+ end
553569 end
554- let code = code_typed1 (M. force_inline_block_implicit, (Int,))
555- @test all (x-> ! isinvoke (x, :noinlined_explicit ), code)
570+ let code = get_code (M. force_inline_block_implicit, (Int,))
571+ @test all (code) do @nospecialize x
572+ ! isinvoke (:noinlined_explicit , x)
573+ end
556574 end
557575
558- let code = code_typed1 (M. force_noinline_explicit, (Int,))
559- @test any (x-> isinvoke (x, :inlined_explicit ), code)
576+ let code = get_code (M. force_noinline_explicit, (Int,))
577+ @test any (code) do @nospecialize x
578+ isinvoke (:inlined_explicit , x)
579+ end
560580 end
561- let code = code_typed1 (M. force_noinline_block_explicit, (Int,))
562- @test count (x-> isinvoke (x, :inlined_explicit ), code) == 2
581+ let code = get_code (M. force_noinline_block_explicit, (Int,))
582+ @test count (code) do @nospecialize x
583+ isinvoke (:inlined_explicit , x)
584+ end == 2
563585 end
564- let code = code_typed1 (M. force_noinline_implicit, (Int,))
565- @test any (x-> isinvoke (x, :inlined_implicit ), code)
586+ let code = get_code (M. force_noinline_implicit, (Int,))
587+ @test any (code) do @nospecialize x
588+ isinvoke (:inlined_implicit , x)
589+ end
566590 end
567- let code = code_typed1 (M. force_noinline_block_implicit, (Int,))
568- @test count (x-> isinvoke (x, :inlined_implicit ), code) == 2
591+ let code = get_code (M. force_noinline_block_implicit, (Int,))
592+ @test count (code) do @nospecialize x
593+ isinvoke (:inlined_implicit , x)
594+ end == 2
569595 end
570596
571- let code = code_typed1 (M. force_inline_constprop_explicit)
572- @test all (x-> ! isinvoke (x, :noinlined_constprop_explicit ), code)
597+ let code = get_code (M. force_inline_constprop_explicit)
598+ @test all (code) do @nospecialize x
599+ ! isinvoke (:noinlined_constprop_explicit , x)
600+ end
573601 end
574- let code = code_typed1 (M. force_inline_constprop_implicit)
575- @test all (x-> ! isinvoke (x, :noinlined_constprop_implicit ), code)
602+ let code = get_code (M. force_inline_constprop_implicit)
603+ @test all (code) do @nospecialize x
604+ ! isinvoke (:noinlined_constprop_implicit , x)
605+ end
576606 end
577607
578- let code = code_typed1 (M. force_noinline_constprop_explicit)
579- @test any (x-> isinvoke (x, :inlined_constprop_explicit ), code)
608+ let code = get_code (M. force_noinline_constprop_explicit)
609+ @test any (code) do @nospecialize x
610+ isinvoke (:inlined_constprop_explicit , x)
611+ end
580612 end
581- let code = code_typed1 (M. force_noinline_constprop_implicit)
582- @test any (x-> isinvoke (x, :inlined_constprop_implicit ), code)
613+ let code = get_code (M. force_noinline_constprop_implicit)
614+ @test any (code) do @nospecialize x
615+ isinvoke (:inlined_constprop_implicit , x)
616+ end
583617 end
584618
585- let code = code_typed1 (M. nested, (Int,Int))
586- @test count (x-> isinvoke (x, :notinlined ), code) == 1
619+ let code = get_code (M. nested, (Int,Int))
620+ @test count (code) do @nospecialize x
621+ isinvoke (:notinlined , x)
622+ end == 1
587623 end
588624end
589625
@@ -604,10 +640,12 @@ let code = @eval Module() begin
604640 end
605641 end
606642
607- $ code_typed1 (setter, (Vector{Foo},))
643+ $ get_code (setter, (Vector{Foo},))
608644 end
609645
610- @test ! any (x-> isinvoke (x, :setproperty! ), code)
646+ @test ! any (code) do @nospecialize x
647+ isinvoke (:setproperty! , x)
648+ end
611649end
612650
613651# Issue #41299 - inlining deletes error check in :>
@@ -624,10 +662,12 @@ end
624662@noinline f42078 (a) = sum (sincos (a))
625663let
626664 ninlined = let
627- code = code_typed1 ((Int,)) do a
665+ code = get_code ((Int,)) do a
628666 @inline f42078 (a)
629667 end
630- @test all (x-> ! isinvoke (x, :f42078 ), code)
668+ @test all (code) do @nospecialize x
669+ ! isinvoke (:f42078 , x)
670+ end
631671 length (code)
632672 end
633673
@@ -643,10 +683,12 @@ let
643683 end
644684
645685 let # inference should re-infer `f42078(::Int)` and we should get the same code
646- code = code_typed1 ((Int,)) do a
686+ code = get_code ((Int,)) do a
647687 @inline f42078 (a)
648688 end
649- @test all (x-> ! isinvoke (x, :f42078 ), code)
689+ @test all (code) do @nospecialize x
690+ ! isinvoke (:f42078 , x)
691+ end
650692 @test ninlined == length (code)
651693 end
652694end
@@ -688,21 +730,16 @@ mutable struct X42754
688730 a:: Union{Nothing, Int}
689731 b:: Symbol
690732end
691- let code = code_typed1 ((X42754, Union{Nothing,Int})) do x, a
733+ let src = code_typed1 ((X42754, Union{Nothing,Int})) do x, a
692734 # this `setproperty` call would be union-split and constant-prop will happen for
693735 # each signature: inlining would fail if we don't use constant-prop'ed source
694736 # since the approximate inlining cost of `convert(fieldtype(X, sym), a)` would
695737 # end up very high if we don't propagate `sym::Const(:a)`
696738 x. a = a
697739 x
698740 end
699- @test all (code) do @nospecialize (x)
700- isinvoke (x, :setproperty! ) && return false
701- if Meta. isexpr (x, :call )
702- f = x. args[1 ]
703- isa (f, GlobalRef) && f. name === :setproperty! && return false
704- end
705- return true
741+ @test all (src. code) do @nospecialize x
742+ ! (isinvoke (:setproperty! , x) || iscall ((src, setproperty!), x))
706743 end
707744end
708745
@@ -713,32 +750,22 @@ import Base: @constprop
713750@constprop :none @inline test_single_nondispatchtuple (@nospecialize (t)) =
714751 isa (t, DataType) && t. name === Type. body. name
715752let
716- code = code_typed1 ((Any,)) do x
753+ src = code_typed1 ((Any,)) do x
717754 test_single_nondispatchtuple (x)
718755 end
719- @test all (code) do @nospecialize (x)
720- isinvoke (x, :test_single_nondispatchtuple ) && return false
721- if Meta. isexpr (x, :call )
722- f = x. args[1 ]
723- isa (f, GlobalRef) && f. name === :test_single_nondispatchtuple && return false
724- end
725- return true
756+ @test all (src. code) do @nospecialize x
757+ ! (isinvoke (:test_single_nondispatchtuple , x) || iscall ((src, test_single_nondispatchtuple), x))
726758 end
727759end
728760
729761@constprop :aggressive @inline test_single_nondispatchtuple (c, @nospecialize (t)) =
730762 c && isa (t, DataType) && t. name === Type. body. name
731763let
732- code = code_typed1 ((Any,)) do x
764+ src = code_typed1 ((Any,)) do x
733765 test_single_nondispatchtuple (true , x)
734766 end
735- @test all (code) do @nospecialize (x)
736- isinvoke (x, :test_single_nondispatchtuple ) && return false
737- if Meta. isexpr (x, :call )
738- f = x. args[1 ]
739- isa (f, GlobalRef) && f. name === :test_single_nondispatchtuple && return false
740- end
741- return true
767+ @test all (src. code) do @nospecialize (x)
768+ ! (isinvoke (:test_single_nondispatchtuple , x) || iscall ((src, test_single_nondispatchtuple), x))
742769 end
743770end
744771
0 commit comments