|
370 | 370 |
|
371 | 371 | function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector{Any},
|
372 | 372 | linetable::Vector{LineInfoNode}, item::InliningTodo,
|
373 |
| - boundscheck::Symbol, todo_bbs::Vector{Tuple{Int, Int}}, |
374 |
| - extra_flags::UInt8 = inlined_flags_for_effects(item.effects)) |
| 373 | + boundscheck::Symbol, todo_bbs::Vector{Tuple{Int, Int}}) |
375 | 374 | # Ok, do the inlining here
|
376 | 375 | sparam_vals = item.mi.sparam_vals
|
377 | 376 | def = item.mi.def::Method
|
@@ -447,14 +446,6 @@ function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector
|
447 | 446 | stmt′ = PhiNode(Int32[edge+bb_offset for edge in stmt′.edges], stmt′.values)
|
448 | 447 | end
|
449 | 448 | inline_compact[idx′] = stmt′
|
450 |
| - if extra_flags != 0 && !isa(stmt′, Union{GotoNode, GotoIfNot}) |
451 |
| - if (extra_flags & IR_FLAG_NOTHROW) != 0 && inline_compact[SSAValue(idx′)][:type] === Union{} |
452 |
| - # Shown nothrow, but also guaranteed to throw => unreachable |
453 |
| - inline_compact[idx′] = ReturnNode() |
454 |
| - else |
455 |
| - inline_compact[SSAValue(idx′)][:flag] |= extra_flags |
456 |
| - end |
457 |
| - end |
458 | 449 | end
|
459 | 450 | just_fixup!(inline_compact, new_new_offset, late_fixup_offset)
|
460 | 451 | compact.result_idx = inline_compact.result_idx
|
@@ -1012,37 +1003,6 @@ function flags_for_effects(effects::Effects)
|
1012 | 1003 | return flags
|
1013 | 1004 | end
|
1014 | 1005 |
|
1015 |
| -""" |
1016 |
| - inlined_flags_for_effects(effects::Effects) |
1017 |
| -
|
1018 |
| -This function answers the query: |
1019 |
| -
|
1020 |
| - Given a call site annotated as `effects`, what can we say about each inlined |
1021 |
| - statement after the inlining? |
1022 |
| -
|
1023 |
| -Note that this is different from `flags_for_effects`, which just talks about |
1024 |
| -the call site itself. Consider for example: |
1025 |
| -
|
1026 |
| -```` |
1027 |
| - function foo() |
1028 |
| - V = Any[] |
1029 |
| - push!(V, 1) |
1030 |
| - tuple(V...) |
1031 |
| - end |
1032 |
| -``` |
1033 |
| -
|
1034 |
| -This function is properly inferred effect_free, because it has no global effects. |
1035 |
| -However, we may not inline each statement with an :effect_free flag, because |
1036 |
| -that would incorrectly lose the `push!`. |
1037 |
| -""" |
1038 |
| -function inlined_flags_for_effects(effects::Effects) |
1039 |
| - flags::UInt8 = 0 |
1040 |
| - if is_nothrow(effects) |
1041 |
| - flags |= IR_FLAG_NOTHROW |
1042 |
| - end |
1043 |
| - return flags |
1044 |
| -end |
1045 |
| - |
1046 | 1006 | function handle_single_case!(todo::Vector{Pair{Int,Any}},
|
1047 | 1007 | ir::IRCode, idx::Int, stmt::Expr, @nospecialize(case), params::OptimizationParams,
|
1048 | 1008 | isinvoke::Bool = false)
|
@@ -1221,24 +1181,20 @@ function handle_invoke_call!(todo::Vector{Pair{Int,Any}},
|
1221 | 1181 | invokesig = sig.argtypes
|
1222 | 1182 | override_effects = EFFECTS_UNKNOWN′
|
1223 | 1183 | if isa(result, ConcreteResult)
|
1224 |
| - if may_inline_concrete_result(result) |
1225 |
| - item = concrete_result_item(result, state; invokesig) |
1226 |
| - handle_single_case!(todo, ir, idx, stmt, item, state.params, true) |
1227 |
| - return nothing |
1228 |
| - end |
1229 |
| - override_effects = result.effects |
1230 |
| - end |
1231 |
| - argtypes = invoke_rewrite(sig.argtypes) |
1232 |
| - if isa(result, ConstPropResult) |
1233 |
| - mi = result.result.linfo |
1234 |
| - validate_sparams(mi.sparam_vals) || return nothing |
1235 |
| - if argtypes_to_type(argtypes) <: mi.def.sig |
1236 |
| - item = resolve_todo(mi, result.result, argtypes, info, flag, state; invokesig, override_effects) |
1237 |
| - handle_single_case!(todo, ir, idx, stmt, item, state.params, true) |
1238 |
| - return nothing |
| 1184 | + item = concrete_result_item(result, state, info; invokesig) |
| 1185 | + else |
| 1186 | + argtypes = invoke_rewrite(sig.argtypes) |
| 1187 | + if isa(result, ConstPropResult) |
| 1188 | + mi = result.result.linfo |
| 1189 | + validate_sparams(mi.sparam_vals) || return nothing |
| 1190 | + if argtypes_to_type(argtypes) <: mi.def.sig |
| 1191 | + item = resolve_todo(mi, result.result, argtypes, info, flag, state; invokesig, override_effects) |
| 1192 | + handle_single_case!(todo, ir, idx, stmt, item, state.params, true) |
| 1193 | + return nothing |
| 1194 | + end |
1239 | 1195 | end
|
| 1196 | + item = analyze_method!(match, argtypes, info, flag, state; allow_typevars=false, invokesig, override_effects) |
1240 | 1197 | end
|
1241 |
| - item = analyze_method!(match, argtypes, info, flag, state; allow_typevars=false, invokesig, override_effects) |
1242 | 1198 | handle_single_case!(todo, ir, idx, stmt, item, state.params, true)
|
1243 | 1199 | return nothing
|
1244 | 1200 | end
|
@@ -1352,12 +1308,7 @@ function handle_any_const_result!(cases::Vector{InliningCase},
|
1352 | 1308 | allow_abstract::Bool, allow_typevars::Bool)
|
1353 | 1309 | override_effects = EFFECTS_UNKNOWN′
|
1354 | 1310 | if isa(result, ConcreteResult)
|
1355 |
| - if may_inline_concrete_result(result) |
1356 |
| - return handle_concrete_result!(cases, result, state) |
1357 |
| - else |
1358 |
| - override_effects = result.effects |
1359 |
| - result = nothing |
1360 |
| - end |
| 1311 | + return handle_concrete_result!(cases, result, state, info) |
1361 | 1312 | end
|
1362 | 1313 | if isa(result, SemiConcreteResult)
|
1363 | 1314 | result = inlining_policy(state.interp, result, info, flag, result.mi, argtypes)
|
@@ -1538,18 +1489,24 @@ function handle_semi_concrete_result!(cases::Vector{InliningCase}, result::SemiC
|
1538 | 1489 | return true
|
1539 | 1490 | end
|
1540 | 1491 |
|
1541 |
| -function handle_concrete_result!(cases::Vector{InliningCase}, result::ConcreteResult, state::InliningState) |
1542 |
| - case = concrete_result_item(result, state) |
| 1492 | +function handle_concrete_result!(cases::Vector{InliningCase}, result::ConcreteResult, state::InliningState, @nospecialize(info::CallInfo)) |
| 1493 | + case = concrete_result_item(result, state, info) |
1543 | 1494 | push!(cases, InliningCase(result.mi.specTypes, case))
|
1544 | 1495 | return true
|
1545 | 1496 | end
|
1546 | 1497 |
|
1547 | 1498 | may_inline_concrete_result(result::ConcreteResult) =
|
1548 | 1499 | isdefined(result, :result) && is_inlineable_constant(result.result)
|
1549 | 1500 |
|
1550 |
| -function concrete_result_item(result::ConcreteResult, state::InliningState; |
| 1501 | +function concrete_result_item(result::ConcreteResult, state::InliningState, @nospecialize(info::CallInfo); |
1551 | 1502 | invokesig::Union{Nothing,Vector{Any}}=nothing)
|
1552 |
| - @assert may_inline_concrete_result(result) |
| 1503 | + if !may_inline_concrete_result(result) |
| 1504 | + et = InliningEdgeTracker(state.et, invokesig) |
| 1505 | + case = compileable_specialization(result.mi, result.effects, et, info; |
| 1506 | + compilesig_invokes=state.params.compilesig_invokes) |
| 1507 | + @assert case !== nothing "concrete evaluation should never happen for uncompileable callsite" |
| 1508 | + return case |
| 1509 | + end |
1553 | 1510 | @assert result.effects === EFFECTS_TOTAL
|
1554 | 1511 | return ConstantCase(quoted(result.result))
|
1555 | 1512 | end
|
@@ -1583,12 +1540,7 @@ function handle_opaque_closure_call!(todo::Vector{Pair{Int,Any}},
|
1583 | 1540 | validate_sparams(mi.sparam_vals) || return nothing
|
1584 | 1541 | item = resolve_todo(mi, result.result, sig.argtypes, info, flag, state)
|
1585 | 1542 | elseif isa(result, ConcreteResult)
|
1586 |
| - if may_inline_concrete_result(result) |
1587 |
| - item = concrete_result_item(result, state) |
1588 |
| - else |
1589 |
| - override_effects = result.effects |
1590 |
| - item = analyze_method!(info.match, sig.argtypes, info, flag, state; allow_typevars=false, override_effects) |
1591 |
| - end |
| 1543 | + item = concrete_result_item(result, state, info) |
1592 | 1544 | else
|
1593 | 1545 | item = analyze_method!(info.match, sig.argtypes, info, flag, state; allow_typevars=false)
|
1594 | 1546 | end
|
|
0 commit comments