From a50ba6f4af19217f393e6a40dbca98e2aefe8f3e Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 10 Apr 2018 01:18:28 -0400 Subject: [PATCH 1/2] [NewOptimizer] support line number emission from new IR format However, there seems to be a bug in the new-IR inliner, where it is failing to correctly unique the linetable contents, which wastes memory and may lead to mistakes here. --- base/compiler/optimize.jl | 2 +- base/compiler/ssair/driver.jl | 2 +- base/compiler/ssair/inlining2.jl | 5 +- base/compiler/ssair/ir.jl | 3 +- base/compiler/ssair/verify.jl | 17 ++ src/ccall.cpp | 4 +- src/codegen.cpp | 358 +++++++++++++++++++------------ 7 files changed, 248 insertions(+), 143 deletions(-) diff --git a/base/compiler/optimize.jl b/base/compiler/optimize.jl index 3985c434773d9..e7f153fc9196a 100644 --- a/base/compiler/optimize.jl +++ b/base/compiler/optimize.jl @@ -283,7 +283,7 @@ function optimize(me::InferenceState) reindex_labels!(opt) nargs = Int(opt.nargs) - 1 if def isa Method - topline = LineInfoNode(opt.mod, def.name, def.file, Int(def.line), Int(0)) + topline = LineInfoNode(opt.mod, def.name, def.file, Int(def.line), 0) else topline = LineInfoNode(opt.mod, NullLineInfo.method, NullLineInfo.file, 0, 0) end diff --git a/base/compiler/ssair/driver.jl b/base/compiler/ssair/driver.jl index 08abce3a32780..1c87653818acc 100644 --- a/base/compiler/ssair/driver.jl +++ b/base/compiler/ssair/driver.jl @@ -151,6 +151,6 @@ function run_passes(ci::CodeInfo, nargs::Int, linetable::Vector{LineInfoNode}, s @timeit "compact 2" ir = compact!(ir) @timeit "type lift" ir = type_lift_pass!(ir) @timeit "compact 3" ir = compact!(ir) - #@timeit "verify 3" verify_ir(ir) + #@timeit "verify 3" (verify_ir(ir); verify_linetable(linetable)) return ir end diff --git a/base/compiler/ssair/inlining2.jl b/base/compiler/ssair/inlining2.jl index c04d361a63582..28fab91f32291 100644 --- a/base/compiler/ssair/inlining2.jl +++ b/base/compiler/ssair/inlining2.jl @@ -151,8 +151,9 @@ function batch_inline!(todo, ir, domtree, linetable, sv) inline_cfg = inline_ir.cfg linetable_offset = length(linetable) # Append the linetable of the inlined function to our line table + inlined_at = compact.result_lines[idx] for entry in inline_linetable - push!(linetable, LineInfoNode(entry.mod, entry.method, entry.file, entry.line, compact.result_lines[idx])) + push!(linetable, LineInfoNode(entry.mod, entry.method, entry.file, entry.line, (entry.inlined_at > 0 ? entry.inlined_at + linetable_offset : inlined_at))) end # If the iterator already moved on to the next basic block, # temorarily re-open in again. @@ -261,6 +262,7 @@ function batch_inline!(todo, ir, domtree, linetable, sv) end ir = finish(compact) + return ir end function spec_lambda(@nospecialize(atype), sv::OptimizationState, @nospecialize(invoke_data)) @@ -313,6 +315,7 @@ function maybe_make_invoke!(ir, idx, @nospecialize(etype), atypes::Vector{Any}, ex.typ = etype ex.args = argexprs ir[SSAValue(idx)] = ex + nothing end function exprtype_func(@nospecialize(arg1), ir) diff --git a/base/compiler/ssair/ir.jl b/base/compiler/ssair/ir.jl index 976a0c2d6fcc1..d64f34d31dda4 100644 --- a/base/compiler/ssair/ir.jl +++ b/base/compiler/ssair/ir.jl @@ -368,7 +368,7 @@ mutable struct IncrementalCompact new_len = length(code.stmts) + length(code.new_nodes) result = Array{Any}(undef, new_len) result_types = Array{Any}(undef, new_len) - result_lines = Array{Int}(undef, new_len) + result_lines = fill(0, new_len) used_ssas = fill(0, new_len) ssa_rename = Any[SSAValue(i) for i = 1:new_len] late_fixup = Vector{Int}() @@ -546,6 +546,7 @@ function resize!(compact::IncrementalCompact, nnewnodes) resize!(compact.result_lines, nnewnodes) resize!(compact.used_ssas, nnewnodes) compact.used_ssas[(old_length+1):nnewnodes] = 0 + nothing end function finish_current_bb!(compact, old_result_idx=compact.result_idx) diff --git a/base/compiler/ssair/verify.jl b/base/compiler/ssair/verify.jl index 3fd5674313280..bd8d37e19bedf 100644 --- a/base/compiler/ssair/verify.jl +++ b/base/compiler/ssair/verify.jl @@ -70,6 +70,7 @@ function verify_ir(ir::IRCode) # Verify statements domtree = construct_domtree(ir.cfg) for (bb, idx, stmt) in bbidxstmt(ir) + stmt === nothing && continue if isa(stmt, PhiNode) @assert length(stmt.edges) == length(stmt.values) for i = 1:length(stmt.edges) @@ -110,6 +111,13 @@ function verify_ir(ir::IRCode) end end else + if isa(stmt, Expr) || isa(stmt, ReturnNode) # TODO: make sure everything has line info + if !(stmt isa ReturnNode && !isdefined(stmt, :val)) # not actually a return node, but an unreachable marker + if ir.lines[idx] <= 0 + @verify_error "Missing line number information for statement $idx of $ir" + end + end + end for op in userefs(stmt) op = op[] check_op(ir, domtree, op, bb, idx) @@ -117,3 +125,12 @@ function verify_ir(ir::IRCode) end end end + +function verify_linetable(linetable::Vector{LineInfoNode}) + for i in 1:length(linetable) + line = linetable[i] + if i <= line.inlined_at + @verify_error "Misordered linetable" + end + end +end diff --git a/src/ccall.cpp b/src/ccall.cpp index f075e8a4d8f6b..1d274186e74f8 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -1126,8 +1126,10 @@ static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nar } CallInst *inst = ctx.builder.CreateCall(f, ArrayRef(&argvals[0], nargt)); - if (isString) + if (isString) { f->addFnAttr(Attribute::AlwaysInline); + inst->setAttributes(f->getAttributes()); + } JL_GC_POP(); diff --git a/src/codegen.cpp b/src/codegen.cpp index d38844ef68cbc..c3c6477d26520 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5887,6 +5887,7 @@ static std::unique_ptr emit_function( } // step 10. allocate rest argument + CallInst *restTuple = NULL; if (va && ctx.vaSlot != -1) { jl_varinfo_t &vi = ctx.slots[ctx.vaSlot]; if (vi.value.constant || !vi.used) { @@ -5907,7 +5908,7 @@ static std::unique_ptr emit_function( } else { // restarg = jl_f_tuple(NULL, &args[nreq], nargs - nreq) - CallInst *restTuple = + restTuple = ctx.builder.CreateCall(prepare_call(jltuple_func), { maybe_decay_untracked(V_null), ctx.builder.CreateGEP(argArray, @@ -5926,13 +5927,6 @@ static std::unique_ptr emit_function( return (!jl_is_submodule(mod, jl_base_module) && !jl_is_submodule(mod, jl_core_module)); }; - struct DbgState { - DebugLoc loc; - DISubprogram *sp; - StringRef file; - ssize_t line; - bool in_user_code; - }; struct StmtProp { DebugLoc loc; StringRef file; @@ -5942,118 +5936,192 @@ static std::unique_ptr emit_function( bool in_user_code; }; std::vector stmtprops(stmtslen); - std::vector DI_stack; - StmtProp cur_prop{topdebugloc, filename, toplineno, - true, false, false}; - ctx.line = &cur_prop.line; - if (coverage_mode != JL_LOG_NONE || malloc_log_mode) { - cur_prop.in_user_code = (!jl_is_submodule(ctx.module, jl_base_module) && - !jl_is_submodule(ctx.module, jl_core_module)); - } - for (i = 0; i < stmtslen; i++) { - cur_prop.loc_changed = false; - cur_prop.is_poploc = false; - jl_value_t *stmt = jl_array_ptr_ref(stmts, i); - jl_expr_t *expr = jl_is_expr(stmt) ? (jl_expr_t*)stmt : nullptr; -#ifndef JL_NDEBUG - if (jl_is_labelnode(stmt)) { - size_t lname = jl_labelnode_label(stmt); - if (lname != i + 1) { - jl_safe_printf("Label number mismatch.\n"); - jl_(stmts); - abort(); + if (ctx.new_style_ir) { + std::vector linetable; + size_t nlocs = jl_array_len(src->linetable); + if (ctx.debug_enabled) { + std::map, DISubprogram*> subprograms; + linetable.resize(nlocs + 1); + linetable[0] = noDbg; + for (size_t i = 0; i < nlocs; i++) { + // LineInfoNode(mod::Module, method::Symbol, file::Symbol, line::Int, inlined_at::Int) + jl_value_t *locinfo = jl_array_ptr_ref(src->linetable, i); + jl_sym_t *method = (jl_sym_t*)jl_fieldref_noalloc(locinfo, 1); + jl_sym_t *file = (jl_sym_t*)jl_fieldref_noalloc(locinfo, 2); + int line = jl_unbox_long(jl_fieldref(locinfo, 3)); + int inlined_at = jl_unbox_long(jl_fieldref(locinfo, 4)); + assert((size_t)inlined_at <= i); + StringRef filename = jl_symbol_name(file); + if (filename.empty()) + filename = ""; + StringRef fname = jl_symbol_name(method); + if (fname.empty()) + fname = "macro expansion"; + if (inlined_at == 0 && filename == ctx.file) { // if everything matches, emit a toplevel line number + linetable[i + 1] = DebugLoc::get(line, 0, SP, NULL); + } + else { // otherwise, describe this as an inlining frame + DISubprogram *&inl_SP = subprograms[std::make_tuple(fname, filename)]; + if (inl_SP == NULL) { + DIFile *difile = dbuilder.createFile(filename, "."); + inl_SP = dbuilder.createFunction( + difile, std::string(fname) + ";", + fname, difile, 0, jl_di_func_null_sig, + false, true, 0, DIFlagZero, true, nullptr); + } + DebugLoc inl_loc = (inlined_at == 0) ? DebugLoc::get(0, 0, SP, NULL) : linetable.at(inlined_at); + linetable[i + 1] = DebugLoc::get(line, 0, inl_SP, inl_loc); + } } } + size_t prev_loc = 0; + for (i = 0; i < stmtslen; i++) { + size_t loc = ((size_t*)jl_array_data(src->codelocs))[i]; + StmtProp &cur_prop = stmtprops[i]; + cur_prop.is_poploc = false; + if (loc > 0) { + jl_value_t *locinfo = jl_array_ptr_ref(src->linetable, loc - 1); + jl_module_t *module = (jl_module_t*)jl_fieldref_noalloc(locinfo, 0); + if (ctx.debug_enabled) + cur_prop.loc = linetable.at(loc); + else + cur_prop.loc = noDbg; + cur_prop.file = jl_symbol_name((jl_sym_t*)jl_fieldref_noalloc(locinfo, 2)); + cur_prop.line = jl_unbox_long(jl_fieldref(locinfo, 3)); + cur_prop.loc_changed = (loc != prev_loc); // for code-coverage + cur_prop.in_user_code = in_user_mod(module); + prev_loc = loc; + } + else { + cur_prop.loc = noDbg; + cur_prop.file = ""; + cur_prop.line = -1; + cur_prop.loc_changed = false; + cur_prop.in_user_code = false; + } + } + } + else { + struct DbgState { + DebugLoc loc; + DISubprogram *sp; + StringRef file; + ssize_t line; + bool in_user_code; + }; + std::vector legacy_DI_stack; + StmtProp cur_prop{topdebugloc, filename, toplineno, + true, false, false}; + ctx.line = &cur_prop.line; + if (coverage_mode != JL_LOG_NONE || malloc_log_mode) + cur_prop.in_user_code = in_user_mod(ctx.module); + for (i = 0; i < stmtslen; i++) { + cur_prop.loc_changed = false; + cur_prop.is_poploc = false; + jl_value_t *stmt = jl_array_ptr_ref(stmts, i); + jl_expr_t *expr = jl_is_expr(stmt) ? (jl_expr_t*)stmt : nullptr; +#ifndef JL_NDEBUG + if (jl_is_labelnode(stmt)) { + size_t lname = jl_labelnode_label(stmt); + if (lname != i + 1) { + jl_safe_printf("Label number mismatch.\n"); + jl_(stmts); + abort(); + } + } #endif - if (jl_is_linenode(stmt)) { - ssize_t lno = -1; - lno = jl_linenode_line(stmt); - MDNode *inlinedAt = NULL; - if (DI_stack.size() > 0) { - inlinedAt = DI_stack.back().loc; - } - if (ctx.debug_enabled) - cur_prop.loc = DebugLoc::get(lno, 0, SP, inlinedAt); - cur_prop.line = lno; - cur_prop.loc_changed = true; - } - else if (expr && expr->head == meta_sym && - jl_array_len(expr->args) >= 1) { - jl_value_t *meta_arg = jl_exprarg(expr, 0); - if (meta_arg == (jl_value_t*)jl_symbol("push_loc")) { - const char *new_filename = ""; - assert(jl_array_len(expr->args) > 1); - jl_sym_t *filesym = (jl_sym_t*)jl_exprarg(expr, 1); - if (filesym != empty_sym) - new_filename = jl_symbol_name(filesym); - DIFile *new_file = nullptr; + if (jl_is_linenode(stmt)) { + ssize_t lno = -1; + lno = jl_linenode_line(stmt); + MDNode *inlinedAt = NULL; + if (legacy_DI_stack.size() > 0) { + inlinedAt = legacy_DI_stack.back().loc; + } if (ctx.debug_enabled) - new_file = dbuilder.createFile(new_filename, "."); - DI_stack.push_back(DbgState{cur_prop.loc, SP, - cur_prop.file, cur_prop.line, - cur_prop.in_user_code}); - const char *inl_name = ""; - int inlined_func_lineno = 0; - if (jl_array_len(expr->args) > 2) { - for (size_t ii = 2; ii < jl_array_len(expr->args); ii++) { - jl_value_t *arg = jl_exprarg(expr, ii); - if (jl_is_symbol(arg)) - inl_name = jl_symbol_name((jl_sym_t*)arg); - else if (jl_is_int32(arg)) - inlined_func_lineno = jl_unbox_int32(arg); - else if (jl_is_int64(arg)) - inlined_func_lineno = jl_unbox_int64(arg); - else if (jl_is_module(arg)) { - jl_module_t *mod = (jl_module_t*)arg; - cur_prop.in_user_code = in_user_mod(mod); + cur_prop.loc = DebugLoc::get(lno, 0, SP, inlinedAt); + cur_prop.line = lno; + cur_prop.loc_changed = true; + } + else if (expr && expr->head == meta_sym && + jl_array_len(expr->args) >= 1) { + jl_value_t *meta_arg = jl_exprarg(expr, 0); + if (meta_arg == (jl_value_t*)jl_symbol("push_loc")) { + const char *new_filename = ""; + assert(jl_array_len(expr->args) > 1); + jl_sym_t *filesym = (jl_sym_t*)jl_exprarg(expr, 1); + if (filesym != empty_sym) + new_filename = jl_symbol_name(filesym); + DIFile *new_file = nullptr; + if (ctx.debug_enabled) + new_file = dbuilder.createFile(new_filename, "."); + legacy_DI_stack.push_back(DbgState{cur_prop.loc, SP, + cur_prop.file, cur_prop.line, + cur_prop.in_user_code}); + const char *inl_name = ""; + int inlined_func_lineno = 0; + if (jl_array_len(expr->args) > 2) { + for (size_t ii = 2; ii < jl_array_len(expr->args); ii++) { + jl_value_t *arg = jl_exprarg(expr, ii); + if (jl_is_symbol(arg)) + inl_name = jl_symbol_name((jl_sym_t*)arg); + else if (jl_is_int32(arg)) + inlined_func_lineno = jl_unbox_int32(arg); + else if (jl_is_int64(arg)) + inlined_func_lineno = jl_unbox_int64(arg); + else if (jl_is_module(arg)) { + jl_module_t *mod = (jl_module_t*)arg; + cur_prop.in_user_code = in_user_mod(mod); + } } } + else { + inl_name = "macro expansion"; + } + if (ctx.debug_enabled) { + SP = dbuilder.createFunction(new_file, + std::string(inl_name) + ";", + inl_name, + new_file, + inlined_func_lineno, + jl_di_func_null_sig, + false, + true, + inlined_func_lineno, + DIFlagZero, + true, + nullptr); + MDNode *inlinedAt = NULL; + inlinedAt = cur_prop.loc; + cur_prop.loc = DebugLoc::get(inlined_func_lineno, + 0, SP, inlinedAt); + } + cur_prop.file = new_filename; + cur_prop.line = inlined_func_lineno; + cur_prop.loc_changed = true; } - else { - inl_name = "macro expansion"; - } - if (ctx.debug_enabled) { - SP = dbuilder.createFunction(new_file, - std::string(inl_name) + ";", - inl_name, - new_file, - inlined_func_lineno, - jl_di_func_null_sig, - false, - true, - inlined_func_lineno, - DIFlagZero, - true, - nullptr); - MDNode *inlinedAt = NULL; - inlinedAt = cur_prop.loc; - cur_prop.loc = DebugLoc::get(inlined_func_lineno, - 0, SP, inlinedAt); + else if (meta_arg == (jl_value_t*)jl_symbol("pop_loc")) { + unsigned npops = 1; + if (jl_expr_nargs(expr) > 1) + npops = jl_unbox_long(jl_exprarg(expr, 1)); + for (unsigned i = 1; i < npops; i++) + legacy_DI_stack.pop_back(); + cur_prop.is_poploc = true; + auto &DI = legacy_DI_stack.back(); + SP = DI.sp; + cur_prop.loc = DI.loc; + cur_prop.file = DI.file; + cur_prop.line = DI.line; + cur_prop.in_user_code = DI.in_user_code; + cur_prop.loc_changed = true; + legacy_DI_stack.pop_back(); } - cur_prop.file = new_filename; - cur_prop.line = inlined_func_lineno; - cur_prop.loc_changed = true; - } - else if (meta_arg == (jl_value_t*)jl_symbol("pop_loc")) { - unsigned npops = 1; - if (jl_expr_nargs(expr) > 1) - npops = jl_unbox_long(jl_exprarg(expr, 1)); - for (unsigned i = 1; i < npops; i++) - DI_stack.pop_back(); - cur_prop.is_poploc = true; - auto &DI = DI_stack.back(); - SP = DI.sp; - cur_prop.loc = DI.loc; - cur_prop.file = DI.file; - cur_prop.line = DI.line; - cur_prop.in_user_code = DI.in_user_code; - cur_prop.loc_changed = true; - DI_stack.pop_back(); } + stmtprops[i] = cur_prop; } - stmtprops[i] = cur_prop; + legacy_DI_stack.clear(); } - DI_stack.clear(); + Instruction &prologue_end = ctx.builder.GetInsertBlock()->back(); + // step 12. Do codegen in control flow order std::vector> workstack; @@ -6061,7 +6129,6 @@ static std::unique_ptr emit_function( // Whether we are doing codegen in statement order. // We need to update debug location if this is false even if // `loc_changed` is false. - bool linear_codegen = true; auto find_next_stmt = [&] (int seq_next) { // new style ir is always in dominance order if (ctx.new_style_ir) { @@ -6075,7 +6142,6 @@ static std::unique_ptr emit_function( // i.e. if it exists, it's the next one following control flow and // should be emitted into the current insert point. if (seq_next >= 0 && (unsigned)seq_next < stmtslen) { - linear_codegen = (seq_next - cursor) == 1; cursor = seq_next; return; } @@ -6083,12 +6149,10 @@ static std::unique_ptr emit_function( ctx.builder.CreateUnreachable(); if (workstack.empty()) { cursor = -1; - linear_codegen = false; return; } auto &item = workstack.back(); ctx.builder.SetInsertPoint(item.second); - linear_codegen = (item.first - cursor) == 1; cursor = item.first; workstack.pop_back(); }; @@ -6191,34 +6255,34 @@ static std::unique_ptr emit_function( } } - // Handle the implicit first line number node. - if (ctx.debug_enabled) - ctx.builder.SetCurrentDebugLocation(topdebugloc); if (coverage_mode != JL_LOG_NONE && do_coverage(in_user_mod(ctx.module))) coverageVisitLine(ctx, filename, toplineno); while (cursor != -1) { auto &props = stmtprops[cursor]; - if ((props.loc_changed || !linear_codegen) && ctx.debug_enabled) + if (ctx.debug_enabled) ctx.builder.SetCurrentDebugLocation(props.loc); - // Disable coverage for pop_loc, it doesn't start a new expression - if (props.loc_changed && do_coverage(props.in_user_code) && - !props.is_poploc) { - coverageVisitLine(ctx, props.file, props.line); - } jl_value_t *stmt = jl_array_ptr_ref(stmts, cursor); jl_expr_t *expr = jl_is_expr(stmt) ? (jl_expr_t*)stmt : nullptr; - if (ctx.new_style_ir && branch_targets.count(cursor+1)) { - come_from_bb[cursor] = ctx.builder.GetInsertBlock(); - BasicBlock *NewBB = BB[cursor+1]; - if (!ctx.builder.GetInsertBlock()->getTerminator()) - ctx.builder.CreateBr(NewBB); - ctx.builder.SetInsertPoint(NewBB); - } - if (jl_is_labelnode(stmt)) { - // Label node - int lname = jl_labelnode_label(stmt); - handle_label(lname, true); - continue; + if (ctx.new_style_ir) { + if (branch_targets.count(cursor + 1)) { + come_from_bb[cursor] = ctx.builder.GetInsertBlock(); + BasicBlock *NewBB = BB[cursor + 1]; + if (!ctx.builder.GetInsertBlock()->getTerminator()) + ctx.builder.CreateBr(NewBB); + ctx.builder.SetInsertPoint(NewBB); + } + } + else { + if (jl_is_labelnode(stmt)) { + // Label node + int lname = jl_labelnode_label(stmt); + handle_label(lname, true); + continue; + } + } + // Legacy IR: disables coverage for pop_loc since it doesn't start a new expression + if (props.loc_changed && do_coverage(props.in_user_code) && !props.is_poploc) { + coverageVisitLine(ctx, props.file, props.line); } if (expr && expr->head == unreachable_sym) { ctx.builder.CreateUnreachable(); @@ -6331,7 +6395,8 @@ static std::unique_ptr emit_function( handle_label(lname, true); } continue; - } else if (jl_is_upsilonnode(stmt)) { + } + if (jl_is_upsilonnode(stmt)) { jl_value_t *val = jl_fieldref_noalloc(stmt, 0); // If the val is null, we can ignore the store. // The middle end guarantees that the value from this @@ -6360,7 +6425,7 @@ static std::unique_ptr emit_function( } else { bool next_is_label = jl_is_labelnode(jl_array_ptr_ref(stmts, cursor+1)); BasicBlock *ifnot = handle_label(lname, false); - BasicBlock *ifso = (next_is_label || ctx.new_style_ir) ? handle_label(cursor+2, false) : BasicBlock::Create(jl_LLVMContext, "if", f); + BasicBlock *ifso = (next_is_label ? handle_label(cursor + 2, false) : BasicBlock::Create(jl_LLVMContext, "if", f)); // Any branches treated as constant in type inference should be // eliminated before running ctx.builder.CreateCondBr(isfalse, ifnot, ifso); @@ -6690,6 +6755,23 @@ static std::unique_ptr emit_function( // step 13. Perform any delayed instantiations if (ctx.debug_enabled) { + bool in_prologue = true; + for (auto &BB : *ctx.f) { + for (auto &I : BB) { + CallSite call(&I); + if (call && !I.getDebugLoc()) { + // LLVM Verifier: inlinable function call in a function with debug info must have a !dbg location + // make sure that anything we attempt to call has some inlining info, just in case optimization messed up + // (except if we know that it is an intrinsic used in our prologue, which should never have its own debug subprogram) + Function *F = call.getCalledFunction(); + if (!in_prologue || !F || !(F->isIntrinsic() || F->getName().startswith("julia.") || &I == restTuple)) { + I.setDebugLoc(topdebugloc); + } + } + if (&I == &prologue_end) + in_prologue = false; + } + } dbuilder.finalize(); } @@ -6725,8 +6807,8 @@ static std::unique_ptr emit_function( if (use) use->eraseFromParent(); root->eraseFromParent(); - if (store_value) - store_value->eraseFromParent(); + assert(!store_value || store_value == restTuple); + restTuple->eraseFromParent(); } } } From 77b65d5d16fab1f91c5c8a80f9b3ca25e2fc2989 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 11 Apr 2018 12:13:53 -0400 Subject: [PATCH 2/2] [NewOptimizer] handle new IR nodes correctly in binary format --- src/common_symbols1.inc | 3 - src/common_symbols2.inc | 6 +- src/dump.c | 145 ++++++++++++++++++++++++++++++++++------ src/init.c | 1 + src/jltypes.c | 1 + src/julia.h | 1 + src/timing.c | 1 + 7 files changed, 131 insertions(+), 27 deletions(-) diff --git a/src/common_symbols1.inc b/src/common_symbols1.inc index cf50924dd4f5f..daa9589663b28 100644 --- a/src/common_symbols1.inc +++ b/src/common_symbols1.inc @@ -97,6 +97,3 @@ jl_symbol("count"), jl_symbol("typeof"), jl_symbol("|"), jl_symbol("Int64"), -jl_symbol("sext_int"), -jl_symbol("rem"), -jl_symbol("_expr"), diff --git a/src/common_symbols2.inc b/src/common_symbols2.inc index 85ed06ca73425..a71c1b0d57958 100644 --- a/src/common_symbols2.inc +++ b/src/common_symbols2.inc @@ -247,6 +247,6 @@ jl_symbol("_collect"), jl_symbol("bswap"), jl_symbol("bswap_int"), jl_symbol("Generator"), -jl_symbol("toUInt32"), -jl_symbol("s"), -jl_symbol("linfo"), +jl_symbol("sext_int"), +jl_symbol("rem"), +jl_symbol("_expr"), diff --git a/src/dump.c b/src/dump.c index 75008fa808856..a68163e6fb6fe 100644 --- a/src/dump.c +++ b/src/dump.c @@ -73,17 +73,20 @@ extern jl_array_t *jl_module_init_order; static const intptr_t LongSymbol_tag = 23; static const intptr_t LongSvec_tag = 24; static const intptr_t LongExpr_tag = 25; -static const intptr_t LiteralVal_tag = 26; -static const intptr_t SmallInt64_tag = 27; -static const intptr_t SmallDataType_tag= 28; -static const intptr_t Int32_tag = 29; -static const intptr_t Array1d_tag = 30; -static const intptr_t Singleton_tag = 31; -static const intptr_t CommonSym_tag = 32; -static const intptr_t NearbyGlobal_tag = 33; // a GlobalRef pointing to tree_enclosing_module -static const intptr_t CoreMod_tag = 34; -static const intptr_t BaseMod_tag = 35; -static const intptr_t BITypeName_tag = 36; // builtin TypeName +static const intptr_t LongPhi_tag = 26; +static const intptr_t LongPhic_tag = 27; +static const intptr_t LiteralVal_tag = 28; +static const intptr_t SmallInt64_tag = 29; +static const intptr_t SmallDataType_tag= 30; +static const intptr_t Int32_tag = 31; +static const intptr_t Array1d_tag = 32; +static const intptr_t Singleton_tag = 33; +static const intptr_t CommonSym_tag = 34; +static const intptr_t NearbyGlobal_tag = 35; // a GlobalRef pointing to tree_enclosing_module +static const intptr_t CoreMod_tag = 36; +static const intptr_t BaseMod_tag = 37; +static const intptr_t BITypeName_tag = 38; // builtin TypeName +static const intptr_t LineInfoNodeType_tag = 39; // placeholder for Core.LineInfoNode static const intptr_t Null_tag = 253; static const intptr_t ShortBackRef_tag = 254; static const intptr_t BackRef_tag = 255; @@ -442,7 +445,9 @@ static int is_ast_node(jl_value_t *v) jl_is_svec(v) || jl_is_tuple(v) || ((jl_datatype_t*)jl_typeof(v))->instance || jl_is_int32(v) || jl_is_int64(v) || jl_is_bool(v) || jl_is_quotenode(v) || jl_is_gotonode(v) || - jl_is_labelnode(v) || jl_is_linenode(v) || jl_is_globalref(v); + jl_is_labelnode(v) || jl_is_linenode(v) || jl_is_globalref(v) || + jl_is_phinode(v) || jl_is_phicnode(v) || jl_is_upsilonnode(v) || jl_is_pinode(v) || + (jl_lineinfonode_type && jl_typeis(v, jl_lineinfonode_type)); } static int literal_val_id(jl_serializer_state *s, jl_value_t *v) @@ -487,6 +492,10 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li writetag(s->s, (jl_value_t*)BaseMod_tag); return; } + else if (v == (jl_value_t*)jl_lineinfonode_type) { + writetag(s->s, (jl_value_t*)LineInfoNodeType_tag); + return; + } else if (!as_literal && !is_ast_node(v)) { writetag(s->s, (jl_value_t*)LiteralVal_tag); int id = literal_val_id(s, v); @@ -547,7 +556,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li writetag(s->s, (jl_value_t*)LongSvec_tag); write_int32(s->s, l); } - for(i=0; i < l; i++) { + for (i = 0; i < l; i++) { jl_serialize_value(s, jl_svecref(v, i)); } } @@ -585,7 +594,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li writetag(s->s, (jl_value_t*)jl_ssavalue_type); write_uint16(s->s, ((jl_ssavalue_t*)v)->id); } - else if (jl_typeis(v,jl_slotnumber_type) && jl_slot_number(v) < 65536) { + else if (jl_typeis(v, jl_slotnumber_type) && jl_slot_number(v) < 65536) { writetag(s->s, (jl_value_t*)jl_slotnumber_type); write_uint16(s->s, jl_slot_number(v)); } @@ -600,7 +609,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li write_uint16(s->s, ar->flags.ndims); write_uint16(s->s, (ar->flags.ptrarray<<15) | (ar->elsize & 0x7fff)); } - for (i=0; i < ar->flags.ndims; i++) + for (i = 0; i < ar->flags.ndims; i++) jl_serialize_value(s, jl_box_long(jl_array_dim(ar,i))); jl_serialize_value(s, jl_typeof(ar)); if (!ar->flags.ptrarray) { @@ -609,7 +618,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li ios_write(s->s, (char*)jl_array_data(ar), tot); } else { - for(i=0; i < jl_array_len(ar); i++) { + for (i = 0; i < jl_array_len(ar); i++) { jl_serialize_value(s, jl_array_ptr_ref(v, i)); } } @@ -631,6 +640,42 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li jl_serialize_value(s, jl_exprarg(e, i)); } } + else if (jl_is_phinode(v)) { + jl_array_t *edges = (jl_array_t*)jl_fieldref_noalloc(v, 0); + jl_array_t *values = (jl_array_t*)jl_fieldref_noalloc(v, 1); + size_t l = jl_array_len(edges); + if (l <= 255 && jl_array_len(values) == l) { + writetag(s->s, jl_phinode_type); + write_uint8(s->s, (uint8_t)l); + } + else { + writetag(s->s, (jl_value_t*)LongPhi_tag); + write_int32(s->s, l); + write_int32(s->s, jl_array_len(values)); + } + for (i = 0; i < l; i++) { + jl_serialize_value(s, jl_array_ptr_ref(edges, i)); + } + l = jl_array_len(values); + for (i = 0; i < l; i++) { + jl_serialize_value(s, jl_array_ptr_ref(values, i)); + } + } + else if (jl_is_phicnode(v)) { + jl_array_t *values = (jl_array_t*)jl_fieldref_noalloc(v, 0); + size_t l = jl_array_len(values); + if (l <= 255) { + writetag(s->s, jl_phicnode_type); + write_uint8(s->s, (uint8_t)l); + } + else { + writetag(s->s, (jl_value_t*)LongPhic_tag); + write_int32(s->s, l); + } + for (i = 0; i < l; i++) { + jl_serialize_value(s, jl_array_ptr_ref(values, i)); + } + } else if (jl_is_datatype(v)) { jl_serialize_datatype(s, (jl_datatype_t*)v); } @@ -1336,6 +1381,8 @@ static jl_value_t *jl_deserialize_value(jl_serializer_state *s, jl_value_t **loc jl_value_t *vtag = deser_tag[tag]; if (tag >= VALUE_TAGS) { + if (vtag == (jl_value_t*)LineInfoNodeType_tag) + return (jl_value_t*)jl_lineinfonode_type; return vtag; } else if (vtag == (jl_value_t*)LiteralVal_tag) { @@ -1457,6 +1504,52 @@ static jl_value_t *jl_deserialize_value_expr(jl_serializer_state *s, jl_value_t return (jl_value_t*)e; } +static jl_value_t *jl_deserialize_value_phi(jl_serializer_state *s, jl_value_t *vtag) +{ + int usetable = (s->mode != MODE_AST); + size_t i, len_e, len_v; + if (vtag == (jl_value_t*)jl_phinode_type) { + len_e = len_v = read_uint8(s->s); + } + else { + len_e = read_int32(s->s); + len_v = read_int32(s->s); + } + jl_array_t *e = jl_alloc_vec_any(len_e); + jl_array_t *v = jl_alloc_vec_any(len_v); + jl_value_t *phi = jl_new_struct(jl_phinode_type, e, v); + if (usetable) + arraylist_push(&backref_list, phi); + jl_value_t **data_e = (jl_value_t**)(e->data); + for (i = 0; i < len_e; i++) { + data_e[i] = jl_deserialize_value(s, &data_e[i]); + } + jl_value_t **data_v = (jl_value_t**)(v->data); + for (i = 0; i < len_v; i++) { + data_v[i] = jl_deserialize_value(s, &data_v[i]); + } + return phi; +} + +static jl_value_t *jl_deserialize_value_phic(jl_serializer_state *s, jl_value_t *vtag) +{ + int usetable = (s->mode != MODE_AST); + size_t i, len; + if (vtag == (jl_value_t*)jl_phicnode_type) + len = read_uint8(s->s); + else + len = read_int32(s->s); + jl_array_t *v = jl_alloc_vec_any(len); + jl_value_t *phic = jl_new_struct(jl_phicnode_type, v); + if (usetable) + arraylist_push(&backref_list, phic); + jl_value_t **data = (jl_value_t**)(v->data); + for (i = 0; i < len; i++) { + data[i] = jl_deserialize_value(s, &data[i]); + } + return phic; +} + static jl_value_t *jl_deserialize_value_method(jl_serializer_state *s, jl_value_t **loc) { int usetable = (s->mode != MODE_AST); @@ -1819,6 +1912,14 @@ static jl_value_t *jl_deserialize_value_(jl_serializer_state *s, jl_value_t *vta vtag == (jl_value_t*)LongExpr_tag) { return jl_deserialize_value_expr(s, vtag); } + else if (vtag == (jl_value_t*)jl_phinode_type || + vtag == (jl_value_t*)LongPhi_tag) { + return jl_deserialize_value_phi(s, vtag); + } + else if (vtag == (jl_value_t*)jl_phicnode_type || + vtag == (jl_value_t*)LongPhic_tag) { + return jl_deserialize_value_phic(s, vtag); + } else if (vtag == (jl_value_t*)jl_tvar_type) { jl_tvar_t *tv = (jl_tvar_t*)jl_gc_alloc(s->ptls, sizeof(jl_tvar_t), jl_tvar_type); if (usetable) @@ -2844,8 +2945,10 @@ void jl_init_serializer(void) void *tags[] = { jl_symbol_type, jl_ssavalue_type, jl_datatype_type, jl_slotnumber_type, jl_simplevector_type, jl_array_type, jl_typedslot_type, - jl_expr_type, (void*)LongSymbol_tag, (void*)LongSvec_tag, - (void*)LongExpr_tag, (void*)LiteralVal_tag, jl_string_type, + jl_expr_type, jl_phinode_type, jl_phicnode_type, + (void*)LongSymbol_tag, (void*)LongSvec_tag, + (void*)LongExpr_tag, (void*)LongPhi_tag, (void*)LongPhic_tag, + (void*)LiteralVal_tag, jl_string_type, (void*)SmallInt64_tag, (void*)SmallDataType_tag, jl_typemap_entry_type, (void*)Int32_tag, (void*)Array1d_tag, (void*)Singleton_tag, jl_module_type, jl_tvar_type, jl_method_instance_type, jl_method_type, @@ -2884,9 +2987,9 @@ void jl_init_serializer(void) jl_box_int64(27), jl_box_int64(28), jl_bool_type, jl_int32_type, jl_int64_type, - jl_labelnode_type, jl_linenumbernode_type, jl_gotonode_type, - jl_quotenode_type, jl_pinode_type, jl_phinode_type, - jl_phicnode_type, jl_upsilonnode_type, + jl_labelnode_type, jl_gotonode_type, + jl_linenumbernode_type, (void*)LineInfoNodeType_tag, + jl_quotenode_type, jl_pinode_type, jl_upsilonnode_type, jl_type_type, jl_bottom_type, jl_ref_type, jl_pointer_type, jl_vararg_type, jl_abstractarray_type, jl_void_type, jl_densearray_type, jl_function_type, jl_unionall_type, jl_typename_type, diff --git a/src/init.c b/src/init.c index c5d50e5d65946..4698b0b566ed1 100644 --- a/src/init.c +++ b/src/init.c @@ -875,6 +875,7 @@ void jl_get_builtin_hooks(void) jl_methoderror_type = (jl_datatype_t*)core("MethodError"); jl_loaderror_type = (jl_datatype_t*)core("LoadError"); jl_initerror_type = (jl_datatype_t*)core("InitError"); + jl_lineinfonode_type = (jl_datatype_t*)core("LineInfoNode"); } void jl_get_builtins(void) diff --git a/src/jltypes.c b/src/jltypes.c index 01ef0439e7aab..5d72efd4bf60b 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -111,6 +111,7 @@ jl_datatype_t *jl_methoderror_type; jl_datatype_t *jl_loaderror_type; jl_datatype_t *jl_initerror_type; jl_datatype_t *jl_undefvarerror_type; +jl_datatype_t *jl_lineinfonode_type; jl_unionall_t *jl_ref_type; jl_unionall_t *jl_pointer_type; jl_typename_t *jl_pointer_typename; diff --git a/src/julia.h b/src/julia.h index ac752b2ec842b..17c8d2075dbb9 100644 --- a/src/julia.h +++ b/src/julia.h @@ -556,6 +556,7 @@ extern JL_DLLEXPORT jl_datatype_t *jl_initerror_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_datatype_t *jl_typeerror_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_datatype_t *jl_methoderror_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_datatype_t *jl_undefvarerror_type JL_GLOBALLY_ROOTED; +extern JL_DLLEXPORT jl_datatype_t *jl_lineinfonode_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_value_t *jl_stackovf_exception JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_value_t *jl_memory_exception JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_value_t *jl_readonlymemory_exception JL_GLOBALLY_ROOTED; diff --git a/src/timing.c b/src/timing.c index a9ee6d7685a10..5e234e52182e6 100644 --- a/src/timing.c +++ b/src/timing.c @@ -3,6 +3,7 @@ #include #include "julia.h" #include "options.h" +#include "stdio.h" #ifdef __cplusplus extern "C" {