@@ -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 )
@@ -839,7 +852,7 @@ function resolve_todo(todo::InliningTodo, state::InliningState, flag::UInt8)
839852 src === nothing && return compileable_specialization (et, match, effects)
840853
841854 et != = nothing && push! (et, mi)
842- return InliningTodo (mi, src, effects)
855+ return InliningTodo (mi, retrieve_ir_for_inlining (mi, src) , effects)
843856end
844857
845858function resolve_todo ((; fully_covered, atype, cases, #= bbs=# ):: UnionSplit , state:: InliningState , flag:: UInt8 )
@@ -861,7 +874,8 @@ function validate_sparams(sparams::SimpleVector)
861874end
862875
863876function analyze_method! (match:: MethodMatch , argtypes:: Vector{Any} ,
864- flag:: UInt8 , state:: InliningState )
877+ flag:: UInt8 , state:: InliningState ,
878+ do_resolve:: Bool = true )
865879 method = match. method
866880 spec_types = match. spec_types
867881
@@ -895,7 +909,7 @@ function analyze_method!(match::MethodMatch, argtypes::Vector{Any},
895909 todo = InliningTodo (mi, match, argtypes)
896910 # If we don't have caches here, delay resolving this MethodInstance
897911 # until the batch inlining step (or an external post-processing pass)
898- state. mi_cache === nothing && return todo
912+ do_resolve && state. mi_cache === nothing && return todo
899913 return resolve_todo (todo, state, flag)
900914end
901915
@@ -904,17 +918,12 @@ function InliningTodo(mi::MethodInstance, ir::IRCode, effects::Effects)
904918 return InliningTodo (mi, ResolvedInliningSpec (ir, effects))
905919end
906920
907- function InliningTodo (mi:: MethodInstance , src:: Union{CodeInfo, Vector{UInt8}} , effects:: Effects )
908- if ! isa (src, CodeInfo)
909- src = ccall (:jl_uncompress_ir , Any, (Any, Ptr{Cvoid}, Any), mi. def, C_NULL , src:: Vector{UInt8} ):: CodeInfo
910- else
911- src = copy (src)
912- end
913- @timeit " inline IR inflation" begin
914- ir = inflate_ir! (src, mi):: IRCode
915- return InliningTodo (mi, ResolvedInliningSpec (ir, effects))
916- end
921+ function retrieve_ir_for_inlining (mi:: MethodInstance , src:: Array{UInt8, 1} )
922+ src = ccall (:jl_uncompress_ir , Any, (Any, Ptr{Cvoid}, Any), mi. def, C_NULL , src:: Vector{UInt8} ):: CodeInfo
923+ return inflate_ir! (src, mi)
917924end
925+ retrieve_ir_for_inlining (mi:: MethodInstance , src:: CodeInfo ) = inflate_ir (src, mi):: IRCode
926+ retrieve_ir_for_inlining (mi:: MethodInstance , ir:: IRCode ) = copy (ir)
918927
919928function handle_single_case! (
920929 ir:: IRCode , idx:: Int , stmt:: Expr ,
@@ -1196,7 +1205,7 @@ function process_simple!(ir::IRCode, idx::Int, state::InliningState, todo::Vecto
11961205 end
11971206 end
11981207
1199- if sig. f != = Core. invoke && is_builtin (sig)
1208+ if sig. f != = Core. invoke && sig . f != = Core . finalizer && is_builtin (sig)
12001209 # No inlining for builtins (other invoke/apply/typeassert)
12011210 return nothing
12021211 end
@@ -1213,9 +1222,10 @@ function process_simple!(ir::IRCode, idx::Int, state::InliningState, todo::Vecto
12131222end
12141223
12151224# TODO inline non-`isdispatchtuple`, union-split callsites?
1216- function analyze_single_call! (
1217- ir:: IRCode , idx:: Int , stmt:: Expr , infos:: Vector{MethodMatchInfo} , flag:: UInt8 ,
1218- sig:: Signature , state:: InliningState , todo:: Vector{Pair{Int, Any}} )
1225+ function compute_inlining_cases (
1226+ infos:: Vector{MethodMatchInfo} , flag:: UInt8 ,
1227+ sig:: Signature , state:: InliningState ,
1228+ do_resolve:: Bool = true )
12191229 argtypes = sig. argtypes
12201230 cases = InliningCase[]
12211231 local any_fully_covered = false
@@ -1232,7 +1242,7 @@ function analyze_single_call!(
12321242 continue
12331243 end
12341244 for match in meth
1235- handled_all_cases &= handle_match! (match, argtypes, flag, state, cases, true )
1245+ handled_all_cases &= handle_match! (match, argtypes, flag, state, cases, true , do_resolve )
12361246 any_fully_covered |= match. fully_covers
12371247 end
12381248 end
@@ -1242,8 +1252,18 @@ function analyze_single_call!(
12421252 filter! (case:: InliningCase -> isdispatchtuple (case. sig), cases)
12431253 end
12441254
1245- handle_cases! (ir, idx, stmt, argtypes_to_type (argtypes), cases,
1246- handled_all_cases & any_fully_covered, todo, state. params)
1255+ return cases, handled_all_cases & any_fully_covered
1256+ end
1257+
1258+ function analyze_single_call! (
1259+ ir:: IRCode , idx:: Int , stmt:: Expr , infos:: Vector{MethodMatchInfo} , flag:: UInt8 ,
1260+ sig:: Signature , state:: InliningState , todo:: Vector{Pair{Int, Any}} )
1261+
1262+ r = compute_inlining_cases (infos, flag, sig, state)
1263+ r === nothing && return nothing
1264+ cases, all_covered = r
1265+ handle_cases! (ir, idx, stmt, argtypes_to_type (sig. argtypes), cases,
1266+ all_covered, todo, state. params)
12471267end
12481268
12491269# similar to `analyze_single_call!`, but with constant results
@@ -1299,14 +1319,15 @@ end
12991319
13001320function handle_match! (
13011321 match:: MethodMatch , argtypes:: Vector{Any} , flag:: UInt8 , state:: InliningState ,
1302- cases:: Vector{InliningCase} , allow_abstract:: Bool = false )
1322+ cases:: Vector{InliningCase} , allow_abstract:: Bool = false ,
1323+ do_resolve:: Bool = true )
13031324 spec_types = match. spec_types
13041325 allow_abstract || isdispatchtuple (spec_types) || return false
13051326 # we may see duplicated dispatch signatures here when a signature gets widened
13061327 # during abstract interpretation: for the purpose of inlining, we can just skip
13071328 # processing this dispatch candidate
13081329 _any (case-> case. sig === spec_types, cases) && return true
1309- item = analyze_method! (match, argtypes, flag, state)
1330+ item = analyze_method! (match, argtypes, flag, state, do_resolve )
13101331 item === nothing && return false
13111332 push! (cases, InliningCase (spec_types, item))
13121333 return true
@@ -1419,6 +1440,48 @@ function assemble_inline_todo!(ir::IRCode, state::InliningState)
14191440 continue
14201441 end
14211442
1443+ # Handle finalizer
1444+ if sig. f === Core. finalizer
1445+ if isa (info, FinalizerInfo)
1446+ # Only inline finalizers that are known nothrow and notls.
1447+ # This avoids having to set up state for finalizer isolation
1448+ (is_nothrow (info. effects) && is_notaskstate (info. effects)) || continue
1449+
1450+ info = info. info
1451+ if isa (info, MethodMatchInfo)
1452+ infos = MethodMatchInfo[info]
1453+ elseif isa (info, UnionSplitInfo)
1454+ infos = info. matches
1455+ else
1456+ continue
1457+ end
1458+
1459+ ft = argextype (stmt. args[2 ], ir)
1460+ has_free_typevars (ft) && return nothing
1461+ f = singleton_type (ft)
1462+ argtypes = Vector {Any} (undef, 2 )
1463+ argtypes[1 ] = ft
1464+ argtypes[2 ] = argextype (stmt. args[3 ], ir)
1465+ sig = Signature (f, ft, argtypes)
1466+
1467+ cases, all_covered = compute_inlining_cases (infos, UInt8 (0 ), sig, state, false )
1468+ length (cases) == 0 && continue
1469+ if all_covered && length (cases) == 1
1470+ if isa (cases[1 ], InliningCase)
1471+ case1 = cases[1 ]. item
1472+ if isa (case1, InliningTodo)
1473+ push! (stmt. args, true )
1474+ push! (stmt. args, case1. mi)
1475+ elseif isa (case1, InvokeCase)
1476+ push! (stmt. args, false )
1477+ push! (stmt. args, case1. invoke)
1478+ end
1479+ end
1480+ end
1481+ continue
1482+ end
1483+ end
1484+
14221485 # if inference arrived here with constant-prop'ed result(s),
14231486 # we can perform a specialized analysis for just this case
14241487 if isa (info, ConstCallInfo)
0 commit comments