Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NewOptimizer] Backport reverse affinity changes from #26778 #26918

Merged
merged 1 commit into from
May 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 44 additions & 27 deletions base/compiler/ssair/ir.jl
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,18 @@ function first_insert_for_bb(code, cfg::CFG, block::Int)
end
end


const NewNode = Tuple{Int, #= reverse affinity =#Bool, Any, Any, #=LineNumber=#Int}
struct NewNode
# Insertion position (interpretation depends on which array this is in)
pos::Int
# Place the new instruction after this instruction (but in the same BB if this is an implicit terminator)
attach_after::Bool
# The type of the instruction to insert
typ::Any
# The node itself
node::Any
# The index into the line number table of this entry
line::Int
end

struct IRCode
stmts::Vector{Any}
Expand All @@ -174,7 +184,7 @@ function getindex(x::IRCode, s::SSAValue)
if s.id <= length(x.stmts)
return x.stmts[s.id]
else
return x.new_nodes[s.id - length(x.stmts)][4]
return x.new_nodes[s.id - length(x.stmts)].node
end
end

Expand Down Expand Up @@ -374,9 +384,9 @@ function foreachssa(f, @nospecialize(stmt))
end
end

function insert_node!(ir::IRCode, pos::Int, @nospecialize(typ), @nospecialize(val), reverse_affinity::Bool=false)
function insert_node!(ir::IRCode, pos::Int, @nospecialize(typ), @nospecialize(val), attach_after::Bool=false)
line = ir.lines[pos]
push!(ir.new_nodes, (pos, reverse_affinity, typ, val, line))
push!(ir.new_nodes, NewNode(pos, attach_after, typ, val, line))
return SSAValue(length(ir.stmts) + length(ir.new_nodes))
end

Expand Down Expand Up @@ -407,8 +417,8 @@ mutable struct IncrementalCompact
result_idx::Int
active_result_bb::Int
function IncrementalCompact(code::IRCode)
# Sort by position with reverse affinity nodes before regular ones
perm = my_sortperm(Int[(code.new_nodes[i][1]*2 + Int(!code.new_nodes[i][2])) for i in 1:length(code.new_nodes)])
# Sort by position with attach after nodes affter regular ones
perm = my_sortperm(Int[(code.new_nodes[i].pos*2 + Int(code.new_nodes[i].attach_after)) for i in 1:length(code.new_nodes)])
new_len = length(code.stmts) + length(code.new_nodes)
result = Array{Any}(undef, new_len)
result_types = Array{Any}(undef, new_len)
Expand All @@ -422,7 +432,7 @@ mutable struct IncrementalCompact

# For inlining
function IncrementalCompact(parent::IncrementalCompact, code::IRCode, result_offset)
perm = my_sortperm(Int[code.new_nodes[i][1] for i in 1:length(code.new_nodes)])
perm = my_sortperm(Int[code.new_nodes[i].pos for i in 1:length(code.new_nodes)])
new_len = length(code.stmts) + length(code.new_nodes)
ssa_rename = Any[SSAValue(i) for i = 1:new_len]
used_ssas = fill(0, new_len)
Expand Down Expand Up @@ -509,7 +519,7 @@ function getindex(view::TypesView, idx)
if idx <= length(ir.types)
return ir.types[idx]
else
return ir.new_nodes[idx - length(ir.types)][3]
return ir.new_nodes[idx - length(ir.types)].typ
end
end

Expand Down Expand Up @@ -603,10 +613,27 @@ function finish_current_bb!(compact, old_result_idx=compact.result_idx)
end
end

function reverse_affinity_stmt_after(compact::IncrementalCompact, idx::Int)
function attach_after_stmt_after(compact::IncrementalCompact, idx::Int)
compact.new_nodes_idx > length(compact.perm) && return false
entry = compact.ir.new_nodes[compact.perm[compact.new_nodes_idx]]
entry[1] == idx + 1 && entry[2]
entry.pos == idx && entry.attach_after
end

function process_newnode!(compact, new_idx, new_node_entry, idx, active_bb)
old_result_idx = compact.result_idx
bb = compact.ir.cfg.blocks[active_bb]
compact.result_types[old_result_idx] = new_node_entry.typ
compact.result_lines[old_result_idx] = new_node_entry.line
result_idx = process_node!(compact, old_result_idx, new_node_entry.node, new_idx, idx)
compact.result_idx = result_idx
# If this instruction has reverse affinity and we were at the end of a basic block,
# finish it now.
if new_node_entry.attach_after && idx == last(bb.stmts)+1 && !attach_after_stmt_after(compact, idx-1)
active_bb += 1
finish_current_bb!(compact, old_result_idx)
end
(old_result_idx == result_idx) && return next(compact, (idx, active_bb))
return Pair{Int, Any}(old_result_idx, compact.result[old_result_idx]), (compact.idx, active_bb)
end

function next(compact::IncrementalCompact, (idx, active_bb)::Tuple{Int, Int})
Expand All @@ -615,24 +642,14 @@ function next(compact::IncrementalCompact, (idx, active_bb)::Tuple{Int, Int})
resize!(compact, old_result_idx)
end
bb = compact.ir.cfg.blocks[active_bb]
if compact.new_nodes_idx <= length(compact.perm) && compact.ir.new_nodes[compact.perm[compact.new_nodes_idx]][1] == idx
if compact.new_nodes_idx <= length(compact.perm) &&
(entry = compact.ir.new_nodes[compact.perm[compact.new_nodes_idx]];
entry.attach_after ? entry.pos == idx - 1 : entry.pos == idx)
new_idx = compact.perm[compact.new_nodes_idx]
compact.new_nodes_idx += 1
_, reverse_affinity, typ, new_node, new_line = compact.ir.new_nodes[new_idx]
new_node_entry = compact.ir.new_nodes[new_idx]
new_idx += length(compact.ir.stmts)
compact.result_types[old_result_idx] = typ
compact.result_lines[old_result_idx] = new_line
compact.result_flags[old_result_idx] = 0x00
result_idx = process_node!(compact, old_result_idx, new_node, new_idx, idx)
compact.result_idx = result_idx
# If this instruction has reverse affinity and we were at the end of a basic block,
# finish it now.
if reverse_affinity && idx == last(bb.stmts)+1 && !reverse_affinity_stmt_after(compact, idx-1)
active_bb += 1
finish_current_bb!(compact, old_result_idx)
end
(old_result_idx == result_idx) && return next(compact, (idx, active_bb))
return Pair{Int, Any}(old_result_idx, compact.result[old_result_idx]), (compact.idx, active_bb)
return process_newnode!(compact, new_idx, new_node_entry, idx, active_bb)
end
# This will get overwritten in future iterations if
# result_idx is not, incremented, but that's ok and expected
Expand All @@ -642,7 +659,7 @@ function next(compact::IncrementalCompact, (idx, active_bb)::Tuple{Int, Int})
result_idx = process_node!(compact, old_result_idx, compact.ir.stmts[idx], idx, idx)
stmt_if_any = old_result_idx == result_idx ? nothing : compact.result[old_result_idx]
compact.result_idx = result_idx
if idx == last(bb.stmts) && !reverse_affinity_stmt_after(compact, idx)
if idx == last(bb.stmts) && !attach_after_stmt_after(compact, idx)
active_bb += 1
finish_current_bb!(compact, old_result_idx)
end
Expand Down
12 changes: 6 additions & 6 deletions base/compiler/ssair/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ function Base.show(io::IO, code::IRCode)
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)
foreach(nn -> scan_ssa_use!(used, nn.node), new_nodes)
if isempty(used)
maxsize = 0
else
Expand Down Expand Up @@ -118,7 +118,7 @@ function Base.show(io::IO, code::IRCode)
floop = true
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]
new_node = code.new_nodes[node_idx]
node_idx += length(code.stmts)
if print_sep
if floop
Expand All @@ -129,13 +129,13 @@ function Base.show(io::IO, code::IRCode)
end
print_sep = true
floop = false
print_ssa_typ = !isa(node, PiNode) && node_idx in used
print_ssa_typ = !isa(new_node.node, PiNode) && node_idx in used
Base.with_output_color(:yellow, io) do io′
print_node(io′, node_idx, node, used, maxsize; color = false,
print_typ=!print_ssa_typ || (isa(node, Expr) && typ != node.typ))
print_node(io′, node_idx, new_node.node, used, maxsize; color = false,
print_typ=!print_ssa_typ || (isa(new_node.node, Expr) && typ != new_node.node.typ))
end
if print_ssa_typ
Base.printstyled(io, "::$(typ)", color=:red)
Base.printstyled(io, "::$(new_node.typ)", color=:red)
end
Base.println(io)
end
Expand Down
60 changes: 33 additions & 27 deletions base/compiler/ssair/slot2ssa.jl
Original file line number Diff line number Diff line change
Expand Up @@ -426,11 +426,15 @@ function domsort_ssa!(ir::IRCode, domtree::DomTree)
end
result_stmts = Any[renumber_ssa!(result_stmts[i], inst_rename, true) for i in 1:length(result_stmts)]
cfg = CFG(new_bbs, Int[first(bb.stmts) for bb in new_bbs[2:end]])
new_new_nodes = NewNode[let (pos, reverse_affinity, typ, node, lno) = ir.new_nodes[i]
isa(node, PhiNode) && (node = rename_phinode_edges(node, 0, result_order, bb_rename))
node = renumber_ssa!(node, inst_rename, true)
(inst_rename[pos].id, reverse_affinity, typ, node, lno)
end for i in 1:length(ir.new_nodes)]
new_new_nodes = Vector{NewNode}(undef, length(ir.new_nodes))
for i = 1:length(ir.new_nodes)
entry = ir.new_nodes[i]
new_new_nodes[i] = NewNode(inst_rename[entry.pos].id, entry.attach_after, entry.typ,
renumber_ssa!(isa(entry.node, PhiNode) ?
rename_phinode_edges(entry.node, 0, result_order, bb_rename) : entry.node,
inst_rename, true),
entry.line)
end
new_ir = IRCode(ir, result_stmts, result_types, result_ltable, result_flags, cfg, new_new_nodes)
return new_ir
end
Expand Down Expand Up @@ -602,12 +606,12 @@ function construct_ssa!(ci::CodeInfo, code::Vector{Any}, ir::IRCode, domtree::Do
end
typ = incoming_val == undef_token ? MaybeUndef(Union{}) : typ_for_val(incoming_val, ci)
new_node_id = ssaval - length(ir.stmts)
old_insert, reverse_affinity, old_typ, _, old_line = ir.new_nodes[new_node_id]
old_entry = ir.new_nodes[new_node_id]
if isa(typ, DelayedTyp)
push!(type_refine_phi, ssaval)
end
new_typ = isa(typ, DelayedTyp) ? Union{} : tmerge(old_typ, typ)
ir.new_nodes[new_node_id] = (old_insert, reverse_affinity, new_typ, node, old_line)
new_typ = isa(typ, DelayedTyp) ? Union{} : tmerge(old_entry.typ, typ)
ir.new_nodes[new_node_id] = NewNode(old_entry.pos, old_entry.attach_after, new_typ, node, old_entry.line)
incoming_vals[slot] = NewSSAValue(ssaval)
end
(item in visited) && continue
Expand Down Expand Up @@ -666,7 +670,7 @@ function construct_ssa!(ci::CodeInfo, code::Vector{Any}, ir::IRCode, domtree::Do
typ = MaybeUndef(Union{})
end
push!(phicnodes[exc][cidx][3].values,
NewSSAValue(insert_node!(ir, idx+1, typ, node, true).id))
NewSSAValue(insert_node!(ir, idx, typ, node, true).id))
end
end
end
Expand Down Expand Up @@ -717,16 +721,16 @@ function construct_ssa!(ci::CodeInfo, code::Vector{Any}, ir::IRCode, domtree::Do
for (_, ssa, node) in nodes
new_typ = Union{}
new_idx = ssa.id - length(ir.stmts)
old_insert, reverse_affinity, old_typ, _, old_line = ir.new_nodes[new_idx]
for i = 1:length(node.values)
orig_typ = typ = typ_for_val(node.values[i], ci)
node = ir.new_nodes[new_idx]
for i = 1:length(node.node.values)
orig_typ = typ = typ_for_val(node.node.values[i], ci)
@assert !isa(typ, MaybeUndef)
while isa(typ, DelayedTyp)
typ = ir.new_nodes[typ.phi.id - length(ir.stmts)][3]
typ = ir.new_nodes[typ.phi.id - length(ir.stmts)].typ
end
new_typ = tmerge(new_typ, typ)
end
ir.new_nodes[new_idx] = (old_insert, reverse_affinity, new_typ, node, old_line)
ir.new_nodes[new_idx] = NewNode(node.pos, node.attach_after, new_typ, node.node, node.line)
end
end
# This is a bit awkward, because it basically duplicates what type
Expand All @@ -737,42 +741,44 @@ function construct_ssa!(ci::CodeInfo, code::Vector{Any}, ir::IRCode, domtree::Do
changed = false
for phi in type_refine_phi
new_idx = phi - length(ir.stmts)
old_insert, reverse_affinity, old_typ, node, old_line = ir.new_nodes[new_idx]
node = ir.new_nodes[new_idx]
new_typ = Union{}
for i = 1:length(node.values)
if !isassigned(node.values, i)
for i = 1:length(node.node.values)
if !isassigned(node.node.values, i)
if !isa(new_typ, MaybeUndef)
new_typ = MaybeUndef(new_typ)
end
continue
end
typ = typ_for_val(node.values[i], ci)
typ = typ_for_val(node.node.values[i], ci)
was_maybe_undef = false
if isa(typ, MaybeUndef)
typ = typ.typ
was_maybe_undef = true
end
@assert !isa(typ, MaybeUndef)
while isa(typ, DelayedTyp)
typ = ir.new_nodes[typ.phi.id - length(ir.stmts)][3]
typ = ir.new_nodes[typ.phi.id - length(ir.stmts)].typ
end
new_typ = tmerge(new_typ, was_maybe_undef ? MaybeUndef(typ) : typ)
end
if !(old_typ ⊑ new_typ) || !(new_typ ⊑ old_typ)
ir.new_nodes[new_idx] = (old_insert, reverse_affinity, new_typ, node, old_line)
if !(node.typ ⊑ new_typ) || !(new_typ ⊑ node.typ)
ir.new_nodes[new_idx] = NewNode(node.pos, node.attach_after, new_typ, node.node, node.line)
changed = true
end
end
end
types = Any[isa(types[i], DelayedTyp) ? ir.new_nodes[types[i].phi.id - length(ir.stmts)][2] : types[i] for i in 1:length(types)]
new_nodes = NewNode[let (pos, reverse_affinity, typ, node, line) = ir.new_nodes[i]
typ = isa(typ, DelayedTyp) ? ir.new_nodes[typ.phi.id - length(ir.stmts)][2] : typ
(pos, reverse_affinity, typ, node, line)
types = Any[isa(types[i], DelayedTyp) ? ir.new_nodes[types[i].phi.id - length(ir.stmts)].typ : types[i] for i in 1:length(types)]
new_nodes = NewNode[let node = ir.new_nodes[i]
typ = isa(node.typ, DelayedTyp) ? ir.new_nodes[node.typ.phi.id - length(ir.stmts)].typ : node.typ
NewNode(node.pos, node.attach_after, typ, node.node, node.line)
end for i in 1:length(ir.new_nodes)]
# Renumber SSA values
new_code = Any[new_to_regular(renumber_ssa!(new_code[i], ssavalmap)) for i in 1:length(new_code)]
new_nodes = NewNode[let (pt, reverse_affinity, typ, stmt, line) = new_nodes[i]
(pt, reverse_affinity, typ, new_to_regular(renumber_ssa!(stmt, ssavalmap)), line)
new_nodes = NewNode[let node = new_nodes[i]
NewNode(node.pos, node.attach_after, node.typ,
new_to_regular(renumber_ssa!(node.node, ssavalmap)),
node.line)
end for i in 1:length(new_nodes)]
ir = IRCode(ir, new_code, types, ir.lines, ir.flags, ir.cfg, new_nodes)
@timeit "domsort" ir = domsort_ssa!(ir, domtree)
Expand Down
4 changes: 2 additions & 2 deletions base/compiler/ssair/verify.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ end
function check_op(ir::IRCode, domtree::DomTree, @nospecialize(op), use_bb::Int, use_idx::Int)
if isa(op, SSAValue)
if op.id > length(ir.stmts)
def_bb = block_for_inst(ir.cfg, ir.new_nodes[op.id - length(ir.stmts)][1])
def_bb = block_for_inst(ir.cfg, ir.new_nodes[op.id - length(ir.stmts)].pos)
else
def_bb = block_for_inst(ir.cfg, op.id)
end
if (def_bb == use_bb)
if op.id > length(ir.stmts)
@assert ir.new_nodes[op.id - length(ir.stmts)][1] <= use_idx
@assert ir.new_nodes[op.id - length(ir.stmts)].pos <= use_idx
else
@assert op.id < use_idx
end
Expand Down