Skip to content

Commit

Permalink
slot2ssa: remove TypedSlot (JuliaLang#50943)
Browse files Browse the repository at this point in the history
Dependent on JuliaLang#50924 .

This removes the last remaining usage of `TypedSlot`.
As a bonus, this evicts all of the "tmerge" type-iteration that was
being done in slot2ssa.

---------

Co-authored-by: Shuhei Kadowaki <[email protected]>
  • Loading branch information
topolarity and aviatesk committed Aug 25, 2023
1 parent 4ac6b05 commit 5e5416a
Show file tree
Hide file tree
Showing 12 changed files with 169 additions and 284 deletions.
4 changes: 3 additions & 1 deletion base/compiler/inferencestate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ mutable struct InferenceState

#= results =#
result::InferenceResult # remember where to put the result
unreachable::BitSet # statements that were found to be statically unreachable
valid_worlds::WorldRange
bestguess #::Type
ipo_effects::Effects
Expand Down Expand Up @@ -278,6 +279,7 @@ mutable struct InferenceState
end
src.ssavaluetypes = ssavaluetypes = Any[ NOT_FOUND for i = 1:nssavalues ]

unreachable = BitSet()
pclimitations = IdSet{InferenceState}()
limitations = IdSet{InferenceState}()
cycle_backedges = Vector{Tuple{InferenceState,Int}}()
Expand Down Expand Up @@ -306,7 +308,7 @@ mutable struct InferenceState
linfo, world, mod, sptypes, slottypes, src, cfg, method_info,
currbb, currpc, ip, handler_at, ssavalue_uses, bb_vartables, ssavaluetypes, stmt_edges, stmt_info,
pclimitations, limitations, cycle_backedges, callers_in_cycle, dont_work_on_me, parent,
result, valid_worlds, bestguess, ipo_effects,
result, unreachable, valid_worlds, bestguess, ipo_effects,
restrict_abstract_call_sites, cached, insert_coverage,
interp)
end
Expand Down
66 changes: 49 additions & 17 deletions base/compiler/optimize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,15 @@ mutable struct OptimizationState{Interp<:AbstractInterpreter}
slottypes::Vector{Any}
inlining::InliningState{Interp}
cfg::CFG
unreachable::BitSet
bb_vartables::Vector{Union{Nothing,VarTable}}
insert_coverage::Bool
end
function OptimizationState(sv::InferenceState, interp::AbstractInterpreter)
inlining = InliningState(sv, interp)
return OptimizationState(sv.linfo, sv.src, nothing, sv.stmt_info, sv.mod,
sv.sptypes, sv.slottypes, inlining, sv.cfg, sv.insert_coverage)
sv.sptypes, sv.slottypes, inlining, sv.cfg,
sv.unreachable, sv.bb_vartables, sv.insert_coverage)
end
function OptimizationState(linfo::MethodInstance, src::CodeInfo, interp::AbstractInterpreter)
# prepare src for running optimization passes if it isn't already
Expand All @@ -159,7 +162,15 @@ function OptimizationState(linfo::MethodInstance, src::CodeInfo, interp::Abstrac
# This method is mostly used for unit testing the optimizer
inlining = InliningState(interp)
cfg = compute_basic_blocks(src.code)
return OptimizationState(linfo, src, nothing, stmt_info, mod, sptypes, slottypes, inlining, cfg, false)
unreachable = BitSet()
bb_vartables = Union{VarTable,Nothing}[]
for block = 1:length(cfg.blocks)
push!(bb_vartables, VarState[
VarState(slottypes[slot], src.slotflags[slot] & SLOT_USEDUNDEF != 0)
for slot = 1:nslots
])
end
return OptimizationState(linfo, src, nothing, stmt_info, mod, sptypes, slottypes, inlining, cfg, unreachable, bb_vartables, false)
end
function OptimizationState(linfo::MethodInstance, interp::AbstractInterpreter)
world = get_world_counter(interp)
Expand All @@ -168,7 +179,6 @@ function OptimizationState(linfo::MethodInstance, interp::AbstractInterpreter)
return OptimizationState(linfo, src, interp)
end


include("compiler/ssair/driver.jl")

function ir_to_codeinf!(opt::OptimizationState)
Expand Down Expand Up @@ -328,7 +338,7 @@ function stmt_effect_flags(𝕃ₒ::AbstractLattice, @nospecialize(stmt), @nospe
return (false, false, false)
end
end
isa(stmt, UnoptSlot) && error("unexpected IR elements")
isa(stmt, SlotNumber) && error("unexpected IR elements")
return (true, true, true)
end

Expand Down Expand Up @@ -363,8 +373,6 @@ function argextype(
@assert false
elseif isa(x, SlotNumber)
return slottypes[x.id]
elseif isa(x, TypedSlot)
return x.typ
elseif isa(x, SSAValue)
return abstract_eval_ssavalue(x, src)
elseif isa(x, Argument)
Expand Down Expand Up @@ -523,12 +531,39 @@ function convert_to_ircode(ci::CodeInfo, sv::OptimizationState)
linetable = collect(LineInfoNode, linetable::Vector{Any})::Vector{LineInfoNode}
end

# Update control-flow to reflect any unreachable branches.
ssavaluetypes = ci.ssavaluetypes::Vector{Any}
code = copy_exprargs(ci.code)
for i = 1:length(code)
expr = code[i]
if !(i in sv.unreachable) && isa(expr, GotoIfNot)
# Replace this live GotoIfNot with:
# - no-op if :nothrow and the branch target is unreachable
# - cond if :nothrow and both targets are unreachable
# - typeassert if must-throw
if widenconst(argextype(expr.cond, ci, sv.sptypes)) === Bool
block = block_for_inst(sv.cfg, i)
if i + 1 in sv.unreachable
cfg_delete_edge!(sv.cfg, block, block + 1)
expr = GotoNode(expr.dest)
elseif expr.dest in sv.unreachable
cfg_delete_edge!(sv.cfg, block, block_for_inst(sv.cfg, expr.dest))
expr = nothing
end
elseif ssavaluetypes[i] === Bottom
block = block_for_inst(sv.cfg, i)
cfg_delete_edge!(sv.cfg, block, block + 1)
cfg_delete_edge!(sv.cfg, block, block_for_inst(sv.cfg, expr.dest))
expr = Expr(:call, Core.typeassert, expr.cond, Bool)
end
code[i] = expr
end
end

# Go through and add an unreachable node after every
# Union{} call. Then reindex labels.
code = copy_exprargs(ci.code)
stmtinfo = sv.stmt_info
codelocs = ci.codelocs
ssavaluetypes = ci.ssavaluetypes::Vector{Any}
ssaflags = ci.ssaflags
meta = Expr[]
idx = 1
Expand Down Expand Up @@ -562,8 +597,8 @@ function convert_to_ircode(ci::CodeInfo, sv::OptimizationState)
idx += 1
prevloc = codeloc
end
if ssavaluetypes[idx] === Union{} && !(code[idx] isa Core.Const)
# Type inference should have converted any must-throw terminators to an equivalent w/o control-flow edges
if ssavaluetypes[idx] === Union{} && !(oldidx in sv.unreachable)
# We should have converted any must-throw terminators to an equivalent w/o control-flow edges
@assert !isterminator(code[idx])

block = block_for_inst(sv.cfg, oldidx)
Expand All @@ -589,8 +624,8 @@ function convert_to_ircode(ci::CodeInfo, sv::OptimizationState)

# Verify that type-inference did its job
if JLOptions().debug_level == 2
for i = (idx + 1):(block_end - 1)
@assert (code[i] isa Core.Const) || is_meta_expr(code[i])
for i = (oldidx + 1):last(sv.cfg.blocks[block].stmts)
@assert i in sv.unreachable
end
end

Expand Down Expand Up @@ -659,7 +694,7 @@ function slot2reg(ir::IRCode, ci::CodeInfo, sv::OptimizationState)
@timeit "domtree 1" domtree = construct_domtree(ir.cfg.blocks)
defuse_insts = scan_slot_def_use(nargs, ci, ir.stmts.stmt)
𝕃ₒ = optimizer_lattice(sv.inlining.interp)
@timeit "construct_ssa" ir = construct_ssa!(ci, ir, domtree, defuse_insts, sv.slottypes, 𝕃ₒ) # consumes `ir`
@timeit "construct_ssa" ir = construct_ssa!(ci, ir, sv, domtree, defuse_insts, 𝕃ₒ) # consumes `ir`
# NOTE now we have converted `ir` to the SSA form and eliminated slots
# let's resize `argtypes` now and remove unnecessary types for the eliminated slots
resize!(ir.argtypes, nargs)
Expand Down Expand Up @@ -888,10 +923,7 @@ function renumber_ir_elements!(body::Vector{Any}, ssachangemap::Vector{Int}, lab
end

function renumber_cfg_stmts!(cfg::CFG, blockchangemap::Vector{Int})
any_change = cumsum_ssamap!(blockchangemap)
any_change || return

last_end = 0
cumsum_ssamap!(blockchangemap) || return
for i = 1:length(cfg.blocks)
old_range = cfg.blocks[i].stmts
new_range = StmtRange(first(old_range) + ((i > 1) ? blockchangemap[i - 1] : 0),
Expand Down
4 changes: 0 additions & 4 deletions base/compiler/ssair/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,6 @@ function print_stmt(io::IO, idx::Int, @nospecialize(stmt), used::BitSet, maxleng
show_unquoted_phinode(io, stmt, indent, "#")
elseif stmt isa GotoIfNot
show_unquoted_gotoifnot(io, stmt, indent, "#")
elseif stmt isa TypedSlot
# call `show` with the type set to Any so it will not be shown, since
# we will show the type ourselves.
show_unquoted(io, SlotNumber(stmt.id), indent, show_type ? prec_decl : 0)
# everything else in the IR, defer to the generic AST printer
else
show_unquoted(io, stmt, indent, show_type ? prec_decl : 0)
Expand Down
Loading

0 comments on commit 5e5416a

Please sign in to comment.