Skip to content

Commit

Permalink
ssair: fix misc bugs, improve printer
Browse files Browse the repository at this point in the history
  • Loading branch information
vtjnash authored and Keno committed Apr 5, 2018
1 parent 5bb3290 commit 10776d9
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 82 deletions.
27 changes: 9 additions & 18 deletions base/compiler/optimize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ function isinlineable(m::Method, src::CodeInfo, mod::Module, params::Params, bon
return inlineable
end

const enable_new_optimizer = RefValue(true)
const enable_new_optimizer = RefValue(false)

# converge the optimization work
function optimize(me::InferenceState)
Expand Down Expand Up @@ -292,15 +292,20 @@ function optimize(me::InferenceState)
force_noinline = any(x->isexpr(x, :meta) && x.args[1] == :noinline, ir.meta)
#@timeit "legacy conversion" replace_code!(opt.src, ir, nargs, linetable)
replace_code_newstyle!(opt.src, ir, nargs, linetable)
any_phi = true
elseif false # !any_phi
else
# This pass is required for the AST to be valid in codegen
# if any `SSAValue` is created by type inference. Ref issue #6068
# This (and `reindex_labels!`) needs to be run for `!me.optimize`
# if we start to create `SSAValue` in type inference when not
# optimizing and use unoptimized IR in codegen.
gotoifnot_elim_pass!(opt)
inlining_pass!(opt, opt.src.propagate_inbounds)
# Clean up after inlining
gotoifnot_elim_pass!(opt)
basic_dce_pass!(opt)
void_use_elim_pass!(opt)
if !enable_new_optimizer[]
any_phi = any(x->isa(x, PhiNode) || (isa(x, Expr) && x.head == :(=) && isa(x.args[2], PhiNode)), opt.src.code)
if !any_phi && !enable_new_optimizer[]
copy_duplicated_expr_pass!(opt)
split_undef_flag_pass!(opt)
fold_constant_getfield_pass!(opt)
Expand All @@ -319,20 +324,6 @@ function optimize(me::InferenceState)
force_noinline = peekmeta(code, :noinline)[1]
reindex_labels!(opt)
end
elseif enable_new_optimizer[]
# This pass is required for the AST to be valid in codegen
# if any `SSAValue` is created by type inference. Ref issue #6068
# This (and `reindex_labels!`) needs to be run for `!me.optimize`
# if we start to create `SSAValue` in type inference when not
# optimizing and use unoptimized IR in codegen.
gotoifnot_elim_pass!(opt)
# Pop metadata before label reindexing
let code = opt.src.code::Array{Any,1}
meta_elim_pass!(code, coverage_enabled())
filter!(x -> x !== nothing, code)
force_noinline = peekmeta(code, :noinline)[1]
reindex_labels!(opt)
end
end
me.min_valid = opt.min_valid
me.max_valid = opt.max_valid
Expand Down
14 changes: 9 additions & 5 deletions base/compiler/ssair/driver.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
using Core: LineInfoNode
const NullLineInfo = LineInfoNode(@__MODULE__, Symbol(""), Symbol(""), 0, 0)

if false
import Base: Base, @show
else
macro show(s)
return :(println(stdout, $(QuoteNode(s)), " = ", $(esc(s))))
end
end

include("compiler/ssair/ir.jl")
include("compiler/ssair/domtree.jl")
include("compiler/ssair/slot2ssa.jl")
Expand All @@ -9,11 +17,7 @@ include("compiler/ssair/passes.jl")
include("compiler/ssair/inlining2.jl")
include("compiler/ssair/verify.jl")
include("compiler/ssair/legacy.jl")


macro show(s)
# return :(println($(QuoteNode(s)), " = ", $(esc(s))))
end
@isdefined(Base) && include("compiler/ssair/show.jl")

function normalize_expr(stmt::Expr)
if stmt.head === :gotoifnot
Expand Down
2 changes: 1 addition & 1 deletion base/compiler/ssair/inlining2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ function assemble_inline_todo!(ir, domtree, linetable, sv)
end

@timeit "inline IR inflation" if src.codelocs === nothing
topline = LineInfoNode(method.module, method.name, method.file, method.line, 0)
topline = LineInfoNode(method.module, method.name, method.file, Int(method.line), 0)
inline_linetable = [topline]
push!(ast, LabelNode(length(ast) + 1))
ir2 = just_construct_ssa(src, ast, na-1, inline_linetable)
Expand Down
29 changes: 21 additions & 8 deletions base/compiler/ssair/passes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,13 @@ function walk_to_def(compact, def, intermediaries = IdSet{Int}(), allow_phinode=
def = def.val
end
continue
elseif isa(def, FastForward)
def = def.to
append!(phi_locs, def.phi_locs)
elseif isa(def, PhiNode)
# For now, we don't track setfields structs through phi nodes
allow_phinode || break
push!(intermediaries, defidx)
possible_predecessors = collect(Iterators.filter(1:length(def.edges)) do n
isassigned(def.values, n) || return false
value = def.values[n]
Expand Down Expand Up @@ -189,6 +193,11 @@ function process_immutable_preserve(new_preserves, compact, def)
end
end

struct FastForward
to
phi_locs
end

function getfield_elim_pass!(ir::IRCode, domtree)
compact = IncrementalCompact(ir)
insertions = Vector{Any}()
Expand Down Expand Up @@ -292,16 +301,18 @@ function getfield_elim_pass!(ir::IRCode, domtree)
field === nothing && continue
isdefined(obj, field) || continue
val = getfield(obj, field)
is_inlineable_constant(val) || continue
is_inlineable_constant(val) || continue
forwarded = quoted(val)
end
# Step 4: Remember any phinodes we need to insert
if !isempty(phi_locs) && isa(forwarded, SSAValue)
# TODO: We have have to use BB ids for phi_locs
# to avoid index invalidation.
push!(insertions, (idx, phi_locs))
push!(insertions, idx)
compact[idx] = FastForward(forwarded, phi_locs)
else
compact[idx] = forwarded
end
compact[idx] = forwarded
end
ir = finish(compact)
# Now go through any mutable structs and see which ones we can eliminate
Expand Down Expand Up @@ -389,17 +400,19 @@ function getfield_elim_pass!(ir::IRCode, domtree)
old_preserves = filter(ssa->!isa(ssa, SSAValue) || !(ssa.id in intermediaries), useexpr.args[(6+nccallargs):end])
new_expr = Expr(:foreigncall, useexpr.args[1:(6+nccallargs-1)]...,
old_preserves..., new_preserves...)
new_expr.typ = useexpr.typ
ir[SSAValue(use)] = new_expr
new_expr.typ = useexpr.typ
ir[SSAValue(use)] = new_expr
end
end
for (idx, phi_locs) in insertions
for idx in insertions
# For non-dominating load-store forward, we may have to insert extra phi nodes
# TODO: Can use the domtree to eliminate unnecessary phis, but ok for now
forwarded = ir.stmts[idx]
ff = ir.stmts[idx]
@assert isa(ff, FastForward)
forwarded = ff.to
if isa(forwarded, SSAValue)
forwarded_typ = ir.types[forwarded.id]
for (pred, pos) in reverse!(phi_locs)
for (pred, pos) in reverse!(ff.phi_locs)
node = PhiNode()
push!(node.edges, pred)
push!(node.values, forwarded)
Expand Down
87 changes: 47 additions & 40 deletions base/compiler/ssair/show.jl
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
if Pair != Base.Pair
import Base: Base, IOContext, string, join, sprint
IOContext(io::IO, KV::Pair) = IOContext(io, Base.Pair(KV[1], KV[2]))
length(s::String) = Base.length(s)
^(s::String, i::Int) = Base.:^(s, i)
end

function Base.show(io::IO, cfg::CFG)
foreach(pairs(cfg.blocks)) do (idx, block)
println("$idx\t=>\t", join(block.succs, ", "))
Base.println("$idx\t=>\t", join(block.succs, ", "))
end
end

print_ssa(io::IO, val) = isa(val, SSAValue) ? print(io, "%$(val.id)") :
isa(val, Argument) ? print(io, "%%$(val.n)") : print(io, val)
print_ssa(io::IO, val) = isa(val, SSAValue) ? Base.print(io, "%$(val.id)") :
isa(val, Argument) ? Base.print(io, "%%$(val.n)") : Base.print(io, val)
function print_node(io::IO, idx, stmt, used, maxsize; color = true, print_typ=true)
if idx in used
pad = " "^(maxsize-length(string(idx)))
print(io, "%$idx $pad= ")
Base.print(io, "%$idx $pad= ")
else
print(io, " "^(maxsize+4))
Base.print(io, " "^(maxsize+4))
end
if isa(stmt, PhiNode)
args = map(1:length(stmt.edges)) do i
Expand All @@ -22,56 +29,56 @@ function print_node(io::IO, idx, stmt, used, maxsize; color = true, print_typ=tr
end
"$e => $v"
end
print(io, "φ ", '(', join(args, ", "), ')')
Base.print(io, "φ ", '(', join(args, ", "), ')')
elseif isa(stmt, PhiCNode)
print(io, "φᶜ ", '(', join(map(x->sprint(print_ssa, x), stmt.values), ", "), ')')
Base.print(io, "φᶜ ", '(', join(map(x->sprint(print_ssa, x), stmt.values), ", "), ')')
elseif isa(stmt, PiNode)
print(io, "π (")
Base.print(io, "π (")
print_ssa(io, stmt.val)
print(io, ", ")
Base.print(io, ", ")
if color
printstyled(io, stmt.typ, color=:red)
Base.printstyled(io, stmt.typ, color=:red)
else
print(io, stmt.typ)
Base.print(io, stmt.typ)
end
print(io, ")")
Base.print(io, ")")
elseif isa(stmt, UpsilonNode)
print(io, "ϒ (")
Base.print(io, "ϒ (")
isdefined(stmt, :val) ?
print_ssa(io, stmt.val) :
print(io, "#undef")
print(io, ")")
Base.print(io, "#undef")
Base.print(io, ")")
elseif isa(stmt, ReturnNode)
if !isdefined(stmt, :val)
print(io, "unreachable")
Base.print(io, "unreachable")
else
print(io, "return ")
Base.print(io, "return ")
print_ssa(io, stmt.val)
end
elseif isa(stmt, GotoIfNot)
print(io, "goto ", stmt.dest, " if not ")
Base.print(io, "goto ", stmt.dest, " if not ")
print_ssa(io, stmt.cond)
elseif isexpr(stmt, :call)
print_ssa(io, stmt.args[1])
print(io, "(")
print(io, join(map(arg->sprint(io->print_ssa(io, arg)), stmt.args[2:end]), ", "))
print(io, ")")
Base.print(io, "(")
Base.print(io, join(map(arg->sprint(io->print_ssa(io, arg)), stmt.args[2:end]), ", "))
Base.print(io, ")")
if print_typ && stmt.typ !== Any
print(io, "::$(stmt.typ)")
Base.print(io, "::$(stmt.typ)")
end
elseif isexpr(stmt, :new)
print(io, "new(")
print(io, join(map(arg->sprint(io->print_ssa(io, arg)), stmt.args), ", "))
print(io, ")")
Base.print(io, "new(")
Base.print(io, join(map(arg->sprint(io->print_ssa(io, arg)), stmt.args), ", "))
Base.print(io, ")")
else
print(io, stmt)
Base.print(io, stmt)
end
end

function Base.show(io::IO, code::IRCode)
io = IOContext(io, :color=>true)
used = Set{Int}()
println(io, "Code")
used = IdSet{Int}()
Base.println(io, "Code")
foreach(stmt->scan_ssa_use!(used, stmt), code.stmts)
foreach(((_a, _b, node, _d),) -> scan_ssa_use!(used, node), code.new_nodes)
if isempty(used)
Expand All @@ -85,7 +92,7 @@ function Base.show(io::IO, code::IRCode)
bb_idx = 1
perm = sortperm(code.new_nodes, by = x->x[1])
new_nodes_perm = Iterators.Stateful(perm)
for idx in Iterators.eachindex(code.stmts)
for idx in eachindex(code.stmts)
if !isassigned(code.stmts, idx)
# This is invalid, but do something useful rather
# than erroring, to make debugging easier
Expand All @@ -99,25 +106,25 @@ function Base.show(io::IO, code::IRCode)
bb_start_str = string("$(bb_idx) ",length(cfg.blocks[bb_idx].preds) <= 1 ? "" : "", ""^(bb_pad)," ")
if idx != last(bbrange)
if idx == first(bbrange)
print(io, bb_start_str)
Base.print(io, bb_start_str)
else
print(io, ""," "^max_bb_idx_size)
Base.print(io, ""," "^max_bb_idx_size)
end
end
print_sep = false
if idx == last(bbrange)
print_sep = true
end
floop = true
while !isempty(new_nodes_perm) && code.new_nodes[Base.peek(new_nodes_perm)][1] == idx
while !isempty(new_nodes_perm) && code.new_nodes[peek(new_nodes_perm)][1] == idx
node_idx = popfirst!(new_nodes_perm)
_, reverse_affinity, typ, node, line = code.new_nodes[node_idx]
node_idx += length(code.stmts)
if print_sep
if floop
print(io, bb_start_str)
Base.print(io, bb_start_str)
else
print(io, ""," "^max_bb_idx_size)
Base.print(io, ""," "^max_bb_idx_size)
end
end
print_sep = true
Expand All @@ -128,15 +135,15 @@ function Base.show(io::IO, code::IRCode)
print_typ=!print_ssa_typ || (isa(node, Expr) && typ != node.typ))
end
if print_ssa_typ
printstyled(io, "::$(typ)", color=:red)
Base.printstyled(io, "::$(typ)", color=:red)
end
println(io)
Base.println(io)
end
if print_sep
if idx == first(bbrange) && floop
print(io, bb_start_str)
Base.print(io, bb_start_str)
else
print(io, idx == last(bbrange) ? string("", ""^(1+max_bb_idx_size), " ") :
Base.print(io, idx == last(bbrange) ? string("", ""^(1+max_bb_idx_size), " ") :
string("", " "^max_bb_idx_size))
end
end
Expand All @@ -154,8 +161,8 @@ function Base.show(io::IO, code::IRCode)
print_node(io, idx, stmt, used, maxsize,
print_typ=!print_ssa_typ || (isa(stmt, Expr) && typ != stmt.typ))
if print_ssa_typ
printstyled(io, "::$(typ)", color=:red)
Base.printstyled(io, "::$(typ)", color=:red)
end
println(io)
Base.println(io)
end
end
Loading

0 comments on commit 10776d9

Please sign in to comment.