Skip to content

Commit 82820ee

Browse files
committed
optimizer: do not delete statements that may not :terminate
1 parent 2345411 commit 82820ee

File tree

2 files changed

+44
-5
lines changed

2 files changed

+44
-5
lines changed

base/compiler/optimize.jl

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ const IR_FLAG_INACCESSIBLEMEM_OR_ARGMEM = one(UInt32) << 11
4848
const NUM_IR_FLAGS = 12 # sync with julia.h
4949

5050
const IR_FLAGS_EFFECTS =
51-
IR_FLAG_CONSISTENT | IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW | IR_FLAG_NOUB
51+
IR_FLAG_CONSISTENT | IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW | IR_FLAG_TERMINATES | IR_FLAG_NOUB
5252

53-
const IR_FLAGS_REMOVABLE = IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW
53+
const IR_FLAGS_REMOVABLE = IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW | IR_FLAG_TERMINATES
5454

5555
const IR_FLAGS_NEEDS_EA = IR_FLAG_EFIIMO | IR_FLAG_INACCESSIBLEMEM_OR_ARGMEM
5656

@@ -69,6 +69,9 @@ function flags_for_effects(effects::Effects)
6969
if is_nothrow(effects)
7070
flags |= IR_FLAG_NOTHROW
7171
end
72+
if is_terminates(effects)
73+
flags |= IR_FLAG_TERMINATES
74+
end
7275
if is_inaccessiblemem_or_argmemonly(effects)
7376
flags |= IR_FLAG_INACCESSIBLEMEM_OR_ARGMEM
7477
end
@@ -338,7 +341,8 @@ function stmt_effect_flags(𝕃ₒ::AbstractLattice, @nospecialize(stmt), @nospe
338341
consistent = is_consistent(effects)
339342
effect_free = is_effect_free(effects)
340343
nothrow = is_nothrow(effects)
341-
removable = effect_free & nothrow
344+
terminates = is_terminates(effects)
345+
removable = effect_free & nothrow & terminates
342346
return (consistent, removable, nothrow)
343347
elseif head === :new
344348
return new_expr_effect_flags(𝕃ₒ, args, src)
@@ -349,7 +353,8 @@ function stmt_effect_flags(𝕃ₒ::AbstractLattice, @nospecialize(stmt), @nospe
349353
consistent = is_consistent(effects)
350354
effect_free = is_effect_free(effects)
351355
nothrow = is_nothrow(effects)
352-
removable = effect_free & nothrow
356+
terminates = is_terminates(effects)
357+
removable = effect_free & nothrow & terminates
353358
return (consistent, removable, nothrow)
354359
elseif head === :new_opaque_closure
355360
length(args) < 4 && return (false, false, false)

test/compiler/irpasses.jl

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1562,7 +1562,7 @@ function persistent_dict_elim_multiple()
15621562
end
15631563
@test_broken fully_eliminated(persistent_dict_elim_multiple)
15641564
let code = code_typed(persistent_dict_elim_multiple)[1][1].code
1565-
@test count(x->isexpr(x, :invoke), code) == 0
1565+
@test_broken count(x->isexpr(x, :invoke), code) == 0
15661566
@test code[end] == Core.ReturnNode(1)
15671567
end
15681568

@@ -1781,3 +1781,37 @@ let code = Any[
17811781
@test !any(iscall((ir, getfield)), ir.stmts.stmt)
17821782
@test length(ir.cfg.blocks[end].stmts) == 1
17831783
end
1784+
1785+
# JuliaLang/julia#52991: statements that may not :terminate should not be deleted
1786+
@noinline Base.@assume_effects :effect_free :nothrow function issue52991(n)
1787+
local s = 0
1788+
try
1789+
while true
1790+
yield()
1791+
if n - rand(1:10) > 0
1792+
s += 1
1793+
else
1794+
break
1795+
end
1796+
end
1797+
catch
1798+
end
1799+
return s
1800+
end
1801+
@test !Core.Compiler.is_removable_if_unused(Base.infer_effects(issue52991, (Int,)))
1802+
let src = code_typed1(issue52991, (Int,))
1803+
@test count(isinvoke(:issue52991), src.code) == 0
1804+
end
1805+
let t = @async begin
1806+
issue52991(11) # this call never terminates
1807+
nothing
1808+
end
1809+
sleep(1)
1810+
if istaskdone(t)
1811+
ok = false
1812+
else
1813+
ok = true
1814+
schedule(t, InterruptException(); error=true)
1815+
end
1816+
@test ok
1817+
end

0 commit comments

Comments
 (0)