diff --git a/test/compiler/EscapeAnalysis/local.jl b/test/compiler/EscapeAnalysis/local.jl index e5d8f1bf2c940..2076ea8c1db2b 100644 --- a/test/compiler/EscapeAnalysis/local.jl +++ b/test/compiler/EscapeAnalysis/local.jl @@ -2186,21 +2186,48 @@ end # @static if isdefined(Core, :ImmutableArray) end end -# # TODO implement a finalizer elision pass -# mutable struct WithFinalizer -# v -# function WithFinalizer(v) -# x = new(v) -# f(t) = @async println("Finalizing $t.") -# return finalizer(x, x) -# end -# end -# make_m(v = 10) = MyMutable(v) -# function simple(cond) -# m = make_m() -# if cond -# # println(m.v) -# return nothing # <= insert `finalize` call here -# end -# return m -# end +mutable struct WithFinalizer + v + function WithFinalizer(v) + x = new(v) + f(t) = @async println("Finalizing $t.") + return finalizer(f, x) + end +end +function simple(cond) + m = WithFinalizer(42) + if cond + # Should have a `finalize` call + return nothing + end + # Should not have a `finalize` call + return m +end +@testset "early finalization" begin + let result = code_escapes(simple, (Bool,)) + println(result) + alloc_idx = SSAValue(2) + @test isnew(result.ir.stmts.inst[2]) + info = result.state[alloc_idx] + dump(info) + @test !has_all_escape(info) + @test has_return_escape(info) + @test has_finalizer_escape(info) + + rs = findall(isreturn, result.ir.stmts.inst) + @test length(rs) == 2 + @test !has_return_escape(info, rs[1]) + @test has_return_escape(info, rs[2]) + for r in rs + @test isreturn(result.ir.stmts.inst[r]) + end + + finalizer_idx = findfirst(isfinalizer, result.ir.stmts.inst) + @test finalizer_idx !== nothing + + finalize_idx = findfirst(isfinalize, result.ir.stmts.inst) + @test finalize_idx !== nothing + # FIXME: Test that there is a `finalize` call dominating `rs[1]`, + # but not `rs[2]` + end +end diff --git a/test/compiler/EscapeAnalysis/setup.jl b/test/compiler/EscapeAnalysis/setup.jl index 4e7d6fb5159aa..7f07cbb763315 100644 --- a/test/compiler/EscapeAnalysis/setup.jl +++ b/test/compiler/EscapeAnalysis/setup.jl @@ -20,6 +20,8 @@ end isarrayalloc(@nospecialize x) = with_normalized_name(nn->!isnothing(Core.Compiler.alloc_array_ndims(nn)), x) isarrayresize(@nospecialize x) = with_normalized_name(nn->!isnothing(EA.array_resize_info(nn)), x) isarraycopy(@nospecialize x) = with_normalized_name(nn->EA.is_array_copy(nn), x) +isfinalizer(@nospecialize x) = with_normalized_name(nn->EA.is_finalizer(nn), x) +isfinalize(@nospecialize x) = with_normalized_name(nn->nn===:jl_finalize_th, x) import Core.Compiler: argextype, singleton_type iscall(y) = @nospecialize(x) -> iscall(y, x) function iscall((ir, f), @nospecialize(x))