Skip to content

Commit

Permalink
compiler: Remove TypedSlot
Browse files Browse the repository at this point in the history
Since this is now unused by `slot2ssa` downstream, we can happily remove
it from the rest of the compiler.

There's one more piece of logic that I still need to move downstream: we
should use the `bb_vartables` for undefined-ness as well. That will
allow us to finally remove the (now incorrectly named) `annotate_slot_load!`
  • Loading branch information
topolarity committed Aug 16, 2023
1 parent 0f7f202 commit 1d4da7e
Show file tree
Hide file tree
Showing 10 changed files with 62 additions and 95 deletions.
4 changes: 1 addition & 3 deletions base/compiler/optimize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,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 @@ -366,8 +366,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
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
35 changes: 14 additions & 21 deletions base/compiler/ssair/slot2ssa.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

struct TypedSlot
id::Int
typ
TypedSlot(id::Int, @nospecialize(typ)) = new(id, typ)
end

const UnoptSlot = Union{SlotNumber, TypedSlot}

mutable struct SlotInfo
defs::Vector{Int}
uses::Vector{Int}
Expand All @@ -29,13 +21,13 @@ function scan_entry!(result::Vector{SlotInfo}, idx::Int, @nospecialize(stmt))
end
stmt = stmt.args[2]
end
if isa(stmt, UnoptSlot)
if isa(stmt, SlotNumber)
push!(result[slot_id(stmt)].uses, idx)
return
end
for op in userefs(stmt)
val = op[]
if isa(val, UnoptSlot)
if isa(val, SlotNumber)
push!(result[slot_id(val)].uses, idx)
end
end
Expand Down Expand Up @@ -89,7 +81,7 @@ function new_to_regular(@nospecialize(stmt), new_offset::Int)
return urs[]
end

function fixup_slot!(ir::IRCode, ci::CodeInfo, idx::Int, slot::Int, stmt::UnoptSlot, @nospecialize(ssa), @nospecialize(def_ssa))
function fixup_slot!(ir::IRCode, ci::CodeInfo, idx::Int, slot::Int, stmt::SlotNumber, @nospecialize(ssa), @nospecialize(def_ssa))
# We don't really have the information here to get rid of these.
# We'll do so later
if ssa === UNDEF_TOKEN
Expand All @@ -100,14 +92,14 @@ function fixup_slot!(ir::IRCode, ci::CodeInfo, idx::Int, slot::Int, stmt::UnoptS
insert_node!(ir, idx, NewInstruction(
Expr(:throw_undef_if_not, ci.slotnames[slot], def_ssa), Any))
end
if isa(stmt, SlotNumber) || isa(stmt, TypedSlot)
if isa(stmt, SlotNumber)
return ssa
end
@assert false # unreachable
end

function fixemup!(@specialize(slot_filter), @specialize(rename_slot), ir::IRCode, ci::CodeInfo, idx::Int, @nospecialize(stmt))
if isa(stmt, UnoptSlot) && slot_filter(stmt)
if isa(stmt, SlotNumber) && slot_filter(stmt)
return fixup_slot!(ir, ci, idx, slot_id(stmt), stmt, rename_slot(stmt)...)
end
if isexpr(stmt, :(=))
Expand All @@ -118,7 +110,7 @@ function fixemup!(@specialize(slot_filter), @specialize(rename_slot), ir::IRCode
for i = 1:length(stmt.edges)
isassigned(stmt.values, i) || continue
val = stmt.values[i]
isa(val, UnoptSlot) || continue
isa(val, SlotNumber) || continue
slot_filter(val) || continue
bb_idx = block_for_inst(ir.cfg, Int(stmt.edges[i]))
from_bb_terminator = last(ir.cfg.blocks[bb_idx].stmts)
Expand All @@ -128,7 +120,7 @@ function fixemup!(@specialize(slot_filter), @specialize(rename_slot), ir::IRCode
end
if isexpr(stmt, :isdefined)
val = stmt.args[1]
if isa(val, UnoptSlot)
if isa(val, SlotNumber)
slot = slot_id(val)
if (ci.slotflags[slot] & SLOT_USEDUNDEF) == 0
return true
Expand All @@ -147,7 +139,7 @@ function fixemup!(@specialize(slot_filter), @specialize(rename_slot), ir::IRCode
urs = userefs(stmt)
for op in urs
val = op[]
if isa(val, UnoptSlot) && slot_filter(val)
if isa(val, SlotNumber) && slot_filter(val)
x = fixup_slot!(ir, ci, idx, slot_id(val), val, rename_slot(val)...)
# We inserted an undef error node. Delete subsequent statement
# to avoid confusing the optimizer
Expand All @@ -156,8 +148,9 @@ function fixemup!(@specialize(slot_filter), @specialize(rename_slot), ir::IRCode
end
op[] = x
elseif isa(val, GlobalRef) && !(isdefined(val.mod, val.name) && isconst(val.mod, val.name))
op[] = NewSSAValue(insert_node!(ir, idx,
NewInstruction(val, typ_for_val(val, ci, ir.sptypes, idx, Any[]))).id - length(ir.stmts))
typ = typ_for_val(val, ci, ir.sptypes, idx, Any[])
new_inst = NewInstruction(val, typ)
op[] = NewSSAValue(insert_node!(ir, idx, new_inst).id - length(ir.stmts))
elseif isexpr(val, :static_parameter)
ty = typ_for_val(val, ci, ir.sptypes, idx, Any[])
if isa(ty, Const)
Expand All @@ -173,12 +166,12 @@ end

function fixup_uses!(ir::IRCode, ci::CodeInfo, code::Vector{Any}, uses::Vector{Int}, slot::Int, @nospecialize(ssa))
for use in uses
code[use] = fixemup!(x::UnoptSlot->slot_id(x)==slot, stmt::UnoptSlot->(ssa, true), ir, ci, use, code[use])
code[use] = fixemup!(x::SlotNumber->slot_id(x)==slot, stmt::SlotNumber->(ssa, true), ir, ci, use, code[use])
end
end

function rename_uses!(ir::IRCode, ci::CodeInfo, idx::Int, @nospecialize(stmt), renames::Vector{Pair{Any, Any}})
return fixemup!(stmt::UnoptSlot->true, stmt::UnoptSlot->renames[slot_id(stmt)], ir, ci, idx, stmt)
return fixemup!(stmt::SlotNumber->true, stmt::SlotNumber->renames[slot_id(stmt)], ir, ci, idx, stmt)
end

function strip_trailing_junk!(ci::CodeInfo, cfg::CFG, code::Vector{Any}, info::Vector{CallInfo})
Expand Down Expand Up @@ -236,7 +229,7 @@ function typ_for_val(@nospecialize(x), ci::CodeInfo, sptypes::Vector{VarState},
isa(x, Argument) && return slottypes[x.n]
isa(x, NewSSAValue) && return DelayedTyp(x)
isa(x, QuoteNode) && return Const(x.value)
isa(x, Union{Symbol, PiNode, PhiNode, UnoptSlot}) && error("unexpected val type")
isa(x, Union{Symbol, PiNode, PhiNode, SlotNumber}) && error("unexpected val type")
return Const(x)
end

Expand Down
2 changes: 1 addition & 1 deletion base/compiler/ssair/verify.jl
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function check_op(ir::IRCode, domtree::DomTree, @nospecialize(op), use_bb::Int,
elseif isa(op, Union{OldSSAValue, NewSSAValue})
@verify_error "Left over SSA marker"
error("")
elseif isa(op, UnoptSlot)
elseif isa(op, SlotNumber)
@verify_error "Left over slot detected in converted IR"
error("")
end
Expand Down
37 changes: 13 additions & 24 deletions base/compiler/typeinfer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ function record_bestguess!(sv::InferenceState)
return nothing
end

function annotate_slot_load!(interp::AbstractInterpreter, undefs::Vector{Bool}, idx::Int, sv::InferenceState, @nospecialize x)
function find_undefs!(interp::AbstractInterpreter, undefs::Vector{Bool}, idx::Int, sv::InferenceState, @nospecialize x)
if isa(x, SlotNumber)
id = slot_id(x)
pc = find_dominating_assignment(id, idx, sv)
Expand All @@ -634,16 +634,7 @@ function annotate_slot_load!(interp::AbstractInterpreter, undefs::Vector{Bool},
state = sv.bb_vartables[block]::VarTable
vt = state[id]
undefs[id] |= vt.undef
typ = widenslotwrapper(ignorelimited(vt.typ))
else
typ = sv.ssavaluetypes[pc]
@assert typ !== NOT_FOUND "active slot in unreached region"
end
# add type annotations where needed
if !(typeinf_lattice(interp), sv.slottypes[id], typ)
return TypedSlot(id, typ)
end
return x
elseif isa(x, Expr)
head = x.head
i0 = 1
Expand All @@ -654,15 +645,13 @@ function annotate_slot_load!(interp::AbstractInterpreter, undefs::Vector{Bool},
i0 = 2
end
for i = i0:length(x.args)
x.args[i] = annotate_slot_load!(interp, undefs, idx, sv, x.args[i])
find_undefs!(interp, undefs, idx, sv, x.args[i])
end
return x
elseif isa(x, ReturnNode) && isdefined(x, :val)
return ReturnNode(annotate_slot_load!(interp, undefs, idx, sv, x.val))
find_undefs!(interp, undefs, idx, sv, x.val)
elseif isa(x, GotoIfNot)
return GotoIfNot(annotate_slot_load!(interp, undefs, idx, sv, x.cond), x.dest)
find_undefs!(interp, undefs, idx, sv, x.cond)
end
return x
end

# find the dominating assignment to the slot `id` in the block containing statement `idx`,
Expand Down Expand Up @@ -708,12 +697,11 @@ function type_annotate!(interp::AbstractInterpreter, sv::InferenceState, run_opt
any_unreachable = false

# this statement traversal does five things:
# 1. introduce temporary `TypedSlot`s that are supposed to be replaced with π-nodes later
# 2. mark used-undef slots (required by the `slot2reg` conversion)
# 3. mark unreached statements for a bulk code deletion (see issue #7836)
# 4. widen slot wrappers (`Conditional` and `MustAlias`) and remove `NOT_FOUND` from `ssavaluetypes`
# 1. mark used-undef slots (required by the `slot2reg` conversion)
# 2. mark unreached statements for a bulk code deletion (see issue #7836)
# 3. widen slot wrappers (`Conditional` and `MustAlias`) and remove `NOT_FOUND` from `ssavaluetypes`
# NOTE because of this, `was_reached` will no longer be available after this point
# 5. eliminate GotoIfNot if either or both branches are statically unreachable
# 4. eliminate GotoIfNot if either or both branches are statically unreachable
changemap = nothing # initialized if there is any dead region
for i = 1:nstmt
expr = stmts[i]
Expand Down Expand Up @@ -741,14 +729,15 @@ function type_annotate!(interp::AbstractInterpreter, sv::InferenceState, run_opt
end
end
end
stmts[i] = annotate_slot_load!(interp, undefs, i, sv, expr) # 1&2
ssavaluetypes[i] = widenslotwrapper(ssavaluetypes[i]) # 4
find_undefs!(interp, undefs, i, sv, expr) # 1
stmts[i] = expr
ssavaluetypes[i] = widenslotwrapper(ssavaluetypes[i]) # 3
else # i.e. any runtime execution will never reach this statement
any_unreachable = true
if is_meta_expr(expr) # keep any lexically scoped expressions
ssavaluetypes[i] = Any # 4
ssavaluetypes[i] = Any # 3
else
ssavaluetypes[i] = Bottom # 4
ssavaluetypes[i] = Bottom # 3
stmts[i] = Const(expr) # annotate that this statement actually is dead
end
end
Expand Down
3 changes: 1 addition & 2 deletions base/compiler/utilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -489,8 +489,7 @@ end
# using a function to ensure we can infer this
@inline function slot_id(s)
isa(s, SlotNumber) && return s.id
isa(s, Argument) && return s.n
return (s::TypedSlot).id
return (s::Argument).n
end

###########
Expand Down
4 changes: 2 additions & 2 deletions base/compiler/validation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,10 @@ end

validate_code(args...) = validate_code!(Vector{InvalidCodeError}(), args...)

is_valid_lvalue(@nospecialize(x)) = isa(x, UnoptSlot) || isa(x, GlobalRef)
is_valid_lvalue(@nospecialize(x)) = isa(x, SlotNumber) || isa(x, GlobalRef)

function is_valid_argument(@nospecialize(x))
if isa(x, UnoptSlot) || isa(x, Argument) || isa(x, SSAValue) ||
if isa(x, SlotNumber) || isa(x, Argument) || isa(x, SSAValue) ||
isa(x, GlobalRef) || isa(x, QuoteNode) || isexpr(x, (:static_parameter, :boundscheck)) ||
isa(x, Number) || isa(x, AbstractString) || isa(x, AbstractChar) || isa(x, Tuple) ||
isa(x, Type) || isa(x, Core.Box) || isa(x, Module) || x === nothing
Expand Down
12 changes: 4 additions & 8 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1424,9 +1424,9 @@ show(io::IO, s::Symbol) = show_unquoted_quote_expr(io, s, 0, 0, 0)
# eval(Meta.parse("Set{Int64}([2,3,1])")) # ==> An actual set
# While this isn’t true of ALL show methods, it is of all ASTs.

using Core.Compiler: TypedSlot, UnoptSlot
using Core.Compiler: SlotNumber

const ExprNode = Union{Expr, QuoteNode, UnoptSlot, LineNumberNode, SSAValue,
const ExprNode = Union{Expr, QuoteNode, SlotNumber, LineNumberNode, SSAValue,
GotoNode, GotoIfNot, GlobalRef, PhiNode, PhiCNode, UpsilonNode,
ReturnNode}
# Operators have precedence levels from 1-N, and show_unquoted defaults to a
Expand Down Expand Up @@ -1777,8 +1777,7 @@ function show_globalref(io::IO, ex::GlobalRef; allow_macroname=false)
nothing
end

function show_unquoted(io::IO, ex::UnoptSlot, ::Int, ::Int)
typ = isa(ex, TypedSlot) ? ex.typ : Any
function show_unquoted(io::IO, ex::SlotNumber, ::Int, ::Int)
slotid = ex.id
slotnames = get(io, :SOURCE_SLOTNAMES, false)
if (isa(slotnames, Vector{String}) &&
Expand All @@ -1787,9 +1786,6 @@ function show_unquoted(io::IO, ex::UnoptSlot, ::Int, ::Int)
else
print(io, "_", slotid)
end
if typ !== Any && isa(ex, TypedSlot)
print(io, "::", typ)
end
end

function show_unquoted(io::IO, ex::QuoteNode, indent::Int, prec::Int)
Expand Down Expand Up @@ -2764,7 +2760,7 @@ module IRShow
const Compiler = Core.Compiler
using Core.IR
import ..Base
import .Compiler: IRCode, TypedSlot, CFG, scan_ssa_use!,
import .Compiler: IRCode, CFG, scan_ssa_use!,
isexpr, compute_basic_blocks, block_for_inst, IncrementalCompact,
Effects, ALWAYS_TRUE, ALWAYS_FALSE
Base.getindex(r::Compiler.StmtRange, ind::Integer) = Compiler.getindex(r, ind)
Expand Down
5 changes: 0 additions & 5 deletions doc/src/devdocs/ast.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,6 @@ types exist in lowered form:
Identifies arguments and local variables by consecutive numbering. It has an
integer-valued `id` field giving the slot index.
The types of these slots can be found in the `slottypes` field of their `CodeInfo` object.
When a slot has different types at different uses and thus requires per-use type annotations,
they are converted to temporary `Core.Compiler.TypedSlot` object. This object has an
additional `typ` field as well as the `id` field. Note that `Core.Compiler.TypedSlot`
only appears in an unoptimized lowered form that is scheduled for optimization,
and it never appears elsewhere.

* `Argument`

Expand Down
51 changes: 26 additions & 25 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1946,31 +1946,32 @@ g26339(T) = T === Int ? 1 : ""
@test Base.return_types(f26339, (Type,)) == Any[Union{Int, String}]
@test Base.return_types(g26339, (Type,)) == Any[Union{Int, String}]

# Test that Conditional doesn't get widened to Bool too quickly
f25261() = (1, 1)
f25261(s) = i == 1 ? (1, 2) : nothing
function foo25261()
next = f25261()
while next !== nothing
next = f25261(Core.getfield(next, 2))
end
end
let opt25261 = code_typed(foo25261, Tuple{}, optimize=false)[1].first.code
i = 1
# Skip to after the branch
while !isa(opt25261[i], GotoIfNot)
i += 1
end
foundslot = false
for expr25261 in opt25261[i:end]
if expr25261 isa Core.Compiler.TypedSlot && expr25261.typ === Tuple{Int, Int}
# This should be the assignment to the SSAValue into the getfield
# call - make sure it's a TypedSlot
foundslot = true
end
end
@test foundslot
end
# TODO: Re-write test
# # Test that Conditional doesn't get widened to Bool too quickly
# f25261() = (1, 1)
# f25261(s) = i == 1 ? (1, 2) : nothing
# function foo25261()
# next = f25261()
# while next !== nothing
# next = f25261(Core.getfield(next, 2))
# end
# end
# let opt25261 = code_typed(foo25261, Tuple{}, optimize=false)[1].first.code
# i = 1
# # Skip to after the branch
# while !isa(opt25261[i], GotoIfNot)
# i += 1
# end
# foundslot = false
# for expr25261 in opt25261[i:end]
# if expr25261 isa Core.Compiler.TypedSlot && expr25261.typ === Tuple{Int, Int}
# # This should be the assignment to the SSAValue into the getfield
# # call - make sure it's a TypedSlot
# foundslot = true
# end
# end
# @test foundslot
# end

@testset "inter-procedural conditional constraint propagation" begin
# simple cases
Expand Down

0 comments on commit 1d4da7e

Please sign in to comment.