Skip to content

Commit 0551039

Browse files
authored
inference: don't allocate TryCatchFrame for compute_trycatch(::IRCode) (#56835)
`TryCatchFrame` is only required for the abstract interpretation and is not necessary in `compute_trycatch` within slot2ssa.jl. @nanosoldier `runbenchmarks("inference", vs=":master")`
1 parent dafaa61 commit 0551039

File tree

3 files changed

+38
-17
lines changed

3 files changed

+38
-17
lines changed

Compiler/src/inferencestate.jl

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -219,16 +219,29 @@ const CACHE_MODE_GLOBAL = 0x01 << 0 # cached globally, optimization required
219219
const CACHE_MODE_LOCAL = 0x01 << 1 # cached locally, optimization required
220220
const CACHE_MODE_VOLATILE = 0x01 << 2 # not cached, optimization required
221221

222-
mutable struct TryCatchFrame
222+
abstract type Handler end
223+
get_enter_idx(handler::Handler) = get_enter_idx_impl(handler)::Int
224+
225+
mutable struct TryCatchFrame <: Handler
223226
exct
224227
scopet
225228
const enter_idx::Int
226229
scope_uses::Vector{Int}
227-
TryCatchFrame(@nospecialize(exct), @nospecialize(scopet), enter_idx::Int) = new(exct, scopet, enter_idx)
230+
TryCatchFrame(@nospecialize(exct), @nospecialize(scopet), enter_idx::Int) =
231+
new(exct, scopet, enter_idx)
232+
end
233+
TryCatchFrame(stmt::EnterNode, pc::Int) =
234+
TryCatchFrame(Bottom, isdefined(stmt, :scope) ? Bottom : nothing, pc)
235+
get_enter_idx_impl((; enter_idx)::TryCatchFrame) = enter_idx
236+
237+
struct SimpleHandler <: Handler
238+
enter_idx::Int
228239
end
240+
SimpleHandler(::EnterNode, pc::Int) = SimpleHandler(pc)
241+
get_enter_idx_impl((; enter_idx)::SimpleHandler) = enter_idx
229242

230-
struct HandlerInfo
231-
handlers::Vector{TryCatchFrame}
243+
struct HandlerInfo{T<:Handler}
244+
handlers::Vector{T}
232245
handler_at::Vector{Tuple{Int,Int}} # tuple of current (handler, exception stack) value at the pc
233246
end
234247

@@ -261,7 +274,7 @@ mutable struct InferenceState
261274
currbb::Int
262275
currpc::Int
263276
ip::BitSet#=TODO BoundedMinPrioritySet=# # current active instruction pointers
264-
handler_info::Union{Nothing,HandlerInfo}
277+
handler_info::Union{Nothing,HandlerInfo{TryCatchFrame}}
265278
ssavalue_uses::Vector{BitSet} # ssavalue sparsity and restart info
266279
# TODO: Could keep this sparsely by doing structural liveness analysis ahead of time.
267280
bb_vartables::Vector{Union{Nothing,VarTable}} # nothing if not analyzed yet
@@ -318,7 +331,7 @@ mutable struct InferenceState
318331

319332
currbb = currpc = 1
320333
ip = BitSet(1) # TODO BitSetBoundedMinPrioritySet(1)
321-
handler_info = compute_trycatch(code)
334+
handler_info = ComputeTryCatch{TryCatchFrame}()(code)
322335
nssavalues = src.ssavaluetypes::Int
323336
ssavalue_uses = find_ssavalue_uses(code, nssavalues)
324337
nstmts = length(code)
@@ -421,10 +434,16 @@ is_inferred(result::InferenceResult) = result.result !== nothing
421434

422435
was_reached(sv::InferenceState, pc::Int) = sv.ssavaluetypes[pc] !== NOT_FOUND
423436

424-
compute_trycatch(ir::IRCode) = compute_trycatch(ir.stmts.stmt, ir.cfg.blocks)
437+
struct ComputeTryCatch{T<:Handler} end
438+
439+
const compute_trycatch = ComputeTryCatch{SimpleHandler}()
440+
441+
(compute_trycatch::ComputeTryCatch{SimpleHandler})(ir::IRCode) =
442+
compute_trycatch(ir.stmts.stmt, ir.cfg.blocks)
425443

426444
"""
427-
compute_trycatch(code, [, bbs]) -> handler_info::Union{Nothing,HandlerInfo}
445+
(::ComputeTryCatch{Handler})(code, [, bbs]) -> handler_info::Union{Nothing,HandlerInfo{Handler}}
446+
const compute_trycatch = ComputeTryCatch{SimpleHandler}()
428447
429448
Given the code of a function, compute, at every statement, the current
430449
try/catch handler, and the current exception stack top. This function returns
@@ -433,9 +452,9 @@ a tuple of:
433452
1. `handler_info.handler_at`: A statement length vector of tuples
434453
`(catch_handler, exception_stack)`, which are indices into `handlers`
435454
436-
2. `handler_info.handlers`: A `TryCatchFrame` vector of handlers
455+
2. `handler_info.handlers`: A `Handler` vector of handlers
437456
"""
438-
function compute_trycatch(code::Vector{Any}, bbs::Union{Vector{BasicBlock},Nothing}=nothing)
457+
function (::ComputeTryCatch{Handler})(code::Vector{Any}, bbs::Union{Vector{BasicBlock},Nothing}=nothing) where Handler
439458
# The goal initially is to record the frame like this for the state at exit:
440459
# 1: (enter 3) # == 0
441460
# 3: (expr) # == 1
@@ -454,10 +473,10 @@ function compute_trycatch(code::Vector{Any}, bbs::Union{Vector{BasicBlock},Nothi
454473
stmt = code[pc]
455474
if isa(stmt, EnterNode)
456475
(;handlers, handler_at) = handler_info =
457-
(handler_info === nothing ? HandlerInfo(TryCatchFrame[], fill((0, 0), n)) : handler_info)
476+
(handler_info === nothing ? HandlerInfo{Handler}(Handler[], fill((0, 0), n)) : handler_info)
458477
l = stmt.catch_dest
459478
(bbs !== nothing) && (l = first(bbs[l].stmts))
460-
push!(handlers, TryCatchFrame(Bottom, isdefined(stmt, :scope) ? Bottom : nothing, pc))
479+
push!(handlers, Handler(stmt, pc))
461480
handler_id = length(handlers)
462481
handler_at[pc + 1] = (handler_id, 0)
463482
push!(ip, pc + 1)
@@ -526,7 +545,7 @@ function compute_trycatch(code::Vector{Any}, bbs::Union{Vector{BasicBlock},Nothi
526545
end
527546
cur_hand = cur_stacks[1]
528547
for i = 1:l
529-
cur_hand = handler_at[handlers[cur_hand].enter_idx][1]
548+
cur_hand = handler_at[get_enter_idx(handlers[cur_hand])][1]
530549
end
531550
cur_stacks = (cur_hand, cur_stacks[2])
532551
cur_stacks == (0, 0) && break

Compiler/src/ssair/slot2ssa.jl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -801,9 +801,11 @@ function construct_ssa!(ci::CodeInfo, ir::IRCode, sv::OptimizationState,
801801
has_pinode[id] = false
802802
enter_idx = idx
803803
while (handler = gethandler(handler_info, enter_idx)) !== nothing
804-
(; enter_idx) = handler
805-
leave_block = block_for_inst(cfg, (code[enter_idx]::EnterNode).catch_dest)
806-
cidx = findfirst((; slot)::NewPhiCNode2->slot_id(slot)==id, new_phic_nodes[leave_block])
804+
enter_idx = get_enter_idx(handler)
805+
enter_node = code[enter_idx]::EnterNode
806+
leave_block = block_for_inst(cfg, enter_node.catch_dest)
807+
cidx = findfirst((; slot)::NewPhiCNode2->slot_id(slot)==id,
808+
new_phic_nodes[leave_block])
807809
if cidx !== nothing
808810
node = thisdef ? UpsilonNode(thisval) : UpsilonNode()
809811
if incoming_vals[id] === UNDEF_TOKEN

Compiler/test/inference.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4436,7 +4436,7 @@ let x = Tuple{Int,Any}[
44364436
#=20=# (0, Core.ReturnNode(Core.SlotNumber(3)))
44374437
]
44384438
(;handler_at, handlers) = Compiler.compute_trycatch(last.(x))
4439-
@test map(x->x[1] == 0 ? 0 : handlers[x[1]].enter_idx, handler_at) == first.(x)
4439+
@test map(x->x[1] == 0 ? 0 : Compiler.get_enter_idx(handlers[x[1]]), handler_at) == first.(x)
44404440
end
44414441

44424442
@test only(Base.return_types((Bool,)) do y

0 commit comments

Comments
 (0)