Skip to content
Closed
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
3 changes: 3 additions & 0 deletions Make.inc
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,9 @@ USE_POLLY := 0
USE_POLLY_OPENMP := 0 # Enable OpenMP code-generation
USE_POLLY_ACC := 0 # Enable GPU code-generation

# Option to enable experimental Tapir support
USE_TAPIR := 0

# Cross-compile
#XC_HOST := i686-w64-mingw32
#XC_HOST := x86_64-w64-mingw32
Expand Down
24 changes: 22 additions & 2 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,21 @@
# name::Symbol
#end

#struct DetachNode
# syncregion
# label::Int
# reattach::Int
#end

#struct ReattachNode
# syncregion
# label::Int
#end

#struct SyncNode
# syncregion
#end

#mutable struct Task
# parent::Task
# storage::Any
Expand Down Expand Up @@ -379,6 +394,9 @@ eval(Core, :(UpsilonNode(val) = $(Expr(:new, :UpsilonNode, :val))))
eval(Core, :(UpsilonNode() = $(Expr(:new, :UpsilonNode))))
eval(Core, :(LineInfoNode(@nospecialize(method), file::Symbol, line::Int, inlined_at::Int) =
$(Expr(:new, :LineInfoNode, :method, :file, :line, :inlined_at))))
eval(Core, :(SyncNode(token) = $(Expr(:new, :SyncNode, :token))))
eval(Core, :(DetachNode(token, bb::Int, reattach::Int) = $(Expr(:new, :DetachNode, :token, :bb, :reattach))))
eval(Core, :(ReattachNode(token, bb::Int) = $(Expr(:new, :ReattachNode, :token, :bb))))

Module(name::Symbol=:anonymous, std_imports::Bool=true) = ccall(:jl_f_new_module, Ref{Module}, (Any, Bool), name, std_imports)

Expand Down Expand Up @@ -447,11 +465,13 @@ Symbol(s::Symbol) = s
module IR
export CodeInfo, MethodInstance, CodeInstance, GotoNode,
NewvarNode, SSAValue, Slot, SlotNumber, TypedSlot,
PiNode, PhiNode, PhiCNode, UpsilonNode, LineInfoNode
PiNode, PhiNode, PhiCNode, UpsilonNode, LineInfoNode,
DetachNode, ReattachNode, SyncNode

import Core: CodeInfo, MethodInstance, CodeInstance, GotoNode,
NewvarNode, SSAValue, Slot, SlotNumber, TypedSlot,
PiNode, PhiNode, PhiCNode, UpsilonNode, LineInfoNode
PiNode, PhiNode, PhiCNode, UpsilonNode, LineInfoNode,
DetachNode, ReattachNode, SyncNode

end

Expand Down
18 changes: 17 additions & 1 deletion base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1107,6 +1107,21 @@ function typeinf_local(frame::InferenceState)
changes[sn] = VarState(Bottom, true)
elseif isa(stmt, GotoNode)
pc´ = (stmt::GotoNode).label
elseif isa(stmt, DetachNode)
# A detach node has two edges we need to add
# the reattach edge to the work queue
l = (stmt::DetachNode).reattach
newstate_reattach = stupdate!(s[l], changes)
if newstate_reattach !== false
if l < frame.pc´´
frame.pc´´ = l
end
push!(W, l)
s[l] = newstate_reattach
end
pc´ = (stmt::DetachNode).label
elseif isa(stmt, ReattachNode)
pc´ = (stmt::ReattachNode).label
elseif hd === :gotoifnot
condt = abstract_eval(stmt.args[1], s[pc], frame)
if condt === Bottom
Expand Down Expand Up @@ -1197,7 +1212,8 @@ function typeinf_local(frame::InferenceState)
if isa(fname, Slot)
changes = StateUpdate(fname, VarState(Any, false), changes)
end
elseif hd === :inbounds || hd === :meta || hd === :loopinfo
elseif hd === :inbounds || hd === :meta || hd === :loopinfo ||
(stmt isa SyncNode)
else
t = abstract_eval(stmt, changes, frame)
t === Bottom && break
Expand Down
24 changes: 23 additions & 1 deletion base/compiler/optimize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ end
# if there is no usage within the function), but don't affect the purity
# of the function as a whole.
function stmt_affects_purity(@nospecialize(stmt), ir)
if isa(stmt, GotoNode) || isa(stmt, ReturnNode)
if isa(stmt, GotoNode) || isa(stmt, ReturnNode) ||
isa(stmt, DetachNode) || isa(stmt, ReattachNode) || isa(stmt, SyncNode)
return false
end
if isa(stmt, GotoIfNot)
Expand Down Expand Up @@ -412,6 +413,27 @@ function renumber_ir_elements!(body::Vector{Any}, ssachangemap::Vector{Int}, lab
el = body[i]
if isa(el, GotoNode)
body[i] = GotoNode(el.label + labelchangemap[el.label])
elseif isa(el, DetachNode)
syncregion = el.syncregion
if isa(syncregion, SSAValue)
syncregion = SSAValue(syncregion.id + ssachangemap[syncregion.id])
end
label = el.label + labelchangemap[el.label]
reattach = el.reattach + labelchangemap[el.label]
body[i] = DetachNode(syncregion, label, reattach)
elseif isa(el, ReattachNode)
syncregion = el.syncregion
if isa(syncregion, SSAValue)
syncregion = SSAValue(syncregion.id + ssachangemap[syncregion.id])
end
label = el.label + labelchangemap[el.label]
body[i] = ReattachNode(syncregion, label)
elseif isa(el, SyncNode)
syncregion = el.syncregion
if isa(syncregion, SSAValue)
syncregion = SSAValue(syncregion.id + ssachangemap[syncregion.id])
end
body[i] = SyncNode(syncregion)
elseif isa(el, SSAValue)
body[i] = SSAValue(el.id + ssachangemap[el.id])
elseif isa(el, Expr)
Expand Down
8 changes: 8 additions & 0 deletions base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,10 @@ function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector
end
elseif isa(stmt′, GotoNode)
stmt′ = GotoNode(stmt′.label + bb_offset)
elseif isa(stmt′, DetachNode)
stmt′ = DetachNode(stmt′.syncregion, stmt′.label + bb_offset, stmt′.reattach + bb_offset)
elseif isa(stmt′, ReattachNode)
stmt′ = ReattachNode(stmt′.syncregion, stmt′.label + bb_offset)
elseif isa(stmt′, Expr) && stmt′.head == :enter
stmt′ = Expr(:enter, stmt′.args[1] + bb_offset)
elseif isa(stmt′, GotoIfNot)
Expand Down Expand Up @@ -560,6 +564,10 @@ function batch_inline!(todo::Vector{Any}, ir::IRCode, linetable::Vector{LineInfo
end
elseif isa(stmt, GotoNode)
compact[idx] = GotoNode(state.bb_rename[stmt.label])
elseif isa(stmt, DetachNode)
compact[idx] = DetachNode(stmt.syncregion, state.bb_rename[stmt.label], state.bb_rename[stmt.reattach])
elseif isa(stmt, ReattachNode)
compact[idx] = ReattachNode(stmt.syncregion, state.bb_rename[stmt.label])
elseif isa(stmt, Expr) && stmt.head == :enter
compact[idx] = Expr(:enter, state.bb_rename[stmt.args[1]])
elseif isa(stmt, GotoIfNot)
Expand Down
46 changes: 44 additions & 2 deletions base/compiler/ssair/ir.jl
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ function basic_blocks_starts(stmts::Vector{Any})
# This is a fake dest to force the next stmt to start a bb
idx < length(stmts) && push!(jump_dests, idx+1)
push!(jump_dests, stmt.label)
elseif isa(stmt, DetachNode)
push!(jump_dests, stmt.label)
push!(jump_dests, stmt.reattach)
elseif isa(stmt, ReattachNode)
push!(jump_dests, stmt.label)
elseif isa(stmt, SyncNode)
push!(jump_dests, idx+1)
elseif isa(stmt, Expr)
if stmt.head === :leave
# :leave terminates a BB
Expand Down Expand Up @@ -134,12 +141,22 @@ function compute_basic_blocks(stmts::Vector{Any})
# return never has any successors
continue
end
if isa(terminator, GotoNode)
if isa(terminator, GotoNode) || isa(terminator, ReattachNode)
block′ = block_for_inst(basic_block_index, terminator.label)
push!(blocks[block′].preds, num)
push!(b.succs, block′)
continue
end
if isa(terminator, DetachNode)
block′ = block_for_inst(basic_block_index, terminator.label)
push!(blocks[block′].preds, num)
push!(b.succs, block′)

block′ = block_for_inst(basic_block_index, terminator.reattach)
push!(blocks[block′].preds, num)
push!(b.succs, block′)
continue
end
# Conditional Branch
if isa(terminator, GotoIfNot)
block′ = block_for_inst(basic_block_index, terminator.dest)
Expand Down Expand Up @@ -299,6 +316,9 @@ function getindex(x::UseRef)
elseif isa(stmt, GotoIfNot)
x.op == 1 || return OOBToken()
return stmt.cond
elseif isa(stmt, DetachNode) || isa(stmt, ReattachNode) || isa(stmt, SyncNode)
x.op == 1 || return OOBToken()
return stmt.syncregion
elseif isa(stmt, ReturnNode)
isdefined(stmt, :val) || return OOBToken()
x.op == 1 || return OOBToken()
Expand Down Expand Up @@ -330,6 +350,7 @@ function is_relevant_expr(e::Expr)
:foreigncall, :isdefined, :copyast,
:undefcheck, :throw_undef_if_not,
:cfunction, :method, :pop_exception,
:syncregion,
#=legacy IR format support=# :gotoifnot, :return)
end

Expand All @@ -352,6 +373,15 @@ function setindex!(x::UseRef, @nospecialize(v))
elseif isa(stmt, GotoIfNot)
x.op == 1 || throw(BoundsError())
x.stmt = GotoIfNot(v, stmt.dest)
elseif isa(stmt, DetachNode)
x.op == 1 || throw(BoundsError())
x.stmt = DetachNode(v, stmt.label, stmt.reattach)
elseif isa(stmt, ReattachNode)
x.op == 1 || throw(BoundsError())
x.stmt = ReattachNode(v, stmt.label)
elseif isa(stmt, SyncNode)
x.op == 1 || throw(BoundsError())
x.stmt = SyncNode(v)
elseif isa(stmt, ReturnNode)
x.op == 1 || throw(BoundsError())
x.stmt = typeof(stmt)(v)
Expand All @@ -378,7 +408,8 @@ end
function userefs(@nospecialize(x))
relevant = (isa(x, Expr) && is_relevant_expr(x)) ||
isa(x, GotoIfNot) || isa(x, ReturnNode) ||
isa(x, PiNode) || isa(x, PhiNode) || isa(x, PhiCNode) || isa(x, UpsilonNode)
isa(x, PiNode) || isa(x, PhiNode) || isa(x, PhiCNode) || isa(x, UpsilonNode) ||
isa(x, DetachNode) || isa(x, ReattachNode) || isa(x, SyncNode)
return UseRefIterator(x, relevant)
end

Expand Down Expand Up @@ -899,6 +930,17 @@ function process_node!(compact::IncrementalCompact, result::Vector{Any},
elseif isa(stmt, GlobalRef) || isa(stmt, GotoNode)
result[result_idx] = stmt
result_idx += 1
elseif isa(stmt, DetachNode) || isa(stmt, ReattachNode) || isa(stmt, SyncNode)
stmt = renumber_ssa2!(stmt, ssa_rename, used_ssas, late_fixup, result_idx, do_rename_ssa)
if compact.cfg_transforms_enabled
if isa(stmt, DetachNode)
stmt = DetachNode(stmt.syncregion, compact.bb_rename[stmt.label], compact.bb_rename[stmt.reattach])
elseif isa(stmt, ReattachNode)
stmt = ReattachNode(stmt.syncregion, compact.bb_rename[stmt.label])
end
end
result[result_idx] = stmt
result_idx += 1
elseif isa(stmt, GotoIfNot) && compact.cfg_transforms_enabled
stmt = renumber_ssa2!(stmt, ssa_rename, used_ssas, late_fixup, result_idx, do_rename_ssa)::GotoIfNot
result[result_idx] = stmt
Expand Down
10 changes: 10 additions & 0 deletions base/compiler/ssair/legacy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ function inflate_ir(ci::CodeInfo, sptypes::Vector{Any}, argtypes::Vector{Any})
# Translate statement edges to bb_edges
if isa(stmt, GotoNode)
code[i] = GotoNode(block_for_inst(cfg, stmt.label))
elseif isa(stmt, DetachNode)
code[i] = DetachNode(stmt.syncregion, block_for_inst(cfg, stmt.label),
block_for_inst(cfg, stmt.reattach))
elseif isa(stmt, ReattachNode)
code[i] = ReattachNode(stmt.syncregion, block_for_inst(cfg, stmt.label))
elseif isa(stmt, GotoIfNot)
code[i] = GotoIfNot(stmt.cond, block_for_inst(cfg, stmt.dest))
elseif isa(stmt, PhiNode)
Expand Down Expand Up @@ -77,6 +82,11 @@ function replace_code_newstyle!(ci::CodeInfo, ir::IRCode, nargs::Int)
stmt = urs[]
if isa(stmt, GotoNode)
ci.code[i] = GotoNode(first(ir.cfg.blocks[stmt.label].stmts))
elseif isa(stmt, DetachNode)
ci.code[i] = DetachNode(stmt.syncregion, first(ir.cfg.blocks[stmt.label].stmts),
first(ir.cfg.blocks[stmt.reattach].stmts))
elseif isa(stmt, ReattachNode)
ci.code[i] = ReattachNode(stmt.syncregion, first(ir.cfg.blocks[stmt.label].stmts))
elseif isa(stmt, GotoIfNot)
ci.code[i] = Expr(:gotoifnot, stmt.cond, first(ir.cfg.blocks[stmt.dest].stmts))
elseif isa(stmt, PhiNode)
Expand Down
3 changes: 3 additions & 0 deletions base/compiler/ssair/queries.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ function stmt_effect_free(@nospecialize(stmt), @nospecialize(rt), src, sptypes::
isa(stmt, ReturnNode) && return false
isa(stmt, GotoNode) && return false
isa(stmt, GotoIfNot) && return false
isa(stmt, DetachNode) && return false
isa(stmt, ReattachNode) && return false
isa(stmt, SyncNode) && return false
isa(stmt, Slot) && return false # Slots shouldn't occur in the IR at this point, but let's be defensive here
isa(stmt, GlobalRef) && return isdefined(stmt.mod, stmt.name)
if isa(stmt, Expr)
Expand Down
15 changes: 13 additions & 2 deletions base/compiler/ssair/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ function print_stmt(io::IO, idx::Int, @nospecialize(stmt), used::BitSet, maxleng
print(io, "\$(Expr(:enter, #", stmt.args[1]::Int, "))")
elseif stmt isa GotoNode
print(io, "goto #", stmt.label)
elseif stmt isa DetachNode
print(io, "detach within ", stmt.syncregion, ", #", stmt.label, ", #", stmt.reattach)
elseif stmt isa ReattachNode
print(io, "reattach within ", stmt.syncregion, ", #", stmt.label)
elseif stmt isa SyncNode
print(io, "sync within ", stmt.syncregion)
elseif stmt isa PhiNode
show_unquoted_phinode(io, stmt, indent, "#")
elseif stmt isa GotoIfNot
Expand Down Expand Up @@ -141,11 +147,12 @@ end

function should_print_ssa_type(@nospecialize node)
if isa(node, Expr)
return !(node.head in (:gc_preserve_begin, :gc_preserve_end, :meta, :return, :enter, :leave))
return !(node.head in (:gc_preserve_begin, :gc_preserve_end, :meta, :return, :enter, :leave, :syncregion))
end
return !isa(node, PiNode) && !isa(node, GotoIfNot) &&
!isa(node, GotoNode) && !isa(node, ReturnNode) &&
!isa(node, QuoteNode)
!isa(node, DetachNode) && !isa(node, ReattachNode) &&
!isa(node, SyncNode) && !isa(node, QuoteNode)
end

function default_expr_type_printer(io::IO, @nospecialize(typ), used::Bool)
Expand Down Expand Up @@ -727,6 +734,10 @@ function show_ir(io::IO, code::CodeInfo, line_info_preprinter=DILineInfoPrinter(
stmt = GotoIfNot(stmt.cond, block_for_inst(cfg, stmt.dest))
elseif stmt isa GotoNode
stmt = GotoNode(block_for_inst(cfg, stmt.label))
elseif isa(stmt, DetachNode)
stmt = DetachNode(stmt.syncregion, block_for_inst(cfg, stmt.label), block_for_inst(cfg, stmt.reattach))
elseif isa(stmt, ReattachNode)
stmt = ReattachNode(stmt.syncregion, block_for_inst(cfg, stmt.label))
elseif stmt isa PhiNode
e = stmt.edges
stmt = PhiNode(Any[block_for_inst(cfg, e[i]) for i in 1:length(e)], stmt.values)
Expand Down
27 changes: 24 additions & 3 deletions base/compiler/ssair/slot2ssa.jl
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,15 @@ function fixemup!(cond, rename, ir::IRCode, ci::CodeInfo, idx::Int, @nospecializ
end
return stmt
end
if isa(stmt, DetachNode)
return DetachNode(fixemup!(cond, rename, ir, ci, idx, stmt.syncregion), stmt.label, stmt.reattach)
end
if isa(stmt, ReattachNode)
return ReattachNode(fixemup!(cond, rename, ir, ci, idx, stmt.syncregion), stmt.label)
end
if isa(stmt, SyncNode)
return SyncNode(fixemup!(cond, rename, ir, ci, idx, stmt.syncregion))
end
if isexpr(stmt, :isdefined)
val = stmt.args[1]
if isa(val, Union{SlotNumber, TypedSlot})
Expand Down Expand Up @@ -197,7 +206,8 @@ function strip_trailing_junk!(ci::CodeInfo, code::Vector{Any}, flags::Vector{UIn
# If the last instruction is not a terminator, add one. This can
# happen for implicit return on dead branches.
term = code[end]
if !isa(term, GotoIfNot) && !isa(term, GotoNode) && !isa(term, ReturnNode)
if !isa(term, GotoIfNot) && !isa(term, GotoNode) && !isa(term, ReturnNode) &&
!isa(term, DetachNode) && !isa(term, ReattachNode) && !(isa, SyncNode)
push!(code, ReturnNode())
push!(ci.ssavaluetypes, Union{})
push!(ci.codelocs, 0)
Expand Down Expand Up @@ -385,12 +395,13 @@ function domsort_ssa!(ir::IRCode, domtree::DomTree)
cs = domtree.nodes[node].children
terminator = ir.stmts[last(ir.cfg.blocks[node].stmts)]
iscondbr = isa(terminator, GotoIfNot)
isspawnbr = isa(terminator, DetachNode) || isa(terminator, ReattachNode)
let old_node = node + 1
if length(cs) >= 1
# Adding the nodes in reverse sorted order attempts to retain
# the original source order of the nodes as much as possible.
# This is not required for correctness, but is easier on the humans
if old_node in cs
if !isspawnbr && old_node in cs
# Schedule the fall through node first,
# so we can retain the fall through
append!(stack, reverse(sort(filter(x -> (x != old_node), cs))))
Expand All @@ -406,7 +417,7 @@ function domsort_ssa!(ir::IRCode, domtree::DomTree)
node = pop!(stack)
end
end
if node != old_node && !isa(terminator, Union{GotoNode, ReturnNode})
if node != old_node && !isa(terminator, Union{GotoNode, ReturnNode, DetachNode, ReattachNode, SyncNode})
if isa(terminator, GotoIfNot)
# Need to break the critical edge
ncritbreaks += 1
Expand Down Expand Up @@ -466,6 +477,11 @@ function domsort_ssa!(ir::IRCode, domtree::DomTree)
else
result_stmts[inst_range[end]] = GotoNode(bb_rename[terminator.label])
end
elseif isa(terminator, DetachNode)
result_stmts[inst_range[end]] = DetachNode(terminator.syncregion, bb_rename[terminator.label],
bb_rename[terminator.reattach])
elseif isa(terminator, ReattachNode)
result_stmts[inst_range[end]] = ReattachNode(terminator.syncregion, bb_rename[terminator.label])
elseif isa(terminator, GotoIfNot)
# Check if we need to break the critical edge
if bb_rename[bb + 1] != new_bb + 1
Expand Down Expand Up @@ -793,6 +809,11 @@ function construct_ssa!(ci::CodeInfo, code::Vector{Any}, ir::IRCode, domtree::Do
# Convert GotoNode/GotoIfNot/PhiNode to BB addressing
if isa(stmt, GotoNode)
new_code[idx] = GotoNode(block_for_inst(cfg, stmt.label))
elseif isa(stmt, DetachNode)
new_code[idx] = DetachNode(stmt.syncregion, block_for_inst(cfg, stmt.label),
block_for_inst(cfg, stmt.reattach))
elseif isa(stmt, ReattachNode)
new_code[idx] = ReattachNode(stmt.syncregion, block_for_inst(cfg, stmt.label))
elseif isa(stmt, GotoIfNot)
new_dest = block_for_inst(cfg, stmt.dest)
if new_dest == bb+1
Expand Down
Loading