@@ -767,7 +767,7 @@ function rewrite_apply_exprargs!(
767767 elseif isa (new_info, MethodMatchInfo) || isa (new_info, UnionSplitInfo)
768768 new_infos = isa (new_info, MethodMatchInfo) ? MethodMatchInfo[new_info] : new_info. matches
769769 # See if we can inline this call to `iterate`
770- analyze_single_call ! (
770+ handle_call ! (
771771 ir, state1. id, new_stmt, new_infos, flag,
772772 new_sig, istate, todo)
773773 end
@@ -874,8 +874,7 @@ function validate_sparams(sparams::SimpleVector)
874874end
875875
876876function analyze_method! (match:: MethodMatch , argtypes:: Vector{Any} ,
877- flag:: UInt8 , state:: InliningState ,
878- do_resolve:: Bool = true )
877+ flag:: UInt8 , state:: InliningState )
879878 method = match. method
880879 spec_types = match. spec_types
881880
@@ -909,7 +908,7 @@ function analyze_method!(match::MethodMatch, argtypes::Vector{Any},
909908 todo = InliningTodo (mi, match, argtypes)
910909 # If we don't have caches here, delay resolving this MethodInstance
911910 # until the batch inlining step (or an external post-processing pass)
912- do_resolve && state. mi_cache === nothing && return todo
911+ state. mi_cache === nothing && return todo
913912 return resolve_todo (todo, state, flag)
914913end
915914
@@ -921,7 +920,7 @@ function retrieve_ir_for_inlining(mi::MethodInstance, src::Array{UInt8, 1})
921920 src = ccall (:jl_uncompress_ir , Any, (Any, Ptr{Cvoid}, Any), mi. def, C_NULL , src:: Vector{UInt8} ):: CodeInfo
922921 return inflate_ir! (src, mi)
923922end
924- retrieve_ir_for_inlining (mi:: MethodInstance , src:: CodeInfo ) = inflate_ir (src, mi):: IRCode
923+ retrieve_ir_for_inlining (mi:: MethodInstance , src:: CodeInfo ) = inflate_ir (src, mi)
925924retrieve_ir_for_inlining (mi:: MethodInstance , ir:: IRCode ) = copy (ir)
926925
927926function handle_single_case! (
@@ -1225,10 +1224,8 @@ function process_simple!(ir::IRCode, idx::Int, state::InliningState, todo::Vecto
12251224end
12261225
12271226# TODO inline non-`isdispatchtuple`, union-split callsites?
1228- function compute_inlining_cases (
1229- infos:: Vector{MethodMatchInfo} , flag:: UInt8 ,
1230- sig:: Signature , state:: InliningState ,
1231- do_resolve:: Bool = true )
1227+ function compute_inlining_cases (infos:: Vector{MethodMatchInfo} ,
1228+ flag:: UInt8 , sig:: Signature , state:: InliningState )
12321229 argtypes = sig. argtypes
12331230 cases = InliningCase[]
12341231 local any_fully_covered = false
@@ -1245,7 +1242,7 @@ function compute_inlining_cases(
12451242 continue
12461243 end
12471244 for match in meth
1248- handled_all_cases &= handle_match! (match, argtypes, flag, state, cases, true , do_resolve )
1245+ handled_all_cases &= handle_match! (match, argtypes, flag, state, cases, #= allow_abstract =# true )
12491246 any_fully_covered |= match. fully_covers
12501247 end
12511248 end
@@ -1258,23 +1255,10 @@ function compute_inlining_cases(
12581255 return cases, handled_all_cases & any_fully_covered
12591256end
12601257
1261- function analyze_single_call! (
1262- ir:: IRCode , idx:: Int , stmt:: Expr , infos:: Vector{MethodMatchInfo} , flag:: UInt8 ,
1263- sig:: Signature , state:: InliningState , todo:: Vector{Pair{Int, Any}} )
1264-
1265- r = compute_inlining_cases (infos, flag, sig, state)
1266- r === nothing && return nothing
1267- cases, all_covered = r
1268- handle_cases! (ir, idx, stmt, argtypes_to_type (sig. argtypes), cases,
1269- all_covered, todo, state. params)
1270- end
1271-
1272- # similar to `analyze_single_call!`, but with constant results
1273- function handle_const_call! (
1274- ir:: IRCode , idx:: Int , stmt:: Expr , cinfo:: ConstCallInfo , flag:: UInt8 ,
1275- sig:: Signature , state:: InliningState , todo:: Vector{Pair{Int, Any}} )
1258+ function compute_inlining_cases (info:: ConstCallInfo ,
1259+ flag:: UInt8 , sig:: Signature , state:: InliningState )
12761260 argtypes = sig. argtypes
1277- (; call, results) = cinfo
1261+ (; call, results) = info
12781262 infos = isa (call, MethodMatchInfo) ? MethodMatchInfo[call] : call. matches
12791263 cases = InliningCase[]
12801264 local any_fully_covered = false
@@ -1302,7 +1286,7 @@ function handle_const_call!(
13021286 handled_all_cases &= handle_const_prop_result! (result, argtypes, flag, state, cases, true )
13031287 else
13041288 @assert result === nothing
1305- handled_all_cases &= handle_match! (match, argtypes, flag, state, cases, true )
1289+ handled_all_cases &= handle_match! (match, argtypes, flag, state, cases, #= allow_abstract =# true )
13061290 end
13071291 end
13081292 end
@@ -1312,21 +1296,39 @@ function handle_const_call!(
13121296 filter! (case:: InliningCase -> isdispatchtuple (case. sig), cases)
13131297 end
13141298
1315- handle_cases! (ir, idx, stmt, argtypes_to_type (argtypes), cases,
1316- handled_all_cases & any_fully_covered, todo, state. params)
1299+ return cases, handled_all_cases & any_fully_covered
1300+ end
1301+
1302+ function handle_call! (
1303+ ir:: IRCode , idx:: Int , stmt:: Expr , infos:: Vector{MethodMatchInfo} , flag:: UInt8 ,
1304+ sig:: Signature , state:: InliningState , todo:: Vector{Pair{Int, Any}} )
1305+ cases = compute_inlining_cases (infos, flag, sig, state)
1306+ cases === nothing && return nothing
1307+ cases, all_covered = cases
1308+ handle_cases! (ir, idx, stmt, argtypes_to_type (sig. argtypes), cases,
1309+ all_covered, todo, state. params)
1310+ end
1311+
1312+ function handle_const_call! (
1313+ ir:: IRCode , idx:: Int , stmt:: Expr , info:: ConstCallInfo , flag:: UInt8 ,
1314+ sig:: Signature , state:: InliningState , todo:: Vector{Pair{Int, Any}} )
1315+ cases = compute_inlining_cases (info, flag, sig, state)
1316+ cases === nothing && return nothing
1317+ cases, all_covered = cases
1318+ handle_cases! (ir, idx, stmt, argtypes_to_type (sig. argtypes), cases,
1319+ all_covered, todo, state. params)
13171320end
13181321
13191322function handle_match! (
13201323 match:: MethodMatch , argtypes:: Vector{Any} , flag:: UInt8 , state:: InliningState ,
1321- cases:: Vector{InliningCase} , allow_abstract:: Bool = false ,
1322- do_resolve:: Bool = true )
1324+ cases:: Vector{InliningCase} , allow_abstract:: Bool = false )
13231325 spec_types = match. spec_types
13241326 allow_abstract || isdispatchtuple (spec_types) || return false
13251327 # we may see duplicated dispatch signatures here when a signature gets widened
13261328 # during abstract interpretation: for the purpose of inlining, we can just skip
13271329 # processing this dispatch candidate
13281330 _any (case-> case. sig === spec_types, cases) && return true
1329- item = analyze_method! (match, argtypes, flag, state, do_resolve )
1331+ item = analyze_method! (match, argtypes, flag, state)
13301332 item === nothing && return false
13311333 push! (cases, InliningCase (spec_types, item))
13321334 return true
@@ -1384,6 +1386,54 @@ function handle_const_opaque_closure_call!(
13841386 return nothing
13851387end
13861388
1389+ function handle_finalizer_call! (
1390+ ir:: IRCode , stmt:: Expr , info:: FinalizerInfo , state:: InliningState )
1391+ # Only inline finalizers that are known nothrow and notls.
1392+ # This avoids having to set up state for finalizer isolation
1393+ (is_nothrow (info. effects) && is_notaskstate (info. effects)) || return nothing
1394+
1395+ info = info. info
1396+ if isa (info, MethodMatchInfo)
1397+ infos = MethodMatchInfo[info]
1398+ elseif isa (info, UnionSplitInfo)
1399+ infos = info. matches
1400+ # elseif isa(info, ConstCallInfo)
1401+ # # NOTE currently this code path isn't active as constant propagation won't happen
1402+ # # for `Core.finalizer` call because inference currently isn't able to fold a mutable
1403+ # # object as a constant
1404+ else
1405+ return nothing
1406+ end
1407+
1408+ ft = argextype (stmt. args[2 ], ir)
1409+ has_free_typevars (ft) && return nothing
1410+ f = singleton_type (ft)
1411+ argtypes = Vector {Any} (undef, 2 )
1412+ argtypes[1 ] = ft
1413+ argtypes[2 ] = argextype (stmt. args[3 ], ir)
1414+ sig = Signature (f, ft, argtypes)
1415+
1416+ cases = compute_inlining_cases (infos, #= flag=# UInt8 (0 ), sig, state)
1417+ cases === nothing && return nothing
1418+ cases, all_covered = cases
1419+ if all_covered && length (cases) == 1
1420+ # NOTE we don't append `item1` to `stmt` here so that we don't serialize
1421+ # `Core.Compiler` data structure into the global cache
1422+ item1 = cases[1 ]. item
1423+ if isa (item1, InliningTodo)
1424+ push! (stmt. args, true )
1425+ push! (stmt. args, item1. mi)
1426+ elseif isa (item1, InvokeCase)
1427+ push! (stmt. args, false )
1428+ push! (stmt. args, item1. invoke)
1429+ elseif isa (item1, ConstantCase)
1430+ push! (stmt. args, nothing )
1431+ push! (stmt. args, item1. val)
1432+ end
1433+ end
1434+ return nothing
1435+ end
1436+
13871437function inline_const_if_inlineable! (inst:: Instruction )
13881438 rt = inst[:type ]
13891439 if rt isa Const && is_inlineable_constant (rt. val)
@@ -1434,53 +1484,15 @@ function assemble_inline_todo!(ir::IRCode, state::InliningState)
14341484 end
14351485
14361486 # Handle invoke
1437- if sig. f === Core. invoke
1438- if isa (info, InvokeCallInfo)
1439- inline_invoke! (ir, idx, stmt, info, flag, sig, state, todo)
1440- end
1487+ if isa (info, InvokeCallInfo)
1488+ inline_invoke! (ir, idx, stmt, info, flag, sig, state, todo)
14411489 continue
14421490 end
14431491
14441492 # Handle finalizer
1445- if sig. f === Core. finalizer
1446- if isa (info, FinalizerInfo)
1447- # Only inline finalizers that are known nothrow and notls.
1448- # This avoids having to set up state for finalizer isolation
1449- (is_nothrow (info. effects) && is_notaskstate (info. effects)) || continue
1450-
1451- info = info. info
1452- if isa (info, MethodMatchInfo)
1453- infos = MethodMatchInfo[info]
1454- elseif isa (info, UnionSplitInfo)
1455- infos = info. matches
1456- else
1457- continue
1458- end
1459-
1460- ft = argextype (stmt. args[2 ], ir)
1461- has_free_typevars (ft) && return nothing
1462- f = singleton_type (ft)
1463- argtypes = Vector {Any} (undef, 2 )
1464- argtypes[1 ] = ft
1465- argtypes[2 ] = argextype (stmt. args[3 ], ir)
1466- sig = Signature (f, ft, argtypes)
1467-
1468- cases, all_covered = compute_inlining_cases (infos, UInt8 (0 ), sig, state, false )
1469- length (cases) == 0 && continue
1470- if all_covered && length (cases) == 1
1471- if isa (cases[1 ], InliningCase)
1472- case1 = cases[1 ]. item
1473- if isa (case1, InliningTodo)
1474- push! (stmt. args, true )
1475- push! (stmt. args, case1. mi)
1476- elseif isa (case1, InvokeCase)
1477- push! (stmt. args, false )
1478- push! (stmt. args, case1. invoke)
1479- end
1480- end
1481- end
1482- continue
1483- end
1493+ if isa (info, FinalizerInfo)
1494+ handle_finalizer_call! (ir, stmt, info, state)
1495+ continue
14841496 end
14851497
14861498 # if inference arrived here with constant-prop'ed result(s),
@@ -1501,7 +1513,7 @@ function assemble_inline_todo!(ir::IRCode, state::InliningState)
15011513 continue # isa(info, ReturnTypeCallInfo), etc.
15021514 end
15031515
1504- analyze_single_call ! (ir, idx, stmt, infos, flag, sig, state, todo)
1516+ handle_call ! (ir, idx, stmt, infos, flag, sig, state, todo)
15051517 end
15061518
15071519 return todo
0 commit comments