Skip to content

Commit f48f2e7

Browse files
committed
optimizer: clean up inlining test code
1 parent 16eb196 commit f48f2e7

File tree

1 file changed

+121
-94
lines changed

1 file changed

+121
-94
lines changed

test/compiler/inline.jl

Lines changed: 121 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -380,15 +380,23 @@ using Base.Experimental: @opaque
380380
f_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
390394
end
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
437445
end
@@ -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
498510
end
@@ -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
588624
end
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
611649
end
612650

613651
# Issue #41299 - inlining deletes error check in :>
@@ -624,10 +662,12 @@ end
624662
@noinline f42078(a) = sum(sincos(a))
625663
let
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
652694
end
@@ -688,21 +730,16 @@ mutable struct X42754
688730
a::Union{Nothing, Int}
689731
b::Symbol
690732
end
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
707744
end
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
715752
let
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
727759
end
728760

729761
@constprop :aggressive @inline test_single_nondispatchtuple(c, @nospecialize(t)) =
730762
c && isa(t, DataType) && t.name === Type.body.name
731763
let
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
743770
end
744771

0 commit comments

Comments
 (0)