28
28
29
29
struct ConstantCase
30
30
val:: Any
31
- ConstantCase (@nospecialize val) = new (val)
31
+ edge:: CodeInstance
32
+ ConstantCase (@nospecialize (val), edge:: CodeInstance ) = new (val, edge)
32
33
end
33
34
34
35
struct SomeCase
@@ -68,12 +69,12 @@ struct InliningEdgeTracker
68
69
new (state. edges, invokesig)
69
70
end
70
71
71
- function add_inlining_edge! (et:: InliningEdgeTracker , mi :: MethodInstance )
72
+ function add_inlining_edge! (et:: InliningEdgeTracker , edge :: CodeInstance )
72
73
(; edges, invokesig) = et
73
74
if invokesig === nothing
74
- add_one_edge! (edges, mi )
75
+ add_one_edge! (edges, edge )
75
76
else # invoke backedge
76
- add_invoke_edge! (edges, invoke_signature (invokesig), mi )
77
+ add_invoke_edge! (edges, invoke_signature (invokesig), edge )
77
78
end
78
79
return nothing
79
80
end
@@ -784,11 +785,11 @@ function rewrite_apply_exprargs!(todo::Vector{Pair{Int,Any}},
784
785
return new_argtypes
785
786
end
786
787
787
- function compileable_specialization (mi :: MethodInstance , effects:: Effects ,
788
- et:: InliningEdgeTracker , @nospecialize (info:: CallInfo ); compilesig_invokes :: Bool = true )
789
- mi_invoke = mi
788
+ function compileable_specialization (edge :: CodeInstance , effects:: Effects ,
789
+ et:: InliningEdgeTracker , @nospecialize (info:: CallInfo ), state :: InliningState )
790
+ mi_invoke = mi = edge . def
790
791
method, atype, sparams = mi. def:: Method , mi. specTypes, mi. sparam_vals
791
- if compilesig_invokes
792
+ if OptimizationParams (state . interp) . compilesig_invokes
792
793
new_atype = get_compileable_sig (method, atype, sparams)
793
794
new_atype === nothing && return nothing
794
795
if atype != = new_atype
@@ -806,43 +807,42 @@ function compileable_specialization(mi::MethodInstance, effects::Effects,
806
807
return nothing
807
808
end
808
809
end
809
- add_inlining_edge! (et, mi) # to the dispatch lookup
810
- mi_invoke != = mi && add_invoke_edge! (et. edges, method. sig, mi_invoke) # add_inlining_edge to the invoke call, if that is different
810
+ add_inlining_edge! (et, edge) # to the dispatch lookup
811
+ if mi_invoke != = mi
812
+ edge_invoke = codeinst_as_invoke_edge (state. interp, mi_invoke)
813
+ add_invoke_edge! (et. edges, method. sig, edge_invoke) # add_inlining_edge to the invoke call, if that is different
814
+ end
811
815
return InvokeCase (mi_invoke, effects, info)
812
816
end
813
817
814
- function compileable_specialization (match:: MethodMatch , effects:: Effects ,
815
- et:: InliningEdgeTracker , @nospecialize (info:: CallInfo ); compilesig_invokes:: Bool = true )
816
- mi = specialize_method (match)
817
- return compileable_specialization (mi, effects, et, info; compilesig_invokes)
818
- end
819
-
820
818
struct InferredResult
821
819
src:: Any # CodeInfo or IRCode
822
820
effects:: Effects
823
- InferredResult (@nospecialize (src), effects:: Effects ) = new (src, effects)
821
+ edge:: CodeInstance
822
+ InferredResult (@nospecialize (src), effects:: Effects , edge:: CodeInstance ) = new (src, effects, edge)
824
823
end
825
824
@inline function get_cached_result (state:: InliningState , mi:: MethodInstance )
826
825
code = get (code_cache (state), mi, nothing )
827
826
if code isa CodeInstance
828
827
if use_const_api (code)
829
828
# in this case function can be inlined to a constant
830
- return ConstantCase (quoted (code. rettype_const))
829
+ return ConstantCase (quoted (code. rettype_const), code )
831
830
end
832
831
return code
833
832
end
834
833
return nothing
835
834
end
836
835
@inline function get_local_result (inf_result:: InferenceResult )
836
+ @assert isdefined (inf_result, :ci_as_edge ) " InferenceResult without ci_as_edge"
837
837
effects = inf_result. ipo_effects
838
838
if is_foldable_nothrow (effects)
839
839
res = inf_result. result
840
840
if isa (res, Const) && is_inlineable_constant (res. val)
841
841
# use constant calling convention
842
- return ConstantCase (quoted (res. val))
842
+ return ConstantCase (quoted (res. val), inf_result . ci_as_edge )
843
843
end
844
844
end
845
- return InferredResult (inf_result. src, effects)
845
+ return InferredResult (inf_result. src, effects, inf_result . ci_as_edge )
846
846
end
847
847
848
848
# the general resolver for usual and const-prop'ed calls
@@ -862,30 +862,29 @@ function resolve_todo(mi::MethodInstance, result::Union{Nothing,InferenceResult,
862
862
inferred_result = get_cached_result (state, mi)
863
863
end
864
864
if inferred_result isa ConstantCase
865
- add_inlining_edge! (et, mi )
865
+ add_inlining_edge! (et, inferred_result . edge )
866
866
return inferred_result
867
867
elseif inferred_result isa InferredResult
868
- (; src, effects) = inferred_result
868
+ (; src, effects, edge ) = inferred_result
869
869
elseif inferred_result isa CodeInstance
870
870
src = @atomic :monotonic inferred_result. inferred
871
871
effects = decode_effects (inferred_result. ipo_purity_bits)
872
+ edge = inferred_result
872
873
else # there is no cached source available, bail out
873
- return compileable_specialization (mi, Effects (), et, info;
874
- compilesig_invokes = OptimizationParams ( state. interp) . compilesig_invokes )
874
+ edge = codeinst_as_invoke_edge (state . interp, mi)
875
+ return compileable_specialization (edge, Effects (), et, info, state)
875
876
end
876
877
877
878
# the duplicated check might have been done already within `analyze_method!`, but still
878
879
# we need it here too since we may come here directly using a constant-prop' result
879
880
if ! OptimizationParams (state. interp). inlining || is_stmt_noinline (flag)
880
- return compileable_specialization (mi, effects, et, info;
881
- compilesig_invokes= OptimizationParams (state. interp). compilesig_invokes)
881
+ return compileable_specialization (edge, effects, et, info, state)
882
882
end
883
883
884
884
src_inlining_policy (state. interp, src, info, flag) ||
885
- return compileable_specialization (mi, effects, et, info;
886
- compilesig_invokes= OptimizationParams (state. interp). compilesig_invokes)
885
+ return compileable_specialization (edge, effects, et, info, state)
887
886
888
- add_inlining_edge! (et, mi )
887
+ add_inlining_edge! (et, edge )
889
888
if inferred_result isa CodeInstance
890
889
ir, spec_info, debuginfo = retrieve_ir_for_inlining (inferred_result, src)
891
890
else
@@ -905,7 +904,7 @@ function resolve_todo(mi::MethodInstance, @nospecialize(info::CallInfo), flag::U
905
904
906
905
cached_result = get_cached_result (state, mi)
907
906
if cached_result isa ConstantCase
908
- add_inlining_edge! (et, mi )
907
+ add_inlining_edge! (et, cached_result . edge )
909
908
return cached_result
910
909
elseif cached_result isa CodeInstance
911
910
src = @atomic :monotonic cached_result. inferred
@@ -916,7 +915,7 @@ function resolve_todo(mi::MethodInstance, @nospecialize(info::CallInfo), flag::U
916
915
917
916
src_inlining_policy (state. interp, src, info, flag) || return nothing
918
917
ir, spec_info, debuginfo = retrieve_ir_for_inlining (cached_result, src)
919
- add_inlining_edge! (et, mi )
918
+ add_inlining_edge! (et, cached_result )
920
919
return InliningTodo (mi, ir, spec_info, debuginfo, effects)
921
920
end
922
921
@@ -1464,14 +1463,12 @@ function semiconcrete_result_item(result::SemiConcreteResult,
1464
1463
# a `@noinline`-declared method when it's marked as `@constprop :aggressive`.
1465
1464
# Suppress the inlining here (unless inlining is requested at the callsite).
1466
1465
(is_declared_noinline (mi. def:: Method ) && ! is_stmt_inline (flag)))
1467
- return compileable_specialization (mi, result. effects, et, info;
1468
- compilesig_invokes= OptimizationParams (state. interp). compilesig_invokes)
1466
+ return compileable_specialization (result. edge, result. effects, et, info, state)
1469
1467
end
1470
1468
src_inlining_policy (state. interp, result. ir, info, flag) ||
1471
- return compileable_specialization (mi, result. effects, et, info;
1472
- compilesig_invokes= OptimizationParams (state. interp). compilesig_invokes)
1469
+ return compileable_specialization (result. edge, result. effects, et, info, state)
1473
1470
1474
- add_inlining_edge! (et, mi )
1471
+ add_inlining_edge! (et, result . edge )
1475
1472
preserve_local_sources = OptimizationParams (state. interp). preserve_local_sources
1476
1473
ir, _, debuginfo = retrieve_ir_for_inlining (mi, result. ir, preserve_local_sources)
1477
1474
return InliningTodo (mi, ir, result. spec_info, debuginfo, result. effects)
@@ -1503,11 +1500,10 @@ function concrete_result_item(result::ConcreteResult, @nospecialize(info::CallIn
1503
1500
invokesig:: Union{Nothing,Vector{Any}} = nothing )
1504
1501
if ! may_inline_concrete_result (result)
1505
1502
et = InliningEdgeTracker (state, invokesig)
1506
- return compileable_specialization (result. edge. def, result. effects, et, info;
1507
- compilesig_invokes= OptimizationParams (state. interp). compilesig_invokes)
1503
+ return compileable_specialization (result. edge, result. effects, et, info, state)
1508
1504
end
1509
1505
@assert result. effects === EFFECTS_TOTAL
1510
- return ConstantCase (quoted (result. result))
1506
+ return ConstantCase (quoted (result. result), result . edge )
1511
1507
end
1512
1508
1513
1509
function handle_cases! (todo:: Vector{Pair{Int,Any}} , ir:: IRCode , idx:: Int , stmt:: Expr ,
@@ -1556,11 +1552,14 @@ function handle_modifyop!_call!(ir::IRCode, idx::Int, stmt::Expr, info::ModifyOp
1556
1552
info isa MethodResultPure && (info = info. info)
1557
1553
info isa ConstCallInfo && (info = info. call)
1558
1554
info isa MethodMatchInfo || return nothing
1559
- length (info. results) == 1 || return nothing
1555
+ length (info. edges) == length (info . results) == 1 || return nothing
1560
1556
match = info. results[1 ]:: MethodMatch
1561
1557
match. fully_covers || return nothing
1562
- case = compileable_specialization (match, Effects (), InliningEdgeTracker (state), info;
1563
- compilesig_invokes= OptimizationParams (state. interp). compilesig_invokes)
1558
+ edge = info. edges[1 ]
1559
+ if edge === nothing
1560
+ edge = codeinst_as_invoke_edge (state. interp, specialize_method (match))
1561
+ end
1562
+ case = compileable_specialization (edge, Effects (), InliningEdgeTracker (state), info, state)
1564
1563
case === nothing && return nothing
1565
1564
stmt. head = :invoke_modify
1566
1565
pushfirst! (stmt. args, case. invoke)
0 commit comments