Skip to content

Commit b2ea6d1

Browse files
author
Ian Atol
committed
Partially revert 44512 to handle duplicated spec_types inlining bug
1 parent 28dbf82 commit b2ea6d1

File tree

2 files changed

+72
-14
lines changed

2 files changed

+72
-14
lines changed

base/compiler/ssair/inlining.jl

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -880,7 +880,7 @@ function validate_sparams(sparams::SimpleVector)
880880
end
881881

882882
function analyze_method!(match::MethodMatch, argtypes::Vector{Any},
883-
flag::UInt8, state::InliningState)
883+
flag::UInt8, state::InliningState, check_sparams::Bool=false)
884884
method = match.method
885885
spec_types = match.spec_types
886886

@@ -902,7 +902,7 @@ function analyze_method!(match::MethodMatch, argtypes::Vector{Any},
902902
end
903903
end
904904

905-
#validate_sparams(match.sparams) || return nothing
905+
check_sparams && (validate_sparams(match.sparams) || return nothing)
906906

907907
et = state.et
908908

@@ -1238,6 +1238,9 @@ function analyze_single_call!(
12381238
cases = InliningCase[]
12391239
local any_fully_covered = false
12401240
local handled_all_cases = true
1241+
local revisit_idx = nothing
1242+
local only_method = nothing
1243+
local meth::MethodLookupResult
12411244
for i in 1:length(infos)
12421245
meth = infos[i].results
12431246
if meth.ambig
@@ -1248,14 +1251,64 @@ function analyze_single_call!(
12481251
# No applicable methods; try next union split
12491252
handled_all_cases = false
12501253
continue
1254+
else
1255+
if length(meth) == 1 && only_method !== false
1256+
if only_method === nothing
1257+
only_method = meth[1].method
1258+
elseif only_method !== meth[1].method
1259+
only_method = false
1260+
end
1261+
else
1262+
only_method = false
1263+
end
12511264
end
1252-
for match in meth
1253-
handled_all_cases &= handle_match!(match, argtypes, flag, state, cases, true)
1265+
for (j, match) in enumerate(meth)
1266+
if !isdispatchtuple(match.spec_types)
1267+
if !match.fully_covers
1268+
handled_all_cases = false
1269+
continue
1270+
end
1271+
if revisit_idx === nothing
1272+
revisit_idx = (i, j)
1273+
else
1274+
handled_all_cases = false
1275+
revisit_idx = nothing
1276+
end
1277+
else
1278+
handled_all_cases &= handle_match!(match, argtypes, flag, state, cases, true)
1279+
end
12541280
any_fully_covered |= match.fully_covers
12551281
end
12561282
end
12571283

1258-
if !handled_all_cases
1284+
atype = argtypes_to_type(argtypes)
1285+
if handled_all_cases && revisit_idx !== nothing
1286+
# If there's only one case that's not a dispatchtuple, we can
1287+
# still unionsplit by visiting all the other cases first.
1288+
# This is useful for code like:
1289+
# foo(x::Int) = 1
1290+
# foo(@nospecialize(x::Any)) = 2
1291+
# where we where only a small number of specific dispatchable
1292+
# cases are split off from an ::Any typed fallback.
1293+
(i, j) = revisit_idx
1294+
match = infos[i].results[j]
1295+
handled_all_cases &= handle_match!(match, argtypes, flag, state, cases, true, true)
1296+
elseif length(cases) == 0 && only_method isa Method
1297+
# if the signature is fully covered and there is only one applicable method,
1298+
# we can try to inline it even if the signature is not a dispatch tuple.
1299+
# -- But don't try it if we already tried to handle the match in the revisit_idx
1300+
# case, because that'll (necessarily) be the same method.
1301+
if length(infos) > 1
1302+
(metharg, methsp) = ccall(:jl_type_intersection_with_env, Any, (Any, Any),
1303+
atype, only_method.sig)::SimpleVector
1304+
match = MethodMatch(metharg, methsp::SimpleVector, only_method, true)
1305+
else
1306+
@assert length(meth) == 1
1307+
match = meth[1]
1308+
end
1309+
handle_match!(match, argtypes, flag, state, cases, true, false) || return nothing
1310+
any_fully_covered = handled_all_cases = match.fully_covers
1311+
elseif !handled_all_cases
12591312
# if we've not seen all candidates, union split is valid only for dispatch tuples
12601313
filter!(case::InliningCase->isdispatchtuple(case.sig), cases)
12611314
end
@@ -1313,14 +1366,18 @@ end
13131366

13141367
function handle_match!(
13151368
match::MethodMatch, argtypes::Vector{Any}, flag::UInt8, state::InliningState,
1316-
cases::Vector{InliningCase}, allow_abstract::Bool = false)
1369+
cases::Vector{InliningCase}, allow_abstract::Bool = false, check_sparams::Bool=false)
13171370
spec_types = match.spec_types
13181371
allow_abstract || isdispatchtuple(spec_types) || return false
1319-
# we may see duplicated dispatch signatures here when a signature gets widened
1320-
# during abstract interpretation: for the purpose of inlining, we can just skip
1321-
# processing this dispatch candidate
1322-
_any(case->case.sig === spec_types, cases) && return true
1323-
item = analyze_method!(match, argtypes, flag, state)
1372+
if check_sparams
1373+
# we may see duplicated dispatch signatures here when a signature gets widened
1374+
# during abstract interpretation: for the purpose of inlining, we can just skip
1375+
# processing this dispatch candidate
1376+
_any(case->case.sig === spec_types, cases) && return true
1377+
item = analyze_method!(match, argtypes, flag, state, true)
1378+
else
1379+
item = analyze_method!(match, argtypes, flag, state)
1380+
end
13241381
item === nothing && return false
13251382
push!(cases, InliningCase(spec_types, item))
13261383
return true

src/builtins.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1614,10 +1614,11 @@ JL_CALLABLE(jl_f__svec_ref)
16141614
JL_TYPECHK(_svec_ref, simplevector, (jl_value_t*)s);
16151615
JL_TYPECHK(_svec_ref, long, i);
16161616
ssize_t idx = jl_unbox_long(i);
1617-
if (idx < 1 || idx > jl_svec_len(s)) {
1618-
jl_bounds_error_int(s, i);
1617+
size_t len = jl_svec_len(s);
1618+
if (idx < 1 || idx > len) {
1619+
jl_bounds_error_int((jl_value_t*)s, idx);
16191620
}
1620-
return jl_svec_ref(s, jl_unbox_long(i)-1);
1621+
return jl_svec_ref(s, idx-1);
16211622
}
16221623

16231624
static int equiv_field_types(jl_value_t *old, jl_value_t *ft)

0 commit comments

Comments
 (0)