Skip to content

Commit a811406

Browse files
authored
EA: minor updates on EA (#51365)
- update outdated test code - add more comments on TODO items - use `MethodInstance` for better frame-identity check - minor cleanups on the inlining code
1 parent 3e9e3be commit a811406

File tree

4 files changed

+22
-24
lines changed

4 files changed

+22
-24
lines changed

base/compiler/ssair/EscapeAnalysis/EscapeAnalysis.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,7 @@ function escape_exception!(astate::AnalysisState, tryregions::Vector{UnitRange{I
10961096
# NOTE if `:the_exception` is the only way to access the exception, we can do:
10971097
# exc = SSAValue(pc)
10981098
# excinfo = estate[exc]
1099+
# TODO? set up a special effect bit that checks the existence of `rethrow` and `current_exceptions` and use it here
10991100
excinfo =
11001101
escapes = estate.escapes
11011102
for i in 1:length(escapes)

base/compiler/ssair/inlining.jl

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,9 @@ function cfg_inline_item!(ir::IRCode, idx::Int, todo::InliningTodo, state::CFGIn
211211
return nothing
212212
end
213213

214-
function cfg_inline_unionsplit!(ir::IRCode, idx::Int,
215-
(; fully_covered, #=atype,=# cases, bbs)::UnionSplit,
216-
state::CFGInliningState,
217-
params::OptimizationParams)
214+
function cfg_inline_unionsplit!(ir::IRCode, idx::Int, union_split::UnionSplit,
215+
state::CFGInliningState, params::OptimizationParams)
216+
(; fully_covered, #=atype,=# cases, bbs) = union_split
218217
inline_into_block!(state, block_for_inst(ir, idx))
219218
from_bbs = Int[]
220219
delete!(state.split_targets, length(state.new_cfg_blocks))
@@ -234,9 +233,7 @@ function cfg_inline_unionsplit!(ir::IRCode, idx::Int,
234233
end
235234
end
236235
push!(from_bbs, length(state.new_cfg_blocks))
237-
# TODO: Right now we unconditionally generate a fallback block
238-
# in case of subtyping errors - This is probably unnecessary.
239-
if i != length(cases) || (!fully_covered)
236+
if !(i == length(cases) && fully_covered)
240237
# This block will have the next condition or the final else case
241238
push!(state.new_cfg_blocks, BasicBlock(StmtRange(idx, idx)))
242239
push!(state.new_cfg_blocks[cond_bb].succs, length(state.new_cfg_blocks))
@@ -582,7 +579,7 @@ function ir_inline_unionsplit!(compact::IncrementalCompact, idx::Int, argexprs::
582579
cond = true
583580
nparams = fieldcount(atype)
584581
@assert nparams == fieldcount(mtype)
585-
if i != ncases || !fully_covered
582+
if !(i == ncases && fully_covered)
586583
for i = 1:nparams
587584
a, m = fieldtype(atype, i), fieldtype(mtype, i)
588585
# If this is always true, we don't need to check for it
@@ -1475,7 +1472,7 @@ function handle_match!(cases::Vector{InliningCase},
14751472
# We may see duplicated dispatch signatures here when a signature gets widened
14761473
# during abstract interpretation: for the purpose of inlining, we can just skip
14771474
# processing this dispatch candidate (unless unmatched type parameters are present)
1478-
!allow_typevars && _any(case->case.sig === spec_types, cases) && return true
1475+
!allow_typevars && any(case::InliningCase->case.sig === spec_types, cases) && return true
14791476
item = analyze_method!(match, argtypes, info, flag, state; allow_typevars)
14801477
item === nothing && return false
14811478
push!(cases, InliningCase(spec_types, item))

test/compiler/EscapeAnalysis/EAUtils.jl

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,10 @@ function code_escapes(@nospecialize(f), @nospecialize(types=Base.default_tt(f));
4141
world::UInt = get_world_counter(),
4242
debuginfo::Symbol = :none)
4343
tt = Base.signature_type(f, types)
44-
interp = EscapeAnalyzer(world, tt)
45-
results = Base.code_typed_by_type(tt; optimize=true, world, interp)
46-
isone(length(results)) || throw(ArgumentError("`code_escapes` only supports single analysis result"))
44+
match = Base._which(tt; world, raise=true)
45+
mi = Core.Compiler.specialize_method(match)::MethodInstance
46+
interp = EscapeAnalyzer(world, mi)
47+
Core.Compiler.typeinf_ext(interp, mi)
4748
return EscapeResult(interp.ir, interp.estate, interp.mi, debuginfo === :source, interp)
4849
end
4950

@@ -93,17 +94,17 @@ mutable struct EscapeAnalyzer <: AbstractInterpreter
9394
const inf_cache::Vector{InferenceResult}
9495
const code_cache::CodeCache
9596
const escape_cache::EscapeCache
96-
const entry_tt
97+
const entry_mi::MethodInstance
9798
ir::IRCode
9899
estate::EscapeState
99100
mi::MethodInstance
100-
function EscapeAnalyzer(world::UInt, @nospecialize(tt),
101+
function EscapeAnalyzer(world::UInt, entry_mi::MethodInstance,
101102
code_cache::CodeCache=GLOBAL_CODE_CACHE,
102103
escape_cache::EscapeCache=GLOBAL_ESCAPE_CACHE)
103104
inf_params = InferenceParams()
104105
opt_params = OptimizationParams()
105106
inf_cache = InferenceResult[]
106-
return new(world, inf_params, opt_params, inf_cache, code_cache, escape_cache, tt)
107+
return new(world, inf_params, opt_params, inf_cache, code_cache, escape_cache, entry_mi)
107108
end
108109
end
109110

@@ -210,10 +211,10 @@ function run_passes_ipo_safe_with_ea(interp::EscapeAnalyzer,
210211
@timeit "EA" estate = analyze_escapes(ir, nargs, get_escape_cache)
211212
catch err
212213
@error "error happened within EA, inspect `Main.failed_escapeanalysis`"
213-
@eval Main failed_escapeanalysis = $(FailedAnalysis(ir, nargs, get_escape_cache))
214+
Main.failed_escapeanalysis = FailedAnalysis(ir, nargs, get_escape_cache)
214215
rethrow(err)
215216
end
216-
if caller.linfo.specTypes === interp.entry_tt
217+
if caller.linfo === interp.entry_mi
217218
# return back the result
218219
interp.ir = cccopy(ir)
219220
interp.estate = estate

test/compiler/EscapeAnalysis/EscapeAnalysis.jl

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,13 @@ end
7474
@testset "basics" begin
7575
let # arg return
7676
result = code_escapes((Any,)) do a # return to caller
77-
Base.donotdelete(1) # TODO #51143
77+
println("prevent ConstABI")
7878
return nothing
7979
end
8080
@test has_arg_escape(result.state[Argument(2)])
8181
# return
8282
result = code_escapes((Any,)) do a
83+
println("prevent ConstABI")
8384
return a
8485
end
8586
i = only(findall(isreturn, result.ir.stmts.stmt))
@@ -114,9 +115,9 @@ end
114115
end
115116
let # :gc_preserve_begin / :gc_preserve_end
116117
result = code_escapes((String,)) do s
117-
Base.donotdelete(1) # TODO #51143
118118
m = SafeRef(s)
119119
GC.@preserve m begin
120+
println(s)
120121
return nothing
121122
end
122123
end
@@ -125,7 +126,7 @@ end
125126
@test has_no_escape(result.state[SSAValue(i)])
126127
end
127128
let # :isdefined
128-
result = code_escapes((String, Bool, )) do a, b
129+
result = code_escapes((String, Bool,)) do a, b
129130
if b
130131
s = Ref(a)
131132
end
@@ -510,7 +511,7 @@ end
510511
end
511512
i = only(findall(isnew, result.ir.stmts.stmt))
512513
r = only(findall(isreturn, result.ir.stmts.stmt))
513-
@test_broken !has_return_escape(result.state[SSAValue(i)], r)
514+
@test_broken !has_return_escape(result.state[SSAValue(i)], r) # TODO? see `escape_exception!`
514515
end
515516
let # sequential: escape information imposed on `err1` and `err2 should propagate separately
516517
result = @eval M $code_escapes() do
@@ -537,7 +538,7 @@ end
537538
r = only(findall(isreturn, result.ir.stmts.stmt))
538539
@test has_all_escape(result.state[SSAValue(i1)])
539540
@test has_return_escape(result.state[SSAValue(i2)], r)
540-
@test_broken !has_all_escape(result.state[SSAValue(i2)])
541+
@test_broken !has_all_escape(result.state[SSAValue(i2)]) # TODO? see `escape_exception!`
541542
end
542543
let # nested: escape information imposed on `inner` shouldn't propagate to `s`
543544
result = @eval M $code_escapes() do
@@ -2350,13 +2351,11 @@ end
23502351
# no method error
23512352
@noinline identity_if_string(x::SafeRef) = (println("preventing inlining"); nothing)
23522353
let result = code_escapes((SafeRef{String},)) do x
2353-
Base.donotdelete(1) # TODO #51143
23542354
identity_if_string(x)
23552355
end
23562356
@test has_no_escape(ignore_argescape(result.state[Argument(2)]))
23572357
end
23582358
let result = code_escapes((Union{SafeRef{String},Nothing},)) do x
2359-
Base.donotdelete(1) # TODO #51143
23602359
identity_if_string(x)
23612360
end
23622361
i = only(findall(iscall((result.ir, identity_if_string)), result.ir.stmts.stmt))

0 commit comments

Comments
 (0)