@@ -767,7 +767,7 @@ function rewrite_apply_exprargs!(
767
767
elseif isa (new_info, MethodMatchInfo) || isa (new_info, UnionSplitInfo)
768
768
new_infos = isa (new_info, MethodMatchInfo) ? MethodMatchInfo[new_info] : new_info. matches
769
769
# See if we can inline this call to `iterate`
770
- analyze_single_call ! (
770
+ handle_call ! (
771
771
ir, state1. id, new_stmt, new_infos, flag,
772
772
new_sig, istate, todo)
773
773
end
@@ -874,8 +874,7 @@ function validate_sparams(sparams::SimpleVector)
874
874
end
875
875
876
876
function analyze_method! (match:: MethodMatch , argtypes:: Vector{Any} ,
877
- flag:: UInt8 , state:: InliningState ,
878
- do_resolve:: Bool = true )
877
+ flag:: UInt8 , state:: InliningState )
879
878
method = match. method
880
879
spec_types = match. spec_types
881
880
@@ -909,7 +908,7 @@ function analyze_method!(match::MethodMatch, argtypes::Vector{Any},
909
908
todo = InliningTodo (mi, match, argtypes)
910
909
# If we don't have caches here, delay resolving this MethodInstance
911
910
# 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
913
912
return resolve_todo (todo, state, flag)
914
913
end
915
914
@@ -921,7 +920,7 @@ function retrieve_ir_for_inlining(mi::MethodInstance, src::Array{UInt8, 1})
921
920
src = ccall (:jl_uncompress_ir , Any, (Any, Ptr{Cvoid}, Any), mi. def, C_NULL , src:: Vector{UInt8} ):: CodeInfo
922
921
return inflate_ir! (src, mi)
923
922
end
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)
925
924
retrieve_ir_for_inlining (mi:: MethodInstance , ir:: IRCode ) = copy (ir)
926
925
927
926
function handle_single_case! (
@@ -1225,10 +1224,8 @@ function process_simple!(ir::IRCode, idx::Int, state::InliningState, todo::Vecto
1225
1224
end
1226
1225
1227
1226
# 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 )
1232
1229
argtypes = sig. argtypes
1233
1230
cases = InliningCase[]
1234
1231
local any_fully_covered = false
@@ -1245,7 +1242,7 @@ function compute_inlining_cases(
1245
1242
continue
1246
1243
end
1247
1244
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 )
1249
1246
any_fully_covered |= match. fully_covers
1250
1247
end
1251
1248
end
@@ -1258,23 +1255,10 @@ function compute_inlining_cases(
1258
1255
return cases, handled_all_cases & any_fully_covered
1259
1256
end
1260
1257
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 )
1276
1260
argtypes = sig. argtypes
1277
- (; call, results) = cinfo
1261
+ (; call, results) = info
1278
1262
infos = isa (call, MethodMatchInfo) ? MethodMatchInfo[call] : call. matches
1279
1263
cases = InliningCase[]
1280
1264
local any_fully_covered = false
@@ -1302,7 +1286,7 @@ function handle_const_call!(
1302
1286
handled_all_cases &= handle_const_prop_result! (result, argtypes, flag, state, cases, true )
1303
1287
else
1304
1288
@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 )
1306
1290
end
1307
1291
end
1308
1292
end
@@ -1312,21 +1296,39 @@ function handle_const_call!(
1312
1296
filter! (case:: InliningCase -> isdispatchtuple (case. sig), cases)
1313
1297
end
1314
1298
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)
1317
1320
end
1318
1321
1319
1322
function handle_match! (
1320
1323
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 )
1323
1325
spec_types = match. spec_types
1324
1326
allow_abstract || isdispatchtuple (spec_types) || return false
1325
1327
# we may see duplicated dispatch signatures here when a signature gets widened
1326
1328
# during abstract interpretation: for the purpose of inlining, we can just skip
1327
1329
# processing this dispatch candidate
1328
1330
_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)
1330
1332
item === nothing && return false
1331
1333
push! (cases, InliningCase (spec_types, item))
1332
1334
return true
@@ -1384,6 +1386,54 @@ function handle_const_opaque_closure_call!(
1384
1386
return nothing
1385
1387
end
1386
1388
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
+
1387
1437
function inline_const_if_inlineable! (inst:: Instruction )
1388
1438
rt = inst[:type ]
1389
1439
if rt isa Const && is_inlineable_constant (rt. val)
@@ -1434,53 +1484,15 @@ function assemble_inline_todo!(ir::IRCode, state::InliningState)
1434
1484
end
1435
1485
1436
1486
# 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)
1441
1489
continue
1442
1490
end
1443
1491
1444
1492
# 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
1484
1496
end
1485
1497
1486
1498
# if inference arrived here with constant-prop'ed result(s),
@@ -1501,7 +1513,7 @@ function assemble_inline_todo!(ir::IRCode, state::InliningState)
1501
1513
continue # isa(info, ReturnTypeCallInfo), etc.
1502
1514
end
1503
1515
1504
- analyze_single_call ! (ir, idx, stmt, infos, flag, sig, state, todo)
1516
+ handle_call ! (ir, idx, stmt, infos, flag, sig, state, todo)
1505
1517
end
1506
1518
1507
1519
return todo
0 commit comments