Skip to content

Commit 73cd069

Browse files
committed
slot2ssa: Remove usage of SLOT_USEDUNDEF
Updates slot2ssa to use the `bb_vartables` for `undef` information. As a bonus, evicts the final usage of `tmerge` in slot2ssa. This also fixes a few crashes from the prior commit, esp. where I was emitting PiNode(UndefToken(), Union{}) or where the PhiC nodes were not being ordered correctly.
1 parent 3561089 commit 73cd069

File tree

3 files changed

+55
-100
lines changed

3 files changed

+55
-100
lines changed

base/compiler/optimize.jl

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ end
136136
function OptimizationState(sv::InferenceState, interp::AbstractInterpreter)
137137
inlining = InliningState(sv, interp)
138138
return OptimizationState(sv.linfo, sv.src, nothing, sv.stmt_info, sv.mod,
139-
sv.sptypes, sv.slottypes, inlining, sv.cfg, sv.bb_vartables,
140-
sv.insert_coverage)
139+
sv.sptypes, sv.slottypes, inlining, sv.cfg,
140+
sv.bb_vartables, sv.insert_coverage)
141141
end
142142
function OptimizationState(linfo::MethodInstance, src::CodeInfo, interp::AbstractInterpreter)
143143
# prepare src for running optimization passes if it isn't already
@@ -161,7 +161,13 @@ function OptimizationState(linfo::MethodInstance, src::CodeInfo, interp::Abstrac
161161
# This method is mostly used for unit testing the optimizer
162162
inlining = InliningState(interp)
163163
cfg = compute_basic_blocks(src.code)
164-
bb_vartables = Union{Nothing,VarTable}[]; fill!(bb_vartables, nothing, length(cfg.blocks))
164+
bb_vartables = VarTable[]
165+
for block = 1:length(cfg.blocks)
166+
push!(bb_vartables, VarState[
167+
VarState(slottypes[slot], src.slotflags[slot] & SLOT_USEDUNDEF != 0)
168+
for slot = 1:nslots
169+
])
170+
end
165171
return OptimizationState(linfo, src, nothing, stmt_info, mod, sptypes, slottypes, inlining, cfg, bb_vartables, false)
166172
end
167173
function OptimizationState(linfo::MethodInstance, interp::AbstractInterpreter)

base/compiler/ssair/slot2ssa.jl

Lines changed: 46 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -122,17 +122,8 @@ function fixemup!(@specialize(slot_filter), @specialize(rename_slot), ir::IRCode
122122
val = stmt.args[1]
123123
if isa(val, SlotNumber)
124124
slot = slot_id(val)
125-
if (ci.slotflags[slot] & SLOT_USEDUNDEF) == 0
126-
return true
127-
else
128-
ssa, undef_ssa = rename_slot(val)
129-
if ssa === UNDEF_TOKEN
130-
return false
131-
elseif !isa(ssa, SSAValue) && !isa(ssa, NewSSAValue)
132-
return true
133-
end
134-
return undef_ssa
135-
end
125+
ssa, undef_ssa = rename_slot(val)
126+
return undef_ssa
136127
end
137128
return stmt
138129
end
@@ -569,7 +560,7 @@ end
569560
struct NewSlotPhi{Phi}
570561
ssaval::NewSSAValue
571562
node::Phi
572-
undef_ssaval::Union{NewSSAValue, Nothing}
563+
undef_ssaval::Union{NewSSAValue, Bool}
573564
undef_node::Union{Phi, Nothing}
574565
end
575566

@@ -646,11 +637,18 @@ function construct_ssa!(ci::CodeInfo, ir::IRCode, sv::OptimizationState,
646637
# an upsilon node in the corresponding enter block
647638
node = PhiCNode(Any[])
648639
insertpoint = first_insert_for_bb(code, cfg, li)
640+
@assert sv.bb_vartables[li] !== nothing
641+
vt = sv.bb_vartables[li][idx]
642+
typ = widenslotwrapper(ignorelimited(vt.typ))
649643
phic_ssa = NewSSAValue(
650644
insert_node!(ir, insertpoint,
651-
NewInstruction(node, Union{})).id - length(ir.stmts))
645+
NewInstruction(node, typ)).id - length(ir.stmts))
652646
undef_node = undef_ssaval = nothing
653-
if (ci.slotflags[idx] & SLOT_USEDUNDEF) != 0
647+
if vt.typ === Union{}
648+
undef_ssaval = false
649+
elseif !vt.undef
650+
undef_ssaval = true
651+
else
654652
undef_node = PhiCNode(Any[])
655653
undef_ssaval = NewSSAValue(insert_node!(ir,
656654
insertpoint, NewInstruction(undef_node, Bool)).id - length(ir.stmts))
@@ -667,14 +665,17 @@ function construct_ssa!(ci::CodeInfo, ir::IRCode, sv::OptimizationState,
667665
for block in phiblocks
668666
push!(phi_slots[block], idx)
669667
node = PhiNode()
670-
typ = sv.slottypes[idx]
671-
if sv.bb_vartables[block] !== nothing
672-
typ = widenslotwrapper(ignorelimited(sv.bb_vartables[block][idx].typ))
673-
end
668+
@assert sv.bb_vartables[block] !== nothing
669+
vt = sv.bb_vartables[block][idx]
670+
typ = widenslotwrapper(ignorelimited(vt.typ))
674671
ssaval = NewSSAValue(insert_node!(ir,
675672
first_insert_for_bb(code, cfg, block), NewInstruction(node, typ)).id - length(ir.stmts))
676673
undef_node = undef_ssaval = nothing
677-
if (ci.slotflags[idx] & SLOT_USEDUNDEF) != 0
674+
if vt.typ === Union{}
675+
undef_ssaval = false
676+
elseif !vt.undef
677+
undef_ssaval = true
678+
else
678679
undef_node = PhiNode()
679680
undef_ssaval = NewSSAValue(insert_node!(ir,
680681
first_insert_for_bb(code, cfg, block), NewInstruction(undef_node, Bool)).id - length(ir.stmts))
@@ -728,38 +729,38 @@ function construct_ssa!(ci::CodeInfo, ir::IRCode, sv::OptimizationState,
728729
else
729730
push!(node.values, incoming_val)
730731
end
731-
outgoing_def = true
732-
if (ci.slotflags[slot] & SLOT_USEDUNDEF) != 0
732+
if undef_node !== nothing
733733
push!(undef_node.edges, pred)
734734
push!(undef_node.values, incoming_def)
735-
outgoing_def = undef_ssaval
736735
end
737736

738-
incoming_vals[slot] = Pair{Any, Any}(ssaval, outgoing_def)
737+
incoming_vals[slot] = Pair{Any, Any}(ssaval, undef_ssaval)
739738
end
740739
(item in visited) && continue
741-
# Record Pi nodes if necessary
742-
if sv.bb_vartables[item] !== nothing
743-
for slot in 1:length(sv.slottypes)
744-
(ival, idef) = incoming_vals[slot]
745-
(ival === SSAValue(-1)) && continue
746-
(ival === SSAValue(-2)) && continue
747-
748-
varstate = sv.bb_vartables[item][slot]
749-
typ = widenslotwrapper(ignorelimited(varstate.typ))
750-
if !(𝕃ₒ, sv.slottypes[slot], typ)
751-
node = PiNode(ival, typ)
752-
ival = NewSSAValue(insert_node!(ir,
753-
first_insert_for_bb(code, cfg, item), NewInstruction(node, typ)).id - length(ir.stmts))
754-
incoming_vals[slot] = Pair{Any, Any}(ival, idef)
755-
end
756-
end
757-
end
758740
# Record phi_C nodes if necessary
759741
if haskey(new_phic_nodes, item)
760742
for (; slot, insert) in new_phic_nodes[item]
761743
(; ssaval, undef_ssaval) = insert
762-
incoming_vals[slot_id(slot)] = Pair{Any, Any}(ssaval, undef_ssaval === nothing ? true : undef_ssaval)
744+
incoming_vals[slot_id(slot)] = Pair{Any, Any}(ssaval, undef_ssaval)
745+
end
746+
end
747+
# Record Pi nodes if necessary
748+
has_pinode = fill(false, length(sv.slottypes))
749+
for slot in 1:length(sv.slottypes)
750+
(ival, idef) = incoming_vals[slot]
751+
(ival === SSAValue(-1)) && continue
752+
(ival === SSAValue(-2)) && continue
753+
(ival === UNDEF_TOKEN) && continue
754+
755+
@assert sv.bb_vartables[item] !== nothing
756+
varstate = sv.bb_vartables[item][slot]
757+
typ = widenslotwrapper(ignorelimited(varstate.typ))
758+
if !(𝕃ₒ, sv.slottypes[slot], typ)
759+
node = PiNode(ival, typ)
760+
ival = NewSSAValue(insert_node!(ir,
761+
first_insert_for_bb(code, cfg, item), NewInstruction(node, typ)).id - length(ir.stmts))
762+
incoming_vals[slot] = Pair{Any, Any}(ival, idef)
763+
has_pinode[slot] = true
763764
end
764765
end
765766
# Record initial upsilon nodes if necessary
@@ -788,6 +789,7 @@ function construct_ssa!(ci::CodeInfo, ir::IRCode, sv::OptimizationState,
788789
(isa(stmt, PhiNode) || (isexpr(stmt, :(=)) && isa(stmt.args[2], PhiNode))) && continue
789790
if isa(stmt, NewvarNode)
790791
incoming_vals[slot_id(stmt.slot)] = Pair{Any, Any}(UNDEF_TOKEN, false)
792+
has_pinode[slot_id(stmt.slot)] = false
791793
code[idx] = nothing
792794
else
793795
stmt = rename_uses!(ir, ci, idx, stmt, incoming_vals)
@@ -814,6 +816,7 @@ function construct_ssa!(ci::CodeInfo, ir::IRCode, sv::OptimizationState,
814816
thisdef = false
815817
end
816818
incoming_vals[id] = Pair{Any, Any}(thisval, thisdef)
819+
has_pinode[id] = false
817820
enter_block = item
818821
while haskey(exc_handlers, enter_block)
819822
(; enter_block, leave_block) = exc_handlers[enter_block]
@@ -840,11 +843,9 @@ function construct_ssa!(ci::CodeInfo, ir::IRCode, sv::OptimizationState,
840843
# Unwrap any PiNodes before continuing, since they weren't considered during our
841844
# dominance frontier calculation and so have to be used locally in each BB.
842845
for (i, (ival, idef)) in enumerate(incoming_vals)
843-
if ival isa NewSSAValue
846+
if has_pinode[i]
844847
stmt = ir[new_to_regular(ival::NewSSAValue, length(ir.stmts))][:stmt]
845-
if stmt isa PiNode
846-
incoming_vals[i] = Pair{Any, Any}(stmt.val, idef)
847-
end
848+
incoming_vals[i] = Pair{Any, Any}(stmt.val, idef)
848849
end
849850
end
850851
for succ in cfg.blocks[item].succs
@@ -896,20 +897,6 @@ function construct_ssa!(ci::CodeInfo, ir::IRCode, sv::OptimizationState,
896897
end
897898
end
898899
end
899-
for (_, nodes) in new_phic_nodes
900-
for (; insert) in nodes
901-
(; node, ssaval) = insert
902-
new_typ = Union{}
903-
new_idx = ssaval.id
904-
node = new_nodes.stmts[new_idx]
905-
phic_values = (node[:stmt]::PhiCNode).values
906-
for i = 1:length(phic_values)
907-
typ = typ_for_val(phic_values[i], ci, ir, -1, sv.slottypes)
908-
new_typ = tmerge(𝕃ₒ, new_typ, typ)
909-
end
910-
node[:type] = new_typ
911-
end
912-
end
913900
# Renumber SSA values
914901
@assert isempty(ir.stmts.type)
915902
resize!(ir.stmts.type, nstmts)

base/compiler/typeinfer.jl

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -625,35 +625,6 @@ function record_bestguess!(sv::InferenceState)
625625
return nothing
626626
end
627627

628-
function find_undefs!(interp::AbstractInterpreter, undefs::Vector{Bool}, idx::Int, sv::InferenceState, @nospecialize x)
629-
if isa(x, SlotNumber)
630-
id = slot_id(x)
631-
pc = find_dominating_assignment(id, idx, sv)
632-
if pc === nothing
633-
block = block_for_inst(sv.cfg, idx)
634-
state = sv.bb_vartables[block]::VarTable
635-
vt = state[id]
636-
undefs[id] |= vt.undef
637-
end
638-
elseif isa(x, Expr)
639-
head = x.head
640-
i0 = 1
641-
if is_meta_expr_head(head) || head === :const
642-
return x
643-
end
644-
if head === :(=) || head === :method
645-
i0 = 2
646-
end
647-
for i = i0:length(x.args)
648-
find_undefs!(interp, undefs, idx, sv, x.args[i])
649-
end
650-
elseif isa(x, ReturnNode) && isdefined(x, :val)
651-
find_undefs!(interp, undefs, idx, sv, x.val)
652-
elseif isa(x, GotoIfNot)
653-
find_undefs!(interp, undefs, idx, sv, x.cond)
654-
end
655-
end
656-
657628
# find the dominating assignment to the slot `id` in the block containing statement `idx`,
658629
# returns `nothing` otherwise
659630
function find_dominating_assignment(id::Int, idx::Int, sv::InferenceState)
@@ -693,7 +664,6 @@ function type_annotate!(interp::AbstractInterpreter, sv::InferenceState, run_opt
693664
ssavaluetypes = sv.ssavaluetypes
694665
slotflags = src.slotflags
695666
nslots = length(slotflags)
696-
undefs = fill(false, nslots)
697667
any_unreachable = false
698668

699669
# this statement traversal does five things:
@@ -729,7 +699,6 @@ function type_annotate!(interp::AbstractInterpreter, sv::InferenceState, run_opt
729699
end
730700
end
731701
end
732-
find_undefs!(interp, undefs, i, sv, expr) # 1
733702
stmts[i] = expr
734703
ssavaluetypes[i] = widenslotwrapper(ssavaluetypes[i]) # 3
735704
else # i.e. any runtime execution will never reach this statement
@@ -743,13 +712,6 @@ function type_annotate!(interp::AbstractInterpreter, sv::InferenceState, run_opt
743712
end
744713
end
745714

746-
# finish marking used-undef variables
747-
for j = 1:nslots
748-
if undefs[j]
749-
slotflags[j] |= SLOT_USEDUNDEF | SLOT_STATICUNDEF
750-
end
751-
end
752-
753715
return any_unreachable
754716
end
755717

0 commit comments

Comments
 (0)