Skip to content

Commit 321fb2c

Browse files
authored
sroa: Fix incorrect scope counting (#53630)
Sroa was incorrectly assuming that every :leave leaves exactly one scope. In reality, it leaves as many scopes as the corresponding :leave references. Fix that to fix #53521.
1 parent fa90883 commit 321fb2c

File tree

2 files changed

+33
-3
lines changed

2 files changed

+33
-3
lines changed

base/compiler/ssair/passes.jl

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,10 +1225,21 @@ function sroa_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing)
12251225
bb = compact.active_result_bb - 1
12261226
bbs = scope_mapping[bb]
12271227
if isexpr(stmt, :leave) && bbs != SSAValue(0)
1228-
update_scope_mapping!(scope_mapping, bb+1, scope_mapping[block_for_inst(compact, bbs)])
1229-
else
1230-
update_scope_mapping!(scope_mapping, bb+1, bbs)
1228+
# Here we want to count the number of scopes that we're leaving,
1229+
# which is the same as the number of EnterNodes being referenced
1230+
# by `stmt.args`. Which have :scope set. In practice, the frontend
1231+
# does emit these in order, so we could simply go to the last one,
1232+
# but we want to avoid making that semantic assumption.
1233+
for i = 1:length(stmt.args)
1234+
scope = stmt.args[i]
1235+
scope === nothing && continue
1236+
enter = compact[scope][:inst]
1237+
@assert isa(enter, EnterNode)
1238+
isdefined(enter, :scope) || continue
1239+
bbs = scope_mapping[block_for_inst(compact, bbs)]
1240+
end
12311241
end
1242+
update_scope_mapping!(scope_mapping, bb+1, bbs)
12321243
end
12331244
# check whether this statement is `getfield` / `setfield!` (or other "interesting" statement)
12341245
is_setfield = is_isdefined = is_finalizer = is_keyvalue_get = false

test/compiler/irpasses.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1801,3 +1801,22 @@ let n = 1000
18011801
end
18021802
end
18031803
@test f_1000_blocks() == 0
1804+
1805+
# https://github.com/JuliaLang/julia/issues/53521
1806+
# Incorrect scope counting in :leave
1807+
using Base.ScopedValues
1808+
function f53521()
1809+
VALUE = ScopedValue(1)
1810+
@with VALUE => 2 begin
1811+
for i = 1
1812+
@with VALUE => 3 begin
1813+
try
1814+
foo()
1815+
catch
1816+
nothing
1817+
end
1818+
end
1819+
end
1820+
end
1821+
end
1822+
@test code_typed(f53521)[1][2] === Nothing

0 commit comments

Comments
 (0)