From cb5a5bcef970d70799cd0dff127fc09bf67ebf11 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 8 Sep 2021 18:55:41 -0400 Subject: [PATCH] inference: remove code that relies upon inferring the output type Recursing into inference may be unreliable during inference. --- base/compiler/ssair/inlining.jl | 2 +- base/compiler/ssair/passes.jl | 29 ++--------------------------- base/compiler/ssair/show.jl | 7 ++++--- base/compiler/ssair/slot2ssa.jl | 22 ++++++---------------- src/gf.c | 5 +++-- 5 files changed, 16 insertions(+), 49 deletions(-) diff --git a/base/compiler/ssair/inlining.jl b/base/compiler/ssair/inlining.jl index f67406dad9308..7c229a3b2081a 100644 --- a/base/compiler/ssair/inlining.jl +++ b/base/compiler/ssair/inlining.jl @@ -109,7 +109,7 @@ function inline_into_block!(state::CFGInliningState, block::Int) new_range = state.first_bb+1:block l = length(state.new_cfg_blocks) state.bb_rename[new_range] = (l+1:l+length(new_range)) - append!(state.new_cfg_blocks, map(copy, state.cfg.blocks[new_range])) + append!(state.new_cfg_blocks, (copy(block) for block in state.cfg.blocks[new_range])) push!(state.merged_orig_blocks, last(new_range)) end state.first_bb = block diff --git a/base/compiler/ssair/passes.jl b/base/compiler/ssair/passes.jl index 2d097b3d46b6f..23517ea3ed860 100644 --- a/base/compiler/ssair/passes.jl +++ b/base/compiler/ssair/passes.jl @@ -27,31 +27,6 @@ function try_compute_fieldidx_args(typ::DataType, args::Vector{Any}) return try_compute_fieldidx(typ, field) end -function lift_defuse(cfg::CFG, ssa::SSADefUse) - # We remove from `uses` any block where all uses are dominated - # by a def. This prevents insertion of dead phi nodes at the top - # of such a block if that block happens to be in a loop - ordered = Tuple{Int, Int, Bool}[(x, block_for_inst(cfg, x), true) for x in ssa.uses] - for x in ssa.defs - push!(ordered, (x, block_for_inst(cfg, x), false)) - end - ordered = sort(ordered, by=x->x[1]) - bb_defs = Int[] - bb_uses = Int[] - last_bb = last_def_bb = 0 - for (_, bb, is_use) in ordered - if bb != last_bb && is_use - push!(bb_uses, bb) - end - last_bb = bb - if last_def_bb != bb && !is_use - push!(bb_defs, bb) - last_def_bb = bb - end - end - SSADefUse(bb_uses, bb_defs, Int[]) -end - function find_curblock(domtree::DomTree, allblocks::Vector{Int}, curblock::Int) # TODO: This can be much faster by looking at current level and only # searching for those blocks in a sorted order @@ -1209,12 +1184,12 @@ function cfg_simplify!(ir::IRCode) # Compute (renamed) successors and predecessors given (renamed) block function compute_succs(i) orig_bb = follow_merged_succ(result_bbs[i]) - return map(i -> bb_rename_succ[i], bbs[orig_bb].succs) + return Int[bb_rename_succ[i] for i in bbs[orig_bb].succs] end function compute_preds(i) orig_bb = result_bbs[i] preds = bbs[orig_bb].preds - return map(pred -> bb_rename_pred[pred], preds) + return Int[bb_rename_pred[pred] for pred in preds] end BasicBlock[ diff --git a/base/compiler/ssair/show.jl b/base/compiler/ssair/show.jl index 4174267ec5a5e..013278ed001d5 100644 --- a/base/compiler/ssair/show.jl +++ b/base/compiler/ssair/show.jl @@ -79,14 +79,15 @@ show_unquoted(io::IO, val::Argument, indent::Int, prec::Int) = show_unquoted(io, show_unquoted(io::IO, stmt::PhiNode, indent::Int, ::Int) = show_unquoted_phinode(io, stmt, indent, "%") function show_unquoted_phinode(io::IO, stmt::PhiNode, indent::Int, prefix::String) - args = map(1:length(stmt.edges)) do i + args = String[let e = stmt.edges[i] v = !isassigned(stmt.values, i) ? "#undef" : sprint() do io′ show_unquoted(io′, stmt.values[i], indent) end - return "$prefix$e => $v" - end + "$prefix$e => $v" + end for i in 1:length(stmt.edges) + ] print(io, "φ ", '(') join(io, args, ", ") print(io, ')') diff --git a/base/compiler/ssair/slot2ssa.jl b/base/compiler/ssair/slot2ssa.jl index 2e3d1da1c168f..489c98c6549cc 100644 --- a/base/compiler/ssair/slot2ssa.jl +++ b/base/compiler/ssair/slot2ssa.jl @@ -33,16 +33,6 @@ function scan_entry!(result::Vector{SlotInfo}, idx::Int, @nospecialize(stmt)) end -function lift_defuse(cfg::CFG, defuse) - map(defuse) do slot - SlotInfo( - Int[block_for_inst(cfg, x) for x in slot.defs], - Int[block_for_inst(cfg, x) for x in slot.uses], - slot.any_newvar - ) - end -end - function scan_slot_def_use(nargs::Int, ci::CodeInfo, code::Vector{Any}) nslots = length(ci.slotflags) result = SlotInfo[SlotInfo() for i = 1:nslots] @@ -524,7 +514,7 @@ function domsort_ssa!(ir::IRCode, domtree::DomTree) return new_ir end -function compute_live_ins(cfg::CFG, defuse) +function compute_live_ins(cfg::CFG, defuse #=::Union{SlotInfo,SSADefUse}=#) # We remove from `uses` any block where all uses are dominated # by a def. This prevents insertion of dead phi nodes at the top # of such a block if that block happens to be in a loop @@ -586,8 +576,8 @@ function recompute_type(node::Union{PhiNode, PhiCNode}, ci::CodeInfo, ir::IRCode return new_typ end -function construct_ssa!(ci::CodeInfo, ir::IRCode, domtree::DomTree, defuse, - slottypes::Vector{Any}) +function construct_ssa!(ci::CodeInfo, ir::IRCode, domtree::DomTree, + defuses::Vector{SlotInfo}, slottypes::Vector{Any}) code = ir.stmts.inst cfg = ir.cfg left = Int[] @@ -616,7 +606,7 @@ function construct_ssa!(ci::CodeInfo, ir::IRCode, domtree::DomTree, defuse, for (_, exc) in catch_entry_blocks phicnodes[exc] = Vector{Tuple{SlotNumber, NewSSAValue, PhiCNode}}() end - @timeit "idf" for (idx, slot) in Iterators.enumerate(defuse) + @timeit "idf" for (idx, slot) in Iterators.enumerate(defuses) # No uses => no need for phi nodes isempty(slot.uses) && continue # TODO: Restore this optimization @@ -671,9 +661,9 @@ function construct_ssa!(ci::CodeInfo, ir::IRCode, domtree::DomTree, defuse, end # Perform SSA renaming initial_incoming_vals = Any[ - if 0 in defuse[x].defs + if 0 in defuses[x].defs Argument(x) - elseif !defuse[x].any_newvar + elseif !defuses[x].any_newvar undef_token else SSAValue(-2) diff --git a/src/gf.c b/src/gf.c index d6c9741f3ebf3..d9012d96a6b2a 100644 --- a/src/gf.c +++ b/src/gf.c @@ -493,14 +493,15 @@ static void reset_mt_caches(jl_methtable_t *mt, void *env) jl_function_t *jl_typeinf_func = NULL; -size_t jl_typeinf_world = 0; +size_t jl_typeinf_world = 1; JL_DLLEXPORT void jl_set_typeinf_func(jl_value_t *f) { + size_t newfunc = jl_typeinf_world == 1 && jl_typeinf_func == NULL; jl_typeinf_func = (jl_function_t*)f; jl_typeinf_world = jl_get_tls_world_age(); ++jl_world_counter; // make type-inference the only thing in this world - if (jl_typeinf_world == 0) { + if (0 && newfunc) { // give type inference a chance to see all of these // TODO: also reinfer if max_world != ~(size_t)0 jl_array_t *unspec = jl_alloc_vec_any(0);