Skip to content

Commit 67f994c

Browse files
Kenoaviatesk
andauthored
Fix SROA miscompile in large functions (#46819)
* Fix SROA miscompile in large functions During the development of #46775, we saw a miscompile in the compiler, specifically, we saw SROA failing to provide a proper PHI nest. The root cause of this turned out to be an incorrect dominance query. In particular, during incremental compaction, the non-compacted portion of the IncrementalCompact cfg is allocated, but not valid, so we must not query it for basic block information. Unfortunately, I don't really have a good test case for this. This code has grown mostly organically for a few years, and I think it's probably overdue for an overhaul. * optimizer: address TODO for computing `joint_effects` more efficiently Co-authored-by: Shuhei Kadowaki <aviatesk@gmail.com>
1 parent caf544b commit 67f994c

File tree

2 files changed

+17
-27
lines changed

2 files changed

+17
-27
lines changed

base/compiler/ssair/inlining.jl

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,27 +1338,6 @@ function info_effects(@nospecialize(result), match::MethodMatch, state::Inlining
13381338
end
13391339
end
13401340

1341-
function compute_joint_effects(info::Union{ConstCallInfo, Vector{MethodMatchInfo}}, state::InliningState)
1342-
if isa(info, ConstCallInfo)
1343-
(; call, results) = info
1344-
infos = isa(call, MethodMatchInfo) ? MethodMatchInfo[call] : call.matches
1345-
else
1346-
results = nothing
1347-
infos = info
1348-
end
1349-
local all_result_count = 0
1350-
local joint_effects::Effects = EFFECTS_TOTAL
1351-
for i in 1:length(infos)
1352-
meth = infos[i].results
1353-
for (j, match) in enumerate(meth)
1354-
all_result_count += 1
1355-
result = results === nothing ? nothing : results[all_result_count]
1356-
joint_effects = merge_effects(joint_effects, info_effects(result, match, state))
1357-
end
1358-
end
1359-
return joint_effects
1360-
end
1361-
13621341
function compute_inlining_cases(info::Union{ConstCallInfo, Vector{MethodMatchInfo}},
13631342
flag::UInt8, sig::Signature, state::InliningState)
13641343
argtypes = sig.argtypes
@@ -1376,6 +1355,8 @@ function compute_inlining_cases(info::Union{ConstCallInfo, Vector{MethodMatchInf
13761355
local only_method = nothing
13771356
local meth::MethodLookupResult
13781357
local all_result_count = 0
1358+
local joint_effects::Effects = EFFECTS_TOTAL
1359+
local nothrow::Bool = true
13791360
for i in 1:length(infos)
13801361
meth = infos[i].results
13811362
if meth.ambig
@@ -1400,6 +1381,8 @@ function compute_inlining_cases(info::Union{ConstCallInfo, Vector{MethodMatchInf
14001381
for (j, match) in enumerate(meth)
14011382
all_result_count += 1
14021383
result = results === nothing ? nothing : results[all_result_count]
1384+
joint_effects = merge_effects(joint_effects, info_effects(result, match, state))
1385+
nothrow &= match.fully_covers
14031386
any_fully_covered |= match.fully_covers
14041387
if !validate_sparams(match.sparams)
14051388
if !match.fully_covers
@@ -1418,6 +1401,8 @@ function compute_inlining_cases(info::Union{ConstCallInfo, Vector{MethodMatchInf
14181401
end
14191402
end
14201403

1404+
joint_effects = Effects(joint_effects; nothrow)
1405+
14211406
if handled_all_cases && revisit_idx !== nothing
14221407
# we handled everything except one match with unmatched sparams,
14231408
# so try to handle it by bypassing validate_sparams
@@ -1447,9 +1432,6 @@ function compute_inlining_cases(info::Union{ConstCallInfo, Vector{MethodMatchInf
14471432
filter!(case::InliningCase->isdispatchtuple(case.sig), cases)
14481433
end
14491434

1450-
# TODO fuse `compute_joint_effects` into the loop above, which currently causes compilation error
1451-
joint_effects = Effects(compute_joint_effects(info, state); nothrow=handled_all_cases)
1452-
14531435
return cases, (handled_all_cases & any_fully_covered), joint_effects
14541436
end
14551437

base/compiler/ssair/ir.jl

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,18 @@ function cfg_delete_edge!(cfg::CFG, from::Int, to::Int)
2828
nothing
2929
end
3030

31+
function bb_ordering()
32+
lt=(<=)
33+
by=x->first(x.stmts)
34+
ord(lt, by, nothing, Forward)
35+
end
36+
3137
function block_for_inst(index::Vector{Int}, inst::Int)
3238
return searchsortedfirst(index, inst, lt=(<=))
3339
end
3440

3541
function block_for_inst(index::Vector{BasicBlock}, inst::Int)
36-
return searchsortedfirst(index, BasicBlock(StmtRange(inst, inst)), by=x->first(x.stmts), lt=(<=))-1
42+
return searchsortedfirst(index, BasicBlock(StmtRange(inst, inst)), bb_ordering())-1
3743
end
3844

3945
block_for_inst(cfg::CFG, inst::Int) = block_for_inst(cfg.index, inst)
@@ -674,7 +680,8 @@ end
674680
function block_for_inst(compact::IncrementalCompact, idx::SSAValue)
675681
id = idx.id
676682
if id < compact.result_idx # if ssa within result
677-
return block_for_inst(compact.result_bbs, id)
683+
return searchsortedfirst(compact.result_bbs, BasicBlock(StmtRange(id, id)),
684+
1, compact.active_result_bb, bb_ordering())-1
678685
else
679686
return block_for_inst(compact.ir.cfg, id)
680687
end
@@ -683,7 +690,8 @@ end
683690
function block_for_inst(compact::IncrementalCompact, idx::OldSSAValue)
684691
id = idx.id
685692
if id < compact.idx # if ssa within result
686-
return block_for_inst(compact.result_bbs, compact.ssa_rename[id])
693+
id = compact.ssa_rename[id]
694+
return block_for_inst(compact, SSAValue(id))
687695
else
688696
return block_for_inst(compact.ir.cfg, id)
689697
end

0 commit comments

Comments
 (0)