Skip to content

Commit

Permalink
cleaner handlings of basic program constructs
Browse files Browse the repository at this point in the history
  • Loading branch information
aviatesk committed Dec 24, 2021
1 parent b2109fc commit 8bb874f
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 54 deletions.
35 changes: 18 additions & 17 deletions src/EscapeAnalysis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -277,26 +277,20 @@ function find_escapes(ir::IRCode, nargs::Int)
add_change!(x, ir, AllEscape(), changes)
end
end
elseif isa(stmt, GlobalRef) # global load
add_change!(SSAValue(pc), ir, AllEscape(), changes)
elseif isa(stmt, PiNode)
elseif isa(stmt, ReturnNode)
if isdefined(stmt, :val)
info = state.ssavalues[pc]
add_change!(stmt.val, ir, info, changes)
add_change!(stmt.val, ir, ReturnEscape(pc), changes)
end
elseif isa(stmt, PhiNode)
escape_backedges!(ir, pc, stmt.values, state, changes)
escape_edges!(ir, pc, stmt.values, state, changes)
elseif isa(stmt, PiNode)
escape_val!(ir, pc, stmt, state, changes)
elseif isa(stmt, PhiCNode)
escape_backedges!(ir, pc, stmt.values, state, changes)
escape_edges!(ir, pc, stmt.values, state, changes)
elseif isa(stmt, UpsilonNode)
if isdefined(stmt, :val)
info = state.ssavalues[pc]
add_change!(stmt.val, ir, info, changes)
end
elseif isa(stmt, ReturnNode)
if isdefined(stmt, :val)
add_change!(stmt.val, ir, ReturnEscape(pc), changes)
end
escape_val!(ir, pc, stmt, state, changes)
elseif isa(stmt, GlobalRef) # global load
add_change!(SSAValue(pc), ir, AllEscape(), changes)
elseif isa(stmt, SSAValue)
# NOTE after SROA, we may see SSA value as statement
info = state.ssavalues[pc]
Expand Down Expand Up @@ -353,8 +347,8 @@ function add_change!(@nospecialize(x), ir::IRCode, info::EscapeLattice, changes:
end
end

function escape_backedges!(ir::IRCode, pc::Int, backedges::Vector{Any},
state::EscapeState, changes::Changes)
function escape_edges!(ir::IRCode, pc::Int, backedges::Vector{Any},
state::EscapeState, changes::Changes)
info = state.ssavalues[pc]
for i in 1:length(backedges)
if isassigned(backedges, i)
Expand All @@ -363,6 +357,13 @@ function escape_backedges!(ir::IRCode, pc::Int, backedges::Vector{Any},
end
end

function escape_val!(ir::IRCode, pc::Int, x, state::EscapeState, changes::Changes)
if isdefined(x, :val)
info = state.ssavalues[pc]
add_change!(x.val, ir, info, changes)
end
end

function escape_call!(ir::IRCode, pc::Int, args::Vector{Any},
state::EscapeState, changes::Changes)
ft = argextype(first(args), ir, ir.sptypes, ir.argtypes)
Expand Down
91 changes: 54 additions & 37 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,27 @@ Base.setindex!(s::SafeRef{T}, x::T) where T = s.x = x
end
@test has_return_escape(result.state.arguments[2])
end

let # :return
let # return
result = analyze_escapes((Any,)) do a
return a
end
@test has_return_escape(result.state.arguments[1]) # self
@test has_return_escape(result.state.arguments[2]) # argument
end

let
# global store
let # global store
result = analyze_escapes((Any,)) do a
global aa = a
return nothing
nothing
end
@test has_all_escape(result.state.arguments[2])

# global load
result = analyze_escapes((Any,)) do a
global gr
(gr::SafeRef{Any})[] = a
nothing
end
@test has_all_escape(result.state.arguments[2])
end
let # global load
result = analyze_escapes() do
global gr
return gr
Expand All @@ -50,8 +53,8 @@ Base.setindex!(s::SafeRef{T}, x::T) where T = s.x = x
(gr::SafeRef{Any})[] = a
end
@test has_all_escape(result.state.arguments[2])

# global store / load (https://github.com/aviatesk/EscapeAnalysis.jl/issues/56)
end
let # global store / load (https://github.com/aviatesk/EscapeAnalysis.jl/issues/56)
result = analyze_escapes((Any,)) do s
global v
v = s
Expand All @@ -60,7 +63,6 @@ Base.setindex!(s::SafeRef{T}, x::T) where T = s.x = x
r = findfirst(isreturn, result.ir.stmts.inst)::Int
@test has_return_escape(result.state.arguments[2], r)
end

let # :gc_preserve_begin / :gc_preserve_end
result = analyze_escapes((String,)) do s
m = SafeRef(s)
Expand All @@ -72,7 +74,6 @@ Base.setindex!(s::SafeRef{T}, x::T) where T = s.x = x
@test !isnothing(i)
@test has_no_escape(result.state.ssavalues[i])
end

let # :isdefined
result = analyze_escapes((String, Bool, )) do a, b
if b
Expand All @@ -84,24 +85,49 @@ Base.setindex!(s::SafeRef{T}, x::T) where T = s.x = x
@test !isnothing(i)
@test has_no_escape(result.state.ssavalues[i])
end

let # :foreigncall
result = analyze_escapes((Vector{String}, Int, )) do a, b
return isassigned(a, b) # TODO: specialize isassigned
end
@test has_all_escape(result.state.arguments[2])
end

# https://github.com/aviatesk/EscapeAnalysis.jl/pull/16
let # don't propagate escape information for bitypes
result = analyze_escapes((Nothing,)) do a
global bb = a
let # ϕ-node
result = analyze_escapes((Bool,Any,Any)) do cond, a, b
c = cond ? a : b # ϕ(a, b)
return c
end
@test !(has_all_escape(result.state.arguments[2]))
@assert any(@nospecialize(x)->isa(x, Core.PhiNode), result.ir.stmts.inst)
i = findfirst(isreturn, result.ir.stmts.inst)::Int
@test has_return_escape(result.state.arguments[3], i) # a
@test has_return_escape(result.state.arguments[4], i) # b
end
let # π-node
result = analyze_escapes((Any,)) do a
if isa(a, Regex) # a::π(Regex)
return a
end
return nothing
end
@assert any(@nospecialize(x)->isa(x, Core.PiNode), result.ir.stmts.inst)
i = findfirst(isreturn, result.ir.stmts.inst)::Int
@test has_return_escape(result.state.arguments[2], i)
end
let # φᶜ-node / ϒ-node
result = analyze_escapes((Any,String)) do a, b
local x::String
try
x = a
catch err
x = b
end
return x
end
@assert any(@nospecialize(x)->isa(x, Core.PhiCNode), result.ir.stmts.inst)
@assert any(@nospecialize(x)->isa(x, Core.UpsilonNode), result.ir.stmts.inst)
i = findfirst(isreturn, result.ir.stmts.inst)::Int
@test has_return_escape(result.state.arguments[2], i)
@test has_return_escape(result.state.arguments[3], i)
end
end

@testset "control flows" begin
let # branching
result = analyze_escapes((Any,Bool,)) do a, c
if c
Expand All @@ -112,20 +138,6 @@ end
end
@test has_return_escape(result.state.arguments[2])
end

let # π node
result = analyze_escapes((Any,)) do a
if isa(a, Regex)
identity(a) # compiler will introduce π node here
return a # return escape !
else
return nothing
end
end
@assert any(@nospecialize(x)->isa(x, Core.PiNode), result.ir.stmts.inst)
@test has_return_escape(result.state.arguments[2])
end

let # loop
result = analyze_escapes((Int,)) do n
c = SafeRef{Bool}(false)
Expand All @@ -137,7 +149,6 @@ end
i = findfirst(isT(SafeRef{Bool}), result.ir.stmts.type)::Int
@test has_return_escape(result.state.ssavalues[i])
end

let # exception
result = analyze_escapes((Any,)) do a
try
Expand Down Expand Up @@ -498,6 +509,12 @@ end
# demonstrate a simple type level analysis can sometimes improve the analysis accuracy
# by compensating the lack of yet unimplemented analyses
@testset "special-casing bitstype" begin
let result = analyze_escapes((Nothing,)) do a
global bb = a
end
@test !(has_all_escape(result.state.arguments[2]))
end

let result = analyze_escapes((Int,)) do a
o = SafeRef(a) # no need to escape
f = o[]
Expand Down

0 comments on commit 8bb874f

Please sign in to comment.