@@ -308,21 +308,17 @@ function finish_cfg_inline!(state::CFGInliningState)
308308 end
309309end
310310
311- function ir_inline_item! (compact:: IncrementalCompact , idx:: Int , argexprs:: Vector{Any} ,
312- linetable:: Vector{LineInfoNode} , item:: InliningTodo ,
313- boundscheck:: Symbol , todo_bbs:: Vector{Tuple{Int, Int}} )
314- # Ok, do the inlining here
315- spec = item. spec:: ResolvedInliningSpec
316- sparam_vals = item. mi. sparam_vals
317- def = item. mi. def:: Method
311+ function ir_inline_linetable! (linetable:: Vector{LineInfoNode} , inlinee_ir:: IRCode ,
312+ inlinee:: Method ,
313+ inlined_at:: Int32 )
314+ coverage = coverage_enabled (inlinee. module)
318315 linetable_offset:: Int32 = length (linetable)
319316 # Append the linetable of the inlined function to our line table
320- inlined_at = compact. result[idx][:line ]
321317 topline:: Int32 = linetable_offset + Int32 (1 )
322- coverage = coverage_enabled (def. module)
323318 coverage_by_path = JLOptions (). code_coverage == 3
324- push! (linetable, LineInfoNode (def. module, def. name, def. file, def. line, inlined_at))
325- oldlinetable = spec. ir. linetable
319+ push! (linetable, LineInfoNode (inlinee. module, inlinee. name, inlinee. file, inlinee. line, inlined_at))
320+ oldlinetable = inlinee_ir. linetable
321+ extra_coverage_line = 0
326322 for oldline in 1 : length (oldlinetable)
327323 entry = oldlinetable[oldline]
328324 if ! coverage && coverage_by_path && is_file_tracked (entry. file)
@@ -341,8 +337,25 @@ function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector
341337 end
342338 push! (linetable, newentry)
343339 end
344- if coverage && spec. ir. stmts[1 ][:line ] + linetable_offset != topline
345- insert_node_here! (compact, NewInstruction (Expr (:code_coverage_effect ), Nothing, topline))
340+ if coverage && inlinee_ir. stmts[1 ][:line ] + linetable_offset != topline
341+ extra_coverage_line = topline
342+ end
343+ return linetable_offset, extra_coverage_line
344+ end
345+
346+ function ir_inline_item! (compact:: IncrementalCompact , idx:: Int , argexprs:: Vector{Any} ,
347+ linetable:: Vector{LineInfoNode} , item:: InliningTodo ,
348+ boundscheck:: Symbol , todo_bbs:: Vector{Tuple{Int, Int}} )
349+ # Ok, do the inlining here
350+ spec = item. spec:: ResolvedInliningSpec
351+ sparam_vals = item. mi. sparam_vals
352+ def = item. mi. def:: Method
353+ inlined_at = compact. result[idx][:line ]
354+ linetable_offset:: Int32 = length (linetable)
355+ topline:: Int32 = linetable_offset + Int32 (1 )
356+ linetable_offset, extra_coverage_line = ir_inline_linetable! (linetable, item. spec. ir, def, inlined_at)
357+ if extra_coverage_line != 0
358+ insert_node_here! (compact, NewInstruction (Expr (:code_coverage_effect ), Nothing, extra_coverage_line))
346359 end
347360 if def. isva
348361 nargs_def = Int (def. nargs:: Int32 )
@@ -848,7 +861,7 @@ function resolve_todo(todo::InliningTodo, state::InliningState, flag::UInt8)
848861 src === nothing && return compileable_specialization (et, match, effects)
849862
850863 et != = nothing && push! (et, mi)
851- return InliningTodo (mi, src, effects)
864+ return InliningTodo (mi, retrieve_ir_for_inlining (mi, src) , effects)
852865end
853866
854867function resolve_todo ((; fully_covered, atype, cases, #= bbs=# ):: UnionSplit , state:: InliningState , flag:: UInt8 )
@@ -870,7 +883,8 @@ function validate_sparams(sparams::SimpleVector)
870883end
871884
872885function analyze_method! (match:: MethodMatch , argtypes:: Vector{Any} ,
873- flag:: UInt8 , state:: InliningState )
886+ flag:: UInt8 , state:: InliningState ,
887+ do_resolve:: Bool = true )
874888 method = match. method
875889 spec_types = match. spec_types
876890
@@ -904,7 +918,7 @@ function analyze_method!(match::MethodMatch, argtypes::Vector{Any},
904918 todo = InliningTodo (mi, match, argtypes)
905919 # If we don't have caches here, delay resolving this MethodInstance
906920 # until the batch inlining step (or an external post-processing pass)
907- state. mi_cache === nothing && return todo
921+ do_resolve && state. mi_cache === nothing && return todo
908922 return resolve_todo (todo, state, flag)
909923end
910924
@@ -913,17 +927,12 @@ function InliningTodo(mi::MethodInstance, ir::IRCode, effects::Effects)
913927 return InliningTodo (mi, ResolvedInliningSpec (ir, effects))
914928end
915929
916- function InliningTodo (mi:: MethodInstance , src:: Union{CodeInfo, Vector{UInt8}} , effects:: Effects )
917- if ! isa (src, CodeInfo)
918- src = ccall (:jl_uncompress_ir , Any, (Any, Ptr{Cvoid}, Any), mi. def, C_NULL , src:: Vector{UInt8} ):: CodeInfo
919- else
920- src = copy (src)
921- end
922- @timeit " inline IR inflation" begin
923- ir = inflate_ir! (src, mi):: IRCode
924- return InliningTodo (mi, ResolvedInliningSpec (ir, effects))
925- end
930+ function retrieve_ir_for_inlining (mi:: MethodInstance , src:: Array{UInt8, 1} )
931+ src = ccall (:jl_uncompress_ir , Any, (Any, Ptr{Cvoid}, Any), mi. def, C_NULL , src:: Vector{UInt8} ):: CodeInfo
932+ return inflate_ir! (src, mi)
926933end
934+ retrieve_ir_for_inlining (mi:: MethodInstance , src:: CodeInfo ) = inflate_ir (src, mi):: IRCode
935+ retrieve_ir_for_inlining (mi:: MethodInstance , ir:: IRCode ) = copy (ir)
927936
928937function handle_single_case! (
929938 ir:: IRCode , idx:: Int , stmt:: Expr ,
@@ -1205,7 +1214,7 @@ function process_simple!(ir::IRCode, idx::Int, state::InliningState, todo::Vecto
12051214 end
12061215 end
12071216
1208- if sig. f != = Core. invoke && is_builtin (sig)
1217+ if sig. f != = Core. invoke && sig . f != = Core . finalizer && is_builtin (sig)
12091218 # No inlining for builtins (other invoke/apply/typeassert)
12101219 return nothing
12111220 end
@@ -1222,9 +1231,10 @@ function process_simple!(ir::IRCode, idx::Int, state::InliningState, todo::Vecto
12221231end
12231232
12241233# TODO inline non-`isdispatchtuple`, union-split callsites?
1225- function analyze_single_call! (
1226- ir:: IRCode , idx:: Int , stmt:: Expr , infos:: Vector{MethodMatchInfo} , flag:: UInt8 ,
1227- sig:: Signature , state:: InliningState , todo:: Vector{Pair{Int, Any}} )
1234+ function compute_inlining_cases (
1235+ infos:: Vector{MethodMatchInfo} , flag:: UInt8 ,
1236+ sig:: Signature , state:: InliningState ,
1237+ do_resolve:: Bool = true )
12281238 argtypes = sig. argtypes
12291239 cases = InliningCase[]
12301240 local any_fully_covered = false
@@ -1241,7 +1251,7 @@ function analyze_single_call!(
12411251 continue
12421252 end
12431253 for match in meth
1244- handled_all_cases &= handle_match! (match, argtypes, flag, state, cases, true )
1254+ handled_all_cases &= handle_match! (match, argtypes, flag, state, cases, true , do_resolve )
12451255 any_fully_covered |= match. fully_covers
12461256 end
12471257 end
@@ -1251,8 +1261,18 @@ function analyze_single_call!(
12511261 filter! (case:: InliningCase -> isdispatchtuple (case. sig), cases)
12521262 end
12531263
1254- handle_cases! (ir, idx, stmt, argtypes_to_type (argtypes), cases,
1255- handled_all_cases & any_fully_covered, todo, state. params)
1264+ return cases, handled_all_cases & any_fully_covered
1265+ end
1266+
1267+ function analyze_single_call! (
1268+ ir:: IRCode , idx:: Int , stmt:: Expr , infos:: Vector{MethodMatchInfo} , flag:: UInt8 ,
1269+ sig:: Signature , state:: InliningState , todo:: Vector{Pair{Int, Any}} )
1270+
1271+ r = compute_inlining_cases (infos, flag, sig, state)
1272+ r === nothing && return nothing
1273+ cases, all_covered = r
1274+ handle_cases! (ir, idx, stmt, argtypes_to_type (sig. argtypes), cases,
1275+ all_covered, todo, state. params)
12561276end
12571277
12581278# similar to `analyze_single_call!`, but with constant results
@@ -1304,14 +1324,15 @@ end
13041324
13051325function handle_match! (
13061326 match:: MethodMatch , argtypes:: Vector{Any} , flag:: UInt8 , state:: InliningState ,
1307- cases:: Vector{InliningCase} , allow_abstract:: Bool = false )
1327+ cases:: Vector{InliningCase} , allow_abstract:: Bool = false ,
1328+ do_resolve:: Bool = true )
13081329 spec_types = match. spec_types
13091330 allow_abstract || isdispatchtuple (spec_types) || return false
13101331 # we may see duplicated dispatch signatures here when a signature gets widened
13111332 # during abstract interpretation: for the purpose of inlining, we can just skip
13121333 # processing this dispatch candidate
13131334 _any (case-> case. sig === spec_types, cases) && return true
1314- item = analyze_method! (match, argtypes, flag, state)
1335+ item = analyze_method! (match, argtypes, flag, state, do_resolve )
13151336 item === nothing && return false
13161337 push! (cases, InliningCase (spec_types, item))
13171338 return true
@@ -1424,6 +1445,48 @@ function assemble_inline_todo!(ir::IRCode, state::InliningState)
14241445 continue
14251446 end
14261447
1448+ # Handle finalizer
1449+ if sig. f === Core. finalizer
1450+ if isa (info, FinalizerInfo)
1451+ # Only inline finalizers that are known nothrow and notls.
1452+ # This avoids having to set up state for finalizer isolation
1453+ (is_nothrow (info. effects) && is_notaskstate (info. effects)) || continue
1454+
1455+ info = info. info
1456+ if isa (info, MethodMatchInfo)
1457+ infos = MethodMatchInfo[info]
1458+ elseif isa (info, UnionSplitInfo)
1459+ infos = info. matches
1460+ else
1461+ continue
1462+ end
1463+
1464+ ft = argextype (stmt. args[2 ], ir)
1465+ has_free_typevars (ft) && return nothing
1466+ f = singleton_type (ft)
1467+ argtypes = Vector {Any} (undef, 2 )
1468+ argtypes[1 ] = ft
1469+ argtypes[2 ] = argextype (stmt. args[3 ], ir)
1470+ sig = Signature (f, ft, argtypes)
1471+
1472+ cases, all_covered = compute_inlining_cases (infos, UInt8 (0 ), sig, state, false )
1473+ length (cases) == 0 && continue
1474+ if all_covered && length (cases) == 1
1475+ if isa (cases[1 ], InliningCase)
1476+ case1 = cases[1 ]. item
1477+ if isa (case1, InliningTodo)
1478+ push! (stmt. args, true )
1479+ push! (stmt. args, case1. mi)
1480+ elseif isa (case1, InvokeCase)
1481+ push! (stmt. args, false )
1482+ push! (stmt. args, case1. invoke)
1483+ end
1484+ end
1485+ end
1486+ continue
1487+ end
1488+ end
1489+
14271490 # if inference arrived here with constant-prop'ed result(s),
14281491 # we can perform a specialized analysis for just this case
14291492 if isa (info, ConstCallInfo)
0 commit comments