Skip to content

Commit

Permalink
IRShow: label builtin / intrinsic / dynamic calls in code_typed
Browse files Browse the repository at this point in the history
This makes it much easier to spot dynamic dispatches:
```julia
3 ── %9  = (isa)(%4, @NamedTuple{x::Int64, y})::Bool
└───       goto JuliaLang#5 if not %9
4 ── %11 = π (%4, @NamedTuple{x::Int64, y})
└───       goto JuliaLang#6
5 ── %13 = (Tuple{Int64, Any})(%4)::Tuple{Int64, Any}
│    %14 = (getfield)(%13, 1)::Int64
│    %15 = (getfield)(%13, 2)::Any
│    %16 = %new(@NamedTuple{x::Int64, y}, %14, %15)::@NamedTuple{x::Int64, y}
```

is now:
```julia
3 ── %9  = builtin (isa)(%4, @NamedTuple{x::Int64, y})::Bool
└───       goto JuliaLang#5 if not %9
4 ── %11 = π (%4, @NamedTuple{x::Int64, y})
└───       goto JuliaLang#6
5 ── %13 = dynamic (Tuple{Int64, Any})(%4)::Tuple{Int64, Any}
│    %14 = builtin (getfield)(%13, 1)::Int64
│    %15 = builtin (getfield)(%13, 2)::Any
│    %16 = %new(@NamedTuple{x::Int64, y}, %14, %15)::@NamedTuple{x::Int64, y}
```

This is on by default when displaying a CodeInfo, and  off by default
for `code_warntype`, unless optimize=true. Can be enabled / disabled
via IRShowConfig.label_dynamic_calls
  • Loading branch information
topolarity committed Oct 11, 2024
1 parent 9844d85 commit 4a93041
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 48 deletions.
1 change: 1 addition & 0 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3114,6 +3114,7 @@ end
abstract_eval_ssavalue(s::SSAValue, sv::InferenceState) = abstract_eval_ssavalue(s, sv.ssavaluetypes)

function abstract_eval_ssavalue(s::SSAValue, ssavaluetypes::Vector{Any})
(1 s.id length(ssavaluetypes)) || throw(InvalidIRError())
typ = ssavaluetypes[s.id]
if typ === NOT_FOUND
return Bottom
Expand Down
25 changes: 21 additions & 4 deletions base/compiler/optimize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -411,26 +411,35 @@ function argextype(@nospecialize(x), compact::IncrementalCompact, sptypes::Vecto
isa(x, AnySSAValue) && return types(compact)[x]
return argextype(x, compact, sptypes, compact.ir.argtypes)
end
argextype(@nospecialize(x), src::CodeInfo, sptypes::Vector{VarState}) = argextype(x, src, sptypes, src.slottypes::Vector{Any})
function argextype(@nospecialize(x), src::CodeInfo, sptypes::Vector{VarState})
return argextype(x, src, sptypes, src.slottypes::Union{Vector{Any},Nothing})
end
function argextype(
@nospecialize(x), src::Union{IRCode,IncrementalCompact,CodeInfo},
sptypes::Vector{VarState}, slottypes::Vector{Any})
sptypes::Vector{VarState}, slottypes::Union{Vector{Any},Nothing})
if isa(x, Expr)
if x.head === :static_parameter
return sptypes[x.args[1]::Int].typ
idx = x.args[1]::Int
(1 idx length(sptypes)) || throw(InvalidIRError())
return sptypes[idx].typ
elseif x.head === :boundscheck
return Bool
elseif x.head === :copyast
length(x.args) == 0 && throw(InvalidIRError())
return argextype(x.args[1], src, sptypes, slottypes)
end
Core.println("argextype called on Expr with head ", x.head,
" which is not valid for IR in argument-position.")
@assert false
elseif isa(x, SlotNumber)
slottypes === nothing && return Any
(1 x.id length(slottypes)) || throw(InvalidIRError())
return slottypes[x.id]
elseif isa(x, SSAValue)
return abstract_eval_ssavalue(x, src)
elseif isa(x, Argument)
slottypes === nothing && return Any
(1 x.n length(slottypes)) || throw(InvalidIRError())
return slottypes[x.n]
elseif isa(x, QuoteNode)
return Const(x.value)
Expand All @@ -444,7 +453,15 @@ function argextype(
return Const(x)
end
end
abstract_eval_ssavalue(s::SSAValue, src::CodeInfo) = abstract_eval_ssavalue(s, src.ssavaluetypes::Vector{Any})
function abstract_eval_ssavalue(s::SSAValue, src::CodeInfo)
ssavaluetypes = src.ssavaluetypes
if ssavaluetypes isa Int
(1 s.id ssavaluetypes) || throw(InvalidIRError())
return Any
else
return abstract_eval_ssavalue(s, ssavaluetypes::Vector{Any})
end
end
abstract_eval_ssavalue(s::SSAValue, src::Union{IRCode,IncrementalCompact}) = types(src)[s]

"""
Expand Down
36 changes: 28 additions & 8 deletions base/compiler/ssair/ir.jl
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ Instruction(is::InstructionStream) = Instruction(is, add_new_idx!(is))
fldarray = getfield(getfield(node, :data), fld)
fldidx = getfield(node, :idx)
(fld === :line) && return (fldarray[3fldidx-2], fldarray[3fldidx-1], fldarray[3fldidx-0])
(1 fldidx length(fldarray)) || throw(InvalidIRError())
return fldarray[fldidx]
end
@inline function setindex!(node::Instruction, @nospecialize(val), fld::Symbol)
Expand Down Expand Up @@ -481,11 +482,16 @@ function block_for_inst(ir::IRCode, inst::Int)
end

function getindex(ir::IRCode, s::SSAValue)
id = s.id
(id 1) || throw(InvalidIRError())
nstmts = length(ir.stmts)
if s.id <= nstmts
return ir.stmts[s.id]
if id <= nstmts
return ir.stmts[id]
else
return ir.new_nodes.stmts[s.id - nstmts]
id -= nstmts
stmts = ir.new_nodes.stmts
(id length(stmts)) || throw(InvalidIRError())
return stmts[id]
end
end

Expand Down Expand Up @@ -801,12 +807,13 @@ end
types(ir::Union{IRCode, IncrementalCompact}) = TypesView(ir)

function getindex(compact::IncrementalCompact, ssa::SSAValue)
@assert ssa.id < compact.result_idx
(1 ssa.id compact.result_idx) || throw(InvalidIRError())
return compact.result[ssa.id]
end

function getindex(compact::IncrementalCompact, ssa::OldSSAValue)
id = ssa.id
(id 1) || throw(InvalidIRError())
if id < compact.idx
new_idx = compact.ssa_rename[id]::Int
return compact.result[new_idx]
Expand All @@ -818,12 +825,15 @@ function getindex(compact::IncrementalCompact, ssa::OldSSAValue)
return compact.ir.new_nodes.stmts[id]
end
id -= length(compact.ir.new_nodes)
(id length(compact.pending_nodes.stmts)) || throw(InvalidIRError())
return compact.pending_nodes.stmts[id]
end

function getindex(compact::IncrementalCompact, ssa::NewSSAValue)
if ssa.id < 0
return compact.new_new_nodes.stmts[-ssa.id]
stmts = compact.new_new_nodes.stmts
(-ssa.id length(stmts)) || throw(InvalidIRError())
return stmts[-ssa.id]
else
return compact[SSAValue(ssa.id)]
end
Expand Down Expand Up @@ -1069,6 +1079,7 @@ function getindex(view::TypesView, v::OldSSAValue)
id = v.id
ir = view.ir.ir
stmts = ir.stmts
(id 1) || throw(InvalidIRError())
if id <= length(stmts)
return stmts[id][:type]
end
Expand All @@ -1077,7 +1088,9 @@ function getindex(view::TypesView, v::OldSSAValue)
return ir.new_nodes.stmts[id][:type]
end
id -= length(ir.new_nodes)
return view.ir.pending_nodes.stmts[id][:type]
stmts = view.ir.pending_nodes.stmts
(id length(stmts)) || throw(InvalidIRError())
return stmts[id][:type]
end

function kill_current_use!(compact::IncrementalCompact, @nospecialize(val))
Expand Down Expand Up @@ -1204,20 +1217,27 @@ end

getindex(view::TypesView, idx::SSAValue) = getindex(view, idx.id)
function getindex(view::TypesView, idx::Int)
(idx 1) || throw(InvalidIRError())
if isa(view.ir, IncrementalCompact) && idx < view.ir.result_idx
return view.ir.result[idx][:type]
elseif isa(view.ir, IncrementalCompact) && view.ir.renamed_new_nodes
if idx <= length(view.ir.result)
return view.ir.result[idx][:type]
else
return view.ir.new_new_nodes.stmts[idx - length(view.ir.result)][:type]
idx -= length(view.ir.result)
stmts = view.ir.new_new_nodes.stmts
(idx length(stmts)) || throw(InvalidIRError())
return stmts[idx][:type]
end
else
ir = isa(view.ir, IncrementalCompact) ? view.ir.ir : view.ir
if idx <= length(ir.stmts)
return ir.stmts[idx][:type]
else
return ir.new_nodes.stmts[idx - length(ir.stmts)][:type]
idx -= length(ir.stmts)
stmts = ir.new_nodes.stmts
(idx length(stmts)) || throw(InvalidIRError())
return stmts[idx][:type]
end
end
end
Expand Down
Loading

0 comments on commit 4a93041

Please sign in to comment.