diff options
author | aoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-10-12 18:58:38 +0000 |
---|---|---|
committer | aoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-10-12 18:58:38 +0000 |
commit | 688ff29b2a2ea29629307f2a0d444059391dee7b (patch) | |
tree | 0cd2fe4eab12298b796d2e872b3b8cd073d8ef6c /gcc/tree-ssa.c | |
parent | 74daae8261e7e34d2945f7399a987a1a31654e6d (diff) | |
download | gcc-688ff29b2a2ea29629307f2a0d444059391dee7b.tar.gz |
gcc/ChangeLog:
PR debug/41343
PR debug/41447
PR debug/41264
PR debug/41338
* tree.def (DEBUG_EXPR_DECL): New.
* rtl.def (DEBUG_EXPR): New.
* gengtype.c (adjust_field_rtx_def): Handle it.
* tree-ssa.c (propagate_var_def_into_debug_stmts): Rename to...
(insert_debug_temp_for_var_def): ... this. Drop support for
moving. Take iterator for def stmt; insert debug stmt before it.
Scan early for use count and kind in debug stmts.
(propagate_defs_into_debug_stmts): Rename to...
(insert_debug_temps_for_defs): ... this. Likewise.
* tree.h (DEBUG_TEMP_UID): New.
* tree.c (next_debug_decl_uid): New.
(make_node_stat): Count debug decls separately.
(copy_node_stat): Likewise.
* cfgexpand.c (expand_debug_expr): Handle DEBUG_EXPR_DECL.
* var-tracking.c (dv_is_decl_p): Recognize it.
(VALUE_RECURSED_INTO): Apply to DEBUG_EXPRs too.
(track_expr_p): Track expanded DEBUG_EXPR_DECLs.
(vt_expand_loc_callback): Expand DEBUG_EXPRs.
(emit_note_insn_var_location): Don't emit notes for DEBUG_EXPR_DECLs.
* cselib.c (rtx_equal_for_cselib_p): Handle DEBUG_EXPR.
(cselib_hash_rtx): Likewise.
(cselib_expand_value_rtx_1): Use callback for DEBUG_EXPR.
* tree-ssa-operands.c (get_expr_operands): Skip DEBUG_EXPR_DECLs in
debug bind stmts.
* emit-rtl.c (verify_rtx_sharing): Handle DEBUG_EXPR and VALUE.
(copy_rtx_if_shared_1, reset_used_flags, set_used_flags): Likewise.
* rtl.c (copy_rtx): Likewise.
(rtx_equal_p_cb, rtx_equal_p): Handle DEBUG_EXPR.
* print-rtl.c (print_rtx): Likewise.
* sched-vis.c (print_value): Likewise.
(print_insn): Handle DEBUG_EXPR_DECL.
* tree-dump.c (dequeue_and_dump): Likewise.
* tree-pretty-print.c (dump_decl_name, dump_generic_node): Likewise.
* gimple-iterator (gsi_replace): Check for same lhs.
(gsi_remove): Insert debug temps.
* tree-ssa-loop-im.c (rewrite_reciprocal): Replace with same lhs.
(move_computations_stmt): Drop explicit propagation into debug stmts.
(rewrite_bittest): Likewise. Use gsi_remove for propagation.
* tree-ssa-reassoc.c (rewrite_expr_tree, linearize_expr): Likewise.
* tree-ssa-sink.c (statement_sink_location): Likewise.
* tree-ssa-forwprop (forward_propagate_addr_expr): Likewise.
* tree-ssanames.c (release_ssa_name): Adjust for rename.
* tree-flow.h: Likewise.
* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Don't mark
debug temps without values.
(eliminate_unnecessary_stmts): Don't discard just-inserted
debug stmts.
gcc/testsuite/ChangeLog:
PR debug/41343
PR debug/41447
PR debug/41264
PR debug/41338
* gcc.dg/guality/pr41447-1.c: New.
* gcc.dg/debug/pr41264-1.c: New.
* gcc.dg/debug/pr41343-1.c: New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@152681 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa.c')
-rw-r--r-- | gcc/tree-ssa.c | 240 |
1 files changed, 143 insertions, 97 deletions
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 9015d19c189..9858b109d03 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -295,152 +295,198 @@ find_released_ssa_name (tree *tp, int *walk_subtrees, void *data_) return NULL_TREE; } -/* Given a VAR whose definition STMT is to be moved to the iterator - position TOGSIP in the TOBB basic block, verify whether we're - moving it across any of the debug statements that use it, and - adjust them as needed. If TOBB is NULL, then the definition is - understood as being removed, and TOGSIP is unused. */ +/* Insert a DEBUG BIND stmt before the DEF of VAR if VAR is referenced + by other DEBUG stmts, and replace uses of the DEF with the + newly-created debug temp. */ + void -propagate_var_def_into_debug_stmts (tree var, - basic_block tobb, - const gimple_stmt_iterator *togsip) +insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var) { imm_use_iterator imm_iter; - gimple stmt; use_operand_p use_p; + gimple stmt; + gimple def_stmt = NULL; + int usecount = 0; tree value = NULL; - bool no_value = false; if (!MAY_HAVE_DEBUG_STMTS) return; - FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var) + /* First of all, check whether there are debug stmts that reference + this variable and, if there are, decide whether we should use a + debug temp. */ + FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var) { - basic_block bb; - gimple_stmt_iterator si; + stmt = USE_STMT (use_p); - if (!is_gimple_debug (stmt)) + if (!gimple_debug_bind_p (stmt)) continue; - if (tobb) + if (usecount++) + break; + + if (gimple_debug_bind_get_value (stmt) != var) { - bb = gimple_bb (stmt); + /* Count this as an additional use, so as to make sure we + use a temp unless VAR's definition has a SINGLE_RHS that + can be shared. */ + usecount++; + break; + } + } - if (bb != tobb) - { - gcc_assert (dom_info_available_p (CDI_DOMINATORS)); - if (dominated_by_p (CDI_DOMINATORS, bb, tobb)) - continue; - } - else - { - si = *togsip; + if (!usecount) + return; - if (gsi_end_p (si)) - continue; + if (gsi) + def_stmt = gsi_stmt (*gsi); + else + def_stmt = SSA_NAME_DEF_STMT (var); - do - { - gsi_prev (&si); - if (gsi_end_p (si)) - break; - } - while (gsi_stmt (si) != stmt); + /* If we didn't get an insertion point, and the stmt has already + been removed, we won't be able to insert the debug bind stmt, so + we'll have to drop debug information. */ + if (is_gimple_assign (def_stmt)) + { + bool no_value = false; - if (gsi_end_p (si)) - continue; - } + if (!dom_info_available_p (CDI_DOMINATORS)) + { + struct walk_stmt_info wi; + + memset (&wi, 0, sizeof (wi)); + + /* When removing blocks without following reverse dominance + order, we may sometimes encounter SSA_NAMEs that have + already been released, referenced in other SSA_DEFs that + we're about to release. Consider: + + <bb X>: + v_1 = foo; + + <bb Y>: + w_2 = v_1 + bar; + # DEBUG w => w_2 + + If we deleted BB X first, propagating the value of w_2 + won't do us any good. It's too late to recover their + original definition of v_1: when it was deleted, it was + only referenced in other DEFs, it couldn't possibly know + it should have been retained, and propagating every + single DEF just in case it might have to be propagated + into a DEBUG STMT would probably be too wasteful. + + When dominator information is not readily available, we + check for and accept some loss of debug information. But + if it is available, there's no excuse for us to remove + blocks in the wrong order, so we don't even check for + dead SSA NAMEs. SSA verification shall catch any + errors. */ + if ((!gsi && !gimple_bb (def_stmt)) + || !walk_gimple_op (def_stmt, find_released_ssa_name, + &wi)) + no_value = true; } - /* Here we compute (lazily) the value assigned to VAR, but we - remember if we tried before and failed, so that we don't try - again. */ - if (!value && !no_value) + if (!no_value) + value = gimple_assign_rhs_to_tree (def_stmt); + } + + if (value) + { + /* If there's a single use of VAR, and VAR is the entire debug + expression (usecount would have been incremented again + otherwise), and the definition involves only constants and + SSA names, then we can propagate VALUE into this single use, + avoiding the temp. + + We can also avoid using a temp if VALUE can be shared and + propagated into all uses, without generating expressions that + wouldn't be valid gimple RHSs. + + Other cases that would require unsharing or non-gimple RHSs + are deferred to a debug temp, although we could avoid temps + at the expense of duplication of expressions. */ + + if (CONSTANT_CLASS_P (value) + || (usecount == 1 + && (!gimple_assign_single_p (def_stmt) + || is_gimple_min_invariant (value))) + || is_gimple_reg (value)) + value = unshare_expr (value); + else { - gimple def_stmt = SSA_NAME_DEF_STMT (var); + gimple def_temp; + tree vexpr = make_node (DEBUG_EXPR_DECL); - if (is_gimple_assign (def_stmt)) - { - if (!dom_info_available_p (CDI_DOMINATORS)) - { - struct walk_stmt_info wi; - - memset (&wi, 0, sizeof (wi)); - - /* When removing blocks without following reverse - dominance order, we may sometimes encounter SSA_NAMEs - that have already been released, referenced in other - SSA_DEFs that we're about to release. Consider: - - <bb X>: - v_1 = foo; - - <bb Y>: - w_2 = v_1 + bar; - # DEBUG w => w_2 - - If we deleted BB X first, propagating the value of - w_2 won't do us any good. It's too late to recover - their original definition of v_1: when it was - deleted, it was only referenced in other DEFs, it - couldn't possibly know it should have been retained, - and propagating every single DEF just in case it - might have to be propagated into a DEBUG STMT would - probably be too wasteful. - - When dominator information is not readily - available, we check for and accept some loss of - debug information. But if it is available, - there's no excuse for us to remove blocks in the - wrong order, so we don't even check for dead SSA - NAMEs. SSA verification shall catch any - errors. */ - if (!walk_gimple_op (def_stmt, find_released_ssa_name, &wi)) - no_value = true; - } + def_temp = gimple_build_debug_bind (vexpr, + unshare_expr (value), + def_stmt); + + DECL_ARTIFICIAL (vexpr) = 1; + TREE_TYPE (vexpr) = TREE_TYPE (value); + if (DECL_P (value)) + DECL_MODE (vexpr) = DECL_MODE (value); + else + DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (value)); - if (!no_value) - value = gimple_assign_rhs_to_tree (def_stmt); + if (gsi) + gsi_insert_before (gsi, def_temp, GSI_SAME_STMT); + else + { + gimple_stmt_iterator ngsi = gsi_for_stmt (def_stmt); + gsi_insert_before (&ngsi, def_temp, GSI_SAME_STMT); } - if (!value) - no_value = true; + value = vexpr; } + } - if (no_value) - gimple_debug_bind_reset_value (stmt); - else + FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var) + { + if (!gimple_debug_bind_p (stmt)) + continue; + + if (value) FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter) - SET_USE (use_p, unshare_expr (value)); + /* unshare_expr is not needed here. vexpr is either a + SINGLE_RHS, that can be safely shared, some other RHS + that was unshared when we found it had a single debug + use, or a DEBUG_EXPR_DECL, that can be safely + shared. */ + SET_USE (use_p, value); + else + gimple_debug_bind_reset_value (stmt); update_stmt (stmt); } } -/* Given a STMT to be moved to the iterator position TOBSIP in the - TOBB basic block, verify whether we're moving it across any of the - debug statements that use it. If TOBB is NULL, then the definition - is understood as being removed, and TOBSIP is unused. */ +/* Insert a DEBUG BIND stmt before STMT for each DEF referenced by + other DEBUG stmts, and replace uses of the DEF with the + newly-created debug temp. */ void -propagate_defs_into_debug_stmts (gimple def, basic_block tobb, - const gimple_stmt_iterator *togsip) +insert_debug_temps_for_defs (gimple_stmt_iterator *gsi) { + gimple stmt; ssa_op_iter op_iter; def_operand_p def_p; if (!MAY_HAVE_DEBUG_STMTS) return; - FOR_EACH_SSA_DEF_OPERAND (def_p, def, op_iter, SSA_OP_DEF) + stmt = gsi_stmt (*gsi); + + FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, op_iter, SSA_OP_DEF) { tree var = DEF_FROM_PTR (def_p); if (TREE_CODE (var) != SSA_NAME) continue; - propagate_var_def_into_debug_stmts (var, tobb, togsip); + insert_debug_temp_for_var_def (gsi, var); } } |