aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2007-10-02 01:42:09 +0000
committerAlexandre Oliva <aoliva@redhat.com>2007-10-02 01:42:09 +0000
commit18709e5e8a145296bac1ce2c07aa088e0b164018 (patch)
treea94bb5163f7b6e2ed2b09860cad2197ecbdd703b
parent9614cb30a621f20cb46bfc637d86a98f7b8830d3 (diff)
* tree-inline.c (processing_debug_stmt_p): New variable.
(remap_decl): Register variables only while not processing debug statements. (copy_body_r): Enqueue debug statements for later processing. (copy_bb): Skip debug statements. (copy_edges_for_bb): Likewise. (copy_debug_stmt): New fn. (copy_debug_stmts): New fn. (copy_generic_body, copy_body): Call it. (setup_one_parameter): Insert debug notes for inlined parms. (estimated_num_insns_1): Handle debug stmts. (optimize_inline_calls): Initialize debug stmt queue. (tree_function_versioning): Likewise. * tree-into-ssa.c (mark_def_sites): Handle debug stmts. (var_debug_value_for_decl): New fn. (adjust_debug_stmts_for_var_def_move): New fn. (adjust_debug_stmts_for_move): New fn. (check_debug_predicate): New struct. (check_and_update_debug_stmt_1): New fn. (check_and_update_debug_stmt): New fn. (insert_phi_nodes_for): Introduce debug stmts for phi nodes. (rewrite_stmt): Likewise, for SSA defs. (mark_use_interesting): Handle debug stmts. (prepare_block_for_update): Likewise. * tree.c (build_var_debug_value_stat): New fn. (empty_body_p): Handle debug stmts. * tree.def (VAR_DEBUG_VALUE): New tree code. * tree.h (VAR_DEBUG_VALUE_SET_VAR): New macro. (VAR_DEBUG_VALUE_VAR): Likewise. (VAR_DEBUG_VALUE_VALUE): Likewise. (IS_DEBUG_STMT): Likewise. (MAY_HAVE_DEBUG_STMTS): Likewise. (VAR_DEBUG_VALUE_NOVALUE): Likewise. (build_var_debug_value_stat): Declare. (build_var_debug_value): New macro. (var_debug_value_for_decl): Declare. * tree-gimple.c (is_gimple_stmt): Handle debug stmts. * tree-ssa-operands.c (opf_debug_use): New flag. (get_expr_operands): Handle debug stmts. Don't mark objects addressed in debug stmts as addressable. (parse_ssa_operands): Handle debug stmts. * tree-dump.c (dequeue_and_dump): Likewise. * tree-pretty-print.c (dump_generic_node): Likewise. * tree-ssa-dce (mark_stmt_if_obviously_necessary): Likewise. (necessary_p): New function. (eliminate_unnecessary_stmts): Handle debug stmts. * tree-ssa-propagate.c (get_rhs): Likewise. * tree-ssa.c (verify_ssa): Likewise. (execute_early_warn_uninitialized): Likewise. * tree-ssa-live.c (remove_unused_locals): Likewise. (set_var_live_on_entry): Likewise. * tree-ssa-dom.c (propagate_rhs_into_lhs): Likewise. * tree-flow-inline.h (has_zero_uses): Ignore uses in debug stmts. (has_single_use): Likewise. (single_imm_use): Likewise. (num_imm_uses): Likewise. (bsi_next_nondebug): New fn. (bsi_prev_nondebug): Likewise. (bsi_start_nondebug): Likewise. (bsi_last_nondebug): Likewise. * tree-ssa-phiopt.c (empty_block_p): Ignore debug stmts. * tree-ssa-sink.c (all_immediate_uses_same_place): Likewise. (nearest_common_dominator_of_uses): Check for debug stmts. (statement_sink_location): Handle debug stmts. * tree-ssa-threadedge.c (record_temporary_equivalences_from_stmts): Skip debug stmts. * tree-ssa-threadupdate.c (redirection_block_p): Ignore them. * tree-cfgcleanup.c (tree_forwarder_block_p): Likewise. * tree-outof-ssa.c (replace_use_variable): Don't clear. (analyze_edges_for_bb): Handle debug stmts. * tree-cfg.c (first_stmt): Skip debug stmts. (last_stmt): Likewise. (last_and_only_stmt): Likewise. (verify_expr): Verify debug value. (tree_block_ends_with_call_p): Skip debug stmts. * tree-flow.h (bsi_next_nondebug): Declare. (bsi_prev_nondebug): Likewise. (bsi_start_nondebug): Likewise. (bsi_last_nondebug): Likewise. (adjust_debug_stmts_for_move): Likewise. (adjust_debug_stmts_for_var_def_move): Likewise. (check_and_update_debug_stmt): Likewise. * tree-ssa-reassoc.c (linearize_expr): Adjust debug stmts. (linearize_expr_tree): Likewise. * tree-ssa-loop-ch.c (should_duplicate_loop_header_p): Skip debug stmts. * tree-ssa-ter.c (find_replaceable_in_bb): Likewise. * tree-ssa-loop-ivopts.c (find_interesting_uses_stmt): Likewise. (remove_unused_ivs): Adjust debug stmts. * tree-ssa-loop-im.c (rewrite_bittest): Likewise. (move_computations_stmt): Likewise. * tree-ssanames.c (release_ssa_name): Likewise. * tree-ssa-alias.c (find_used_portions): Handle debug exprs. * tree-ssa-structalias.c (compute_points_to_sets): Ignore debug stmts. * tree-tailcall.c (find_tail_calls): Handle debug stmts. * tree-vrp.c (find_assert_locations): Likewise. * tree-ssa-coalesce.c (build_ssa_conflict_graph): Likewise. (create_outofssa_var_map): Likewise. * tree-ssa-forwprop.c (forward_propagate_addr_expr): Handle debug stmts. * tree-ssa-pre.c (compute_avail): Skip debug stmts. * tree-ssa-loop-manip.c (find_uses_to_rename_stmt): Likewise. (check_loop_closed_ssa_stmt): Likewise. * tree-inline.h (copy_body_data): Add debug_stmts queue. * ipa-pure-const.c (scan_function): Skip debug stmts. * ipa-reference.c (scan_for_static_refs): Likewise. * ipa-type-escape.c (scan_for_refs): Likewise. * tree-stdarg.c (execute_optimize_stdarg): Likewise. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/var-tracking-assignments-branch@128945 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog.vta112
-rw-r--r--gcc/ipa-pure-const.c4
-rw-r--r--gcc/ipa-reference.c4
-rw-r--r--gcc/ipa-type-escape.c4
-rw-r--r--gcc/tree-cfg.c33
-rw-r--r--gcc/tree-cfgcleanup.c5
-rw-r--r--gcc/tree-dump.c5
-rw-r--r--gcc/tree-flow-inline.h120
-rw-r--r--gcc/tree-flow.h9
-rw-r--r--gcc/tree-gimple.c1
-rw-r--r--gcc/tree-inline.c87
-rw-r--r--gcc/tree-inline.h3
-rw-r--r--gcc/tree-into-ssa.c205
-rw-r--r--gcc/tree-outof-ssa.c7
-rw-r--r--gcc/tree-pretty-print.c13
-rw-r--r--gcc/tree-ssa-alias.c4
-rw-r--r--gcc/tree-ssa-coalesce.c5
-rw-r--r--gcc/tree-ssa-dce.c24
-rw-r--r--gcc/tree-ssa-dom.c2
-rw-r--r--gcc/tree-ssa-forwprop.c9
-rw-r--r--gcc/tree-ssa-live.c5
-rw-r--r--gcc/tree-ssa-loop-ch.c3
-rw-r--r--gcc/tree-ssa-loop-im.c2
-rw-r--r--gcc/tree-ssa-loop-ivopts.c22
-rw-r--r--gcc/tree-ssa-loop-manip.c6
-rw-r--r--gcc/tree-ssa-operands.c40
-rw-r--r--gcc/tree-ssa-phiopt.c3
-rw-r--r--gcc/tree-ssa-pre.c4
-rw-r--r--gcc/tree-ssa-propagate.c3
-rw-r--r--gcc/tree-ssa-reassoc.c3
-rw-r--r--gcc/tree-ssa-sink.c26
-rw-r--r--gcc/tree-ssa-structalias.c3
-rw-r--r--gcc/tree-ssa-ter.c4
-rw-r--r--gcc/tree-ssa-threadedge.c3
-rw-r--r--gcc/tree-ssa-threadupdate.c3
-rw-r--r--gcc/tree-ssa.c7
-rw-r--r--gcc/tree-ssanames.c3
-rw-r--r--gcc/tree-stdarg.c2
-rw-r--r--gcc/tree-tailcall.c5
-rw-r--r--gcc/tree-vrp.c3
-rw-r--r--gcc/tree.c17
-rw-r--r--gcc/tree.def4
-rw-r--r--gcc/tree.h47
43 files changed, 822 insertions, 52 deletions
diff --git a/gcc/ChangeLog.vta b/gcc/ChangeLog.vta
index 0386826678f..69679b2a06a 100644
--- a/gcc/ChangeLog.vta
+++ b/gcc/ChangeLog.vta
@@ -1,5 +1,117 @@
2007-10-01 Alexandre Oliva <aoliva@redhat.com>
+ * tree-inline.c (processing_debug_stmt_p): New variable.
+ (remap_decl): Register variables only while not processing debug
+ statements.
+ (copy_body_r): Enqueue debug statements for later processing.
+ (copy_bb): Skip debug statements.
+ (copy_edges_for_bb): Likewise.
+ (copy_debug_stmt): New fn.
+ (copy_debug_stmts): New fn.
+ (copy_generic_body, copy_body): Call it.
+ (setup_one_parameter): Insert debug notes for inlined parms.
+ (estimated_num_insns_1): Handle debug stmts.
+ (optimize_inline_calls): Initialize debug stmt queue.
+ (tree_function_versioning): Likewise.
+ * tree-into-ssa.c (mark_def_sites): Handle debug stmts.
+ (var_debug_value_for_decl): New fn.
+ (adjust_debug_stmts_for_var_def_move): New fn.
+ (adjust_debug_stmts_for_move): New fn.
+ (check_debug_predicate): New struct.
+ (check_and_update_debug_stmt_1): New fn.
+ (check_and_update_debug_stmt): New fn.
+ (insert_phi_nodes_for): Introduce debug stmts for phi nodes.
+ (rewrite_stmt): Likewise, for SSA defs.
+ (mark_use_interesting): Handle debug stmts.
+ (prepare_block_for_update): Likewise.
+ * tree.c (build_var_debug_value_stat): New fn.
+ (empty_body_p): Handle debug stmts.
+ * tree.def (VAR_DEBUG_VALUE): New tree code.
+ * tree.h (VAR_DEBUG_VALUE_SET_VAR): New macro.
+ (VAR_DEBUG_VALUE_VAR): Likewise.
+ (VAR_DEBUG_VALUE_VALUE): Likewise.
+ (IS_DEBUG_STMT): Likewise.
+ (MAY_HAVE_DEBUG_STMTS): Likewise.
+ (VAR_DEBUG_VALUE_NOVALUE): Likewise.
+ (build_var_debug_value_stat): Declare.
+ (build_var_debug_value): New macro.
+ (var_debug_value_for_decl): Declare.
+ * tree-gimple.c (is_gimple_stmt): Handle debug stmts.
+ * tree-ssa-operands.c (opf_debug_use): New flag.
+ (get_expr_operands): Handle debug stmts. Don't mark objects
+ addressed in debug stmts as addressable.
+ (parse_ssa_operands): Handle debug stmts.
+ * tree-dump.c (dequeue_and_dump): Likewise.
+ * tree-pretty-print.c (dump_generic_node): Likewise.
+ * tree-ssa-dce (mark_stmt_if_obviously_necessary): Likewise.
+ (necessary_p): New function.
+ (eliminate_unnecessary_stmts): Handle debug stmts.
+ * tree-ssa-propagate.c (get_rhs): Likewise.
+ * tree-ssa.c (verify_ssa): Likewise.
+ (execute_early_warn_uninitialized): Likewise.
+ * tree-ssa-live.c (remove_unused_locals): Likewise.
+ (set_var_live_on_entry): Likewise.
+ * tree-ssa-dom.c (propagate_rhs_into_lhs): Likewise.
+ * tree-flow-inline.h (has_zero_uses): Ignore uses in debug stmts.
+ (has_single_use): Likewise.
+ (single_imm_use): Likewise.
+ (num_imm_uses): Likewise.
+ (bsi_next_nondebug): New fn.
+ (bsi_prev_nondebug): Likewise.
+ (bsi_start_nondebug): Likewise.
+ (bsi_last_nondebug): Likewise.
+ * tree-ssa-phiopt.c (empty_block_p): Ignore debug stmts.
+ * tree-ssa-sink.c (all_immediate_uses_same_place): Likewise.
+ (nearest_common_dominator_of_uses): Check for debug stmts.
+ (statement_sink_location): Handle debug stmts.
+ * tree-ssa-threadedge.c
+ (record_temporary_equivalences_from_stmts): Skip debug stmts.
+ * tree-ssa-threadupdate.c (redirection_block_p): Ignore them.
+ * tree-cfgcleanup.c (tree_forwarder_block_p): Likewise.
+ * tree-outof-ssa.c (replace_use_variable): Don't clear.
+ (analyze_edges_for_bb): Handle debug stmts.
+ * tree-cfg.c (first_stmt): Skip debug stmts.
+ (last_stmt): Likewise.
+ (last_and_only_stmt): Likewise.
+ (verify_expr): Verify debug value.
+ (tree_block_ends_with_call_p): Skip debug stmts.
+ * tree-flow.h (bsi_next_nondebug): Declare.
+ (bsi_prev_nondebug): Likewise.
+ (bsi_start_nondebug): Likewise.
+ (bsi_last_nondebug): Likewise.
+ (adjust_debug_stmts_for_move): Likewise.
+ (adjust_debug_stmts_for_var_def_move): Likewise.
+ (check_and_update_debug_stmt): Likewise.
+ * tree-ssa-reassoc.c (linearize_expr): Adjust debug stmts.
+ (linearize_expr_tree): Likewise.
+ * tree-ssa-loop-ch.c (should_duplicate_loop_header_p): Skip debug
+ stmts.
+ * tree-ssa-ter.c (find_replaceable_in_bb): Likewise.
+ * tree-ssa-loop-ivopts.c (find_interesting_uses_stmt): Likewise.
+ (remove_unused_ivs): Adjust debug stmts.
+ * tree-ssa-loop-im.c (rewrite_bittest): Likewise.
+ (move_computations_stmt): Likewise.
+ * tree-ssanames.c (release_ssa_name): Likewise.
+ * tree-ssa-alias.c (find_used_portions): Handle debug exprs.
+ * tree-ssa-structalias.c (compute_points_to_sets): Ignore debug
+ stmts.
+ * tree-tailcall.c (find_tail_calls): Handle debug stmts.
+ * tree-vrp.c (find_assert_locations): Likewise.
+ * tree-ssa-coalesce.c (build_ssa_conflict_graph): Likewise.
+ (create_outofssa_var_map): Likewise.
+ * tree-ssa-forwprop.c (forward_propagate_addr_expr): Handle debug
+ stmts.
+ * tree-ssa-pre.c (compute_avail): Skip debug stmts.
+ * tree-ssa-loop-manip.c (find_uses_to_rename_stmt): Likewise.
+ (check_loop_closed_ssa_stmt): Likewise.
+ * tree-inline.h (copy_body_data): Add debug_stmts queue.
+ * ipa-pure-const.c (scan_function): Skip debug stmts.
+ * ipa-reference.c (scan_for_static_refs): Likewise.
+ * ipa-type-escape.c (scan_for_refs): Likewise.
+ * tree-stdarg.c (execute_optimize_stdarg): Likewise.
+
+2007-10-01 Alexandre Oliva <aoliva@redhat.com>
+
* common.opt (fvar-tracking-assignments): New.
* doc/invoke.texi: Document it.
* toplev.c (flag_var_tracking_assignments): New.
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index 519b402df20..ab8545da046 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -467,6 +467,10 @@ scan_function (tree *tp,
}
break;
+ case VAR_DEBUG_VALUE:
+ *walk_subtrees = 0;
+ break;
+
case ADDR_EXPR:
/* This case is here to find addresses on rhs of constructors in
decl_initial of static variables. */
diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c
index 1a962c52cdb..9002edf0000 100644
--- a/gcc/ipa-reference.c
+++ b/gcc/ipa-reference.c
@@ -552,6 +552,10 @@ scan_for_static_refs (tree *tp,
}
break;
+ case VAR_DEBUG_VALUE:
+ *walk_subtrees = 0;
+ break;
+
case ADDR_EXPR:
/* This case is here to find addresses on rhs of constructors in
decl_initial of static variables. */
diff --git a/gcc/ipa-type-escape.c b/gcc/ipa-type-escape.c
index 5303e79ec26..bf11f0b0499 100644
--- a/gcc/ipa-type-escape.c
+++ b/gcc/ipa-type-escape.c
@@ -1612,6 +1612,10 @@ scan_for_refs (tree *tp, int *walk_subtrees, void *data)
}
break;
+ case VAR_DEBUG_VALUE:
+ *walk_subtrees = 0;
+ break;
+
case ADDR_EXPR:
/* This case is here to find addresses on rhs of constructors in
decl_initial of static variables. */
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index c15e81e20b4..40ec164073f 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -2591,7 +2591,13 @@ tree
first_stmt (basic_block bb)
{
block_stmt_iterator i = bsi_start (bb);
- return !bsi_end_p (i) ? bsi_stmt (i) : NULL_TREE;
+ tree stmt = NULL;
+ while (!bsi_end_p (i) && IS_DEBUG_STMT ((stmt = bsi_stmt (i))))
+ {
+ bsi_next (&i);
+ stmt = NULL;
+ }
+ return stmt;
}
/* Return the last statement in basic block BB. */
@@ -2600,7 +2606,14 @@ tree
last_stmt (basic_block bb)
{
block_stmt_iterator b = bsi_last (bb);
- return !bsi_end_p (b) ? bsi_stmt (b) : NULL_TREE;
+ tree stmt = NULL;
+
+ while (!bsi_end_p (b) && IS_DEBUG_STMT ((stmt = bsi_stmt (b))))
+ {
+ bsi_prev (&b);
+ stmt = NULL;
+ }
+ return stmt;
}
/* Return the last statement of an otherwise empty block. Return NULL
@@ -2610,14 +2623,15 @@ last_stmt (basic_block bb)
tree
last_and_only_stmt (basic_block bb)
{
- block_stmt_iterator i = bsi_last (bb);
+ block_stmt_iterator i = bsi_last_nondebug (bb);
tree last, prev;
if (bsi_end_p (i))
return NULL_TREE;
last = bsi_stmt (i);
- bsi_prev (&i);
+ bsi_prev_nondebug (&i);
+
if (bsi_end_p (i))
return last;
@@ -3151,6 +3165,15 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
}
break;
+ case VAR_DEBUG_VALUE:
+ check_and_update_debug_stmt (t, NULL);
+ /* Walking sub-trees could fail to verify ADDR_EXPRs referencing
+ variables that became non-addressable due to optimization,
+ and perhaps other reasons as well. We could perform some
+ more limited form of checking. */
+ *walk_subtrees = 0;
+ break;
+
case ADDR_EXPR:
{
bool old_invariant;
@@ -6249,7 +6272,7 @@ debug_loop_ir (void)
static bool
tree_block_ends_with_call_p (basic_block bb)
{
- block_stmt_iterator bsi = bsi_last (bb);
+ block_stmt_iterator bsi = bsi_last_nondebug (bb);
return get_call_expr_in (bsi_stmt (bsi)) != NULL;
}
diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c
index bcae4488dc1..69548fee276 100644
--- a/gcc/tree-cfgcleanup.c
+++ b/gcc/tree-cfgcleanup.c
@@ -270,6 +270,11 @@ tree_forwarder_block_p (basic_block bb, bool phi_wanted)
return false;
break;
+ /* ??? For now, hope there's a corresponding debug
+ assignment at the destination. */
+ case VAR_DEBUG_VALUE:
+ break;
+
default:
return false;
}
diff --git a/gcc/tree-dump.c b/gcc/tree-dump.c
index 6821e363bb3..66da6dd53b4 100644
--- a/gcc/tree-dump.c
+++ b/gcc/tree-dump.c
@@ -605,6 +605,11 @@ dequeue_and_dump (dump_info_p di)
dump_child ("op 1", GIMPLE_STMT_OPERAND (t, 1));
break;
+ case VAR_DEBUG_VALUE:
+ dump_child ("op 0", VAR_DEBUG_VALUE_VAR (t));
+ dump_child ("op 1", VAR_DEBUG_VALUE_VALUE (t));
+ break;
+
case COMPONENT_REF:
dump_child ("op 0", TREE_OPERAND (t, 0));
dump_child ("op 1", TREE_OPERAND (t, 1));
diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h
index 71e607bddce..0c13992eddb 100644
--- a/gcc/tree-flow-inline.h
+++ b/gcc/tree-flow-inline.h
@@ -524,18 +524,48 @@ next_readonly_imm_use (imm_use_iterator *imm)
static inline bool
has_zero_uses (const_tree var)
{
- const ssa_use_operand_t *const ptr = &(SSA_NAME_IMM_USE_NODE (var));
+ const ssa_use_operand_t *ptr, *start;
+ bool ret;
+
+ ptr = &(SSA_NAME_IMM_USE_NODE (var));
/* A single use means there is no items in the list. */
- return (ptr == ptr->next);
+ ret = (ptr == ptr->next);
+
+ if (ret || !MAY_HAVE_DEBUG_STMTS)
+ return ret;
+
+ start = ptr;
+ for (ptr = start->next; ptr != start; ptr = ptr->next)
+ if (!IS_DEBUG_STMT (ptr->stmt))
+ return false;
+ return true;
}
/* Return true if VAR has a single use. */
static inline bool
has_single_use (const_tree var)
{
- const ssa_use_operand_t *const ptr = &(SSA_NAME_IMM_USE_NODE (var));
+ const ssa_use_operand_t *ptr, *start;
+ bool ret;
+
+ ptr = &(SSA_NAME_IMM_USE_NODE (var));
/* A single use means there is one item in the list. */
- return (ptr != ptr->next && ptr == ptr->next->next);
+ ret = (ptr != ptr->next && ptr == ptr->next->next);
+
+ if (ret)
+ return !IS_DEBUG_STMT (ptr->next->stmt);
+ else if (!MAY_HAVE_DEBUG_STMTS)
+ return ret;
+
+ start = ptr;
+ for (ptr = start->next; ptr != start; ptr = ptr->next)
+ if (!IS_DEBUG_STMT (ptr->stmt))
+ {
+ if (ret)
+ return false;
+ ret = true;
+ }
+ return ret;
}
@@ -544,8 +574,35 @@ has_single_use (const_tree var)
static inline bool
single_imm_use (const_tree var, use_operand_p *use_p, tree *stmt)
{
- const ssa_use_operand_t *const ptr = &(SSA_NAME_IMM_USE_NODE (var));
- if (ptr != ptr->next && ptr == ptr->next->next)
+ const ssa_use_operand_t *ptr;
+ bool ret;
+
+ ptr = &(SSA_NAME_IMM_USE_NODE (var));
+
+ ret = ptr != ptr->next && ptr == ptr->next->next;
+
+ if (ret)
+ ret = !IS_DEBUG_STMT (ptr->next->stmt);
+ else if (MAY_HAVE_DEBUG_STMTS)
+ {
+ const ssa_use_operand_t *start = ptr, *prev = ptr, *single_use_prev = 0;
+
+ for (ptr = start->next; ptr != start; prev = ptr, ptr = ptr->next)
+ if (!IS_DEBUG_STMT (ptr->stmt))
+ {
+ if (ret)
+ {
+ ret = false;
+ break;
+ }
+ ret = true;
+ single_use_prev = prev;
+ }
+
+ ptr = single_use_prev;
+ }
+
+ if (ret)
{
*use_p = ptr->next;
*stmt = ptr->next->stmt;
@@ -564,8 +621,13 @@ num_imm_uses (const_tree var)
const ssa_use_operand_t *ptr;
unsigned int num = 0;
- for (ptr = start->next; ptr != start; ptr = ptr->next)
- num++;
+ if (!MAY_HAVE_DEBUG_STMTS)
+ for (ptr = start->next; ptr != start; ptr = ptr->next)
+ num++;
+ else
+ for (ptr = start->next; ptr != start; ptr = ptr->next)
+ if (!IS_DEBUG_STMT (ptr->stmt))
+ num++;
return num;
}
@@ -817,6 +879,48 @@ bsi_stmt_ptr (block_stmt_iterator i)
return tsi_stmt_ptr (i.tsi);
}
+/* Modify block statement iterator I so that it is at the next
+ statement in the basic block. */
+static inline void
+bsi_next_nondebug (block_stmt_iterator *i)
+{
+ do
+ bsi_next (i);
+ while (!bsi_end_p (*i) && IS_DEBUG_STMT (bsi_stmt (*i)));
+}
+
+/* Modify block statement iterator I so that it is at the previous
+ non-debug statement in the basic block. */
+static inline void
+bsi_prev_nondebug (block_stmt_iterator *i)
+{
+ do
+ bsi_prev (i);
+ while (!bsi_end_p (*i) && IS_DEBUG_STMT (bsi_stmt (*i)));
+}
+
+static inline block_stmt_iterator
+bsi_start_nondebug (basic_block bb)
+{
+ block_stmt_iterator bsi = bsi_start (bb);
+
+ while (!bsi_end_p (bsi) && IS_DEBUG_STMT (bsi_stmt (bsi)))
+ bsi_next (&bsi);
+
+ return bsi;
+}
+
+static inline block_stmt_iterator
+bsi_last_nondebug (basic_block bb)
+{
+ block_stmt_iterator bsi = bsi_last (bb);
+
+ while (!bsi_end_p (bsi) && IS_DEBUG_STMT (bsi_stmt (bsi)))
+ bsi_prev (&bsi);
+
+ return bsi;
+}
+
/* Returns the loop of the statement STMT. */
static inline struct loop *
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index 518e4f2236e..0ad8ee3a785 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -633,6 +633,10 @@ static inline void bsi_next (block_stmt_iterator *);
static inline void bsi_prev (block_stmt_iterator *);
static inline tree bsi_stmt (block_stmt_iterator);
static inline tree * bsi_stmt_ptr (block_stmt_iterator);
+static inline void bsi_next_nondebug (block_stmt_iterator *);
+static inline void bsi_prev_nondebug (block_stmt_iterator *);
+static inline block_stmt_iterator bsi_start_nondebug (basic_block);
+static inline block_stmt_iterator bsi_last_nondebug (basic_block);
extern void bsi_remove (block_stmt_iterator *, bool);
extern void bsi_move_before (block_stmt_iterator *, block_stmt_iterator *);
@@ -890,6 +894,11 @@ void mark_sym_for_renaming (tree);
void mark_set_for_renaming (bitmap);
tree get_current_def (tree);
void set_current_def (tree, tree);
+void adjust_debug_stmts_for_move (tree, basic_block,
+ const block_stmt_iterator *);
+void adjust_debug_stmts_for_var_def_move (tree, basic_block,
+ const block_stmt_iterator *);
+void check_and_update_debug_stmt (tree, bool (*)(tree));
/* In tree-ssa-ccp.c */
bool fold_stmt (tree *);
diff --git a/gcc/tree-gimple.c b/gcc/tree-gimple.c
index 8e976e201fe..fc77c0a89da 100644
--- a/gcc/tree-gimple.c
+++ b/gcc/tree-gimple.c
@@ -245,6 +245,7 @@ is_gimple_stmt (tree t)
case CALL_EXPR:
case GIMPLE_MODIFY_STMT:
+ case VAR_DEBUG_VALUE:
/* These are valid regardless of their type. */
return true;
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 936808fa875..a0b7b8cae95 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -201,6 +201,8 @@ remap_ssa_name (tree name, copy_body_data *id)
return new;
}
+bool processing_debug_stmt_p = false;
+
/* Remap DECL during the copying of the BLOCK tree for the function. */
tree
@@ -262,7 +264,8 @@ remap_decl (tree decl, copy_body_data *id)
if (TREE_CODE (map) == SSA_NAME)
set_default_def (t, map);
}
- add_referenced_var (t);
+ if (!processing_debug_stmt_p)
+ add_referenced_var (t);
}
return t;
}
@@ -699,6 +702,13 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
return NULL;
}
}
+ else if (IS_DEBUG_STMT (*tp))
+ {
+ *tp = copy_node (*tp);
+ VARRAY_PUSH_TREE (id->debug_stmts, *tp);
+ *walk_subtrees = 0;
+ goto shallow_stmt_copy;
+ }
/* Here is the "usual case". Copy this tree node, and then
tweak some special cases. */
@@ -714,6 +724,7 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
of function call. */
if (EXPR_P (*tp) || GIMPLE_STMT_P (*tp))
{
+ shallow_stmt_copy:
new_block = id->block;
if (TREE_BLOCK (*tp))
{
@@ -817,6 +828,13 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, int count_scal
{
tree *stmtp = bsi_stmt_ptr (copy_bsi);
tree stmt = *stmtp;
+
+ if (IS_DEBUG_STMT (stmt))
+ {
+ bsi_next (&copy_bsi);
+ continue;
+ }
+
call = get_call_expr_in (stmt);
if (call && CALL_EXPR_VA_ARG_PACK (call) && id->call_expr)
@@ -1102,9 +1120,12 @@ copy_edges_for_bb (basic_block bb, int count_scale, basic_block ret_bb)
bool can_throw, nonlocal_goto;
copy_stmt = bsi_stmt (bsi);
- update_stmt (copy_stmt);
- if (gimple_in_ssa_p (cfun))
- mark_symbols_for_renaming (copy_stmt);
+ if (!IS_DEBUG_STMT (copy_stmt))
+ {
+ update_stmt (copy_stmt);
+ if (gimple_in_ssa_p (cfun))
+ mark_symbols_for_renaming (copy_stmt);
+ }
/* Do this before the possible split_block. */
bsi_next (&bsi);
@@ -1337,6 +1358,40 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency,
return new_fndecl;
}
+static void
+copy_debug_stmt (tree stmt, copy_body_data *id)
+{
+ tree t;
+
+ processing_debug_stmt_p = true;
+
+ t = VAR_DEBUG_VALUE_VAR (stmt);
+ walk_tree (&t, copy_body_r, id, NULL);
+ VAR_DEBUG_VALUE_SET_VAR (stmt, t);
+
+ walk_tree (&VAR_DEBUG_VALUE_VALUE (stmt), copy_body_r, id, NULL);
+
+ processing_debug_stmt_p = false;
+
+ update_stmt (stmt);
+ if (gimple_in_ssa_p (cfun))
+ mark_symbols_for_renaming (stmt);
+}
+
+static void
+copy_debug_stmts (copy_body_data *id)
+{
+ size_t i, e;
+
+ if (!id->debug_stmts)
+ return;
+
+ for (i = 0, e = VARRAY_ACTIVE_SIZE (id->debug_stmts); i < e; i++)
+ copy_debug_stmt (VARRAY_TREE (id->debug_stmts, i), id);
+
+ VARRAY_POP_ALL (id->debug_stmts);
+}
+
/* Make a copy of the body of FN so that it can be inserted inline in
another function. */
@@ -1348,6 +1403,7 @@ copy_generic_body (copy_body_data *id)
body = DECL_SAVED_TREE (fndecl);
walk_tree (&body, copy_body_r, id, NULL);
+ copy_debug_stmts (id);
return body;
}
@@ -1362,6 +1418,7 @@ copy_body (copy_body_data *id, gcov_type count, int frequency,
/* If this body has a CFG, walk CFG and copy. */
gcc_assert (ENTRY_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (fndecl)));
body = copy_cfg_body (id, count, frequency, entry_block_map, exit_block_map);
+ copy_debug_stmts (id);
return body;
}
@@ -1486,8 +1543,18 @@ setup_one_parameter (copy_body_data *id, tree p, tree value,
if (init_stmt)
bsi_insert_after (&bsi, init_stmt, BSI_NEW_STMT);
if (gimple_in_ssa_p (cfun))
- for (;!bsi_end_p (bsi); bsi_next (&bsi))
- mark_symbols_for_renaming (bsi_stmt (bsi));
+ {
+ if (MAY_HAVE_DEBUG_STMTS && var_debug_value_for_decl (var))
+ {
+ tree note = build_var_debug_value (var,
+ is_gimple_reg (p)
+ ? def : var);
+ bsi_insert_after (&bsi, note, BSI_SAME_STMT);
+ }
+
+ for (;!bsi_end_p (bsi); bsi_next (&bsi))
+ mark_symbols_for_renaming (bsi_stmt (bsi));
+ }
}
}
@@ -2093,8 +2160,9 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
*walk_subtrees = 0;
return NULL;
- /* CHANGE_DYNAMIC_TYPE_EXPR explicitly expands to nothing. */
+ /* These explicitly expand to nothing. */
case CHANGE_DYNAMIC_TYPE_EXPR:
+ case VAR_DEBUG_VALUE:
*walk_subtrees = 0;
return NULL;
@@ -2804,6 +2872,8 @@ optimize_inline_calls (tree fn)
id.transform_return_to_modify = true;
id.transform_lang_insert_block = false;
id.statements_to_fold = pointer_set_create ();
+ if (MAY_HAVE_DEBUG_STMTS)
+ VARRAY_TREE_INIT (id.debug_stmts, 8, "debug_stmt");
push_gimplify_context ();
@@ -3376,6 +3446,9 @@ tree_function_versioning (tree old_decl, tree new_decl, varray_type tree_map,
SET_DECL_RTL (new_decl, NULL_RTX);
id.statements_to_fold = pointer_set_create ();
}
+
+ if (MAY_HAVE_DEBUG_STMTS)
+ VARRAY_TREE_INIT (id.debug_stmts, 8, "debug_stmt");
id.decl_map = pointer_map_create ();
id.src_fn = old_decl;
diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h
index 895a0afcbbd..d2ac460c572 100644
--- a/gcc/tree-inline.h
+++ b/gcc/tree-inline.h
@@ -94,6 +94,9 @@ typedef struct copy_body_data
/* Statements that might be possibly folded. */
struct pointer_set_t *statements_to_fold;
+
+ /* Debug statements that need processing. */
+ varray_type debug_stmts;
} copy_body_data;
/* Weights of constructions for estimate_num_insns. */
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index 2baf879627e..7353a0fd80d 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -742,6 +742,9 @@ mark_def_sites (struct dom_walk_data *walk_data, basic_block bb,
REGISTER_DEFS_IN_THIS_STMT (stmt) = 0;
REWRITE_THIS_STMT (stmt) = 0;
+ if (IS_DEBUG_STMT (stmt))
+ return;
+
/* If a variable is used before being set, then the variable is live
across a block boundary, so mark it live-on-entry to BB. */
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
@@ -1104,6 +1107,183 @@ mark_phi_for_rewrite (basic_block bb, tree phi)
VEC_replace (tree_vec, phis_to_rewrite, idx, phis);
}
+/* Decide whether to emit a VAR_DEBUG_VALUE annotation for VAR. */
+
+bool
+var_debug_value_for_decl (tree var)
+{
+ if (TREE_CODE (var) != VAR_DECL
+ && TREE_CODE (var) != PARM_DECL)
+ return false;
+
+ if (DECL_IGNORED_P (var))
+ return false;
+
+ if (!MAY_HAVE_DEBUG_STMTS)
+ return false;
+
+ if (!is_gimple_reg (var))
+ return false;
+
+ return true;
+}
+
+/* Given a VAR whose definition STMT is 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, and
+ adjust them as needed. If TOBB is NULL, then the definition is
+ understood as being removed, and TOBSIP is unused. */
+void
+adjust_debug_stmts_for_var_def_move (tree var,
+ basic_block tobb,
+ const block_stmt_iterator *tobsip)
+{
+ imm_use_iterator imm_iter;
+ tree stmt;
+ use_operand_p use_p;
+
+ if (!MAY_HAVE_DEBUG_STMTS)
+ return;
+
+ FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
+ {
+ basic_block bb;
+ block_stmt_iterator si;
+
+ if (!IS_DEBUG_STMT (stmt))
+ continue;
+
+ if (tobb)
+ {
+ bb = bb_for_stmt (stmt);
+
+ if (bb != tobb)
+ {
+ if (dominated_by_p (CDI_DOMINATORS, bb, tobb))
+ continue;
+ }
+ else
+ {
+ si = *tobsip;
+
+ if (bsi_end_p (si))
+ continue;
+
+ do
+ {
+ bsi_prev (&si);
+ if (bsi_end_p (si))
+ break;
+ }
+ while (bsi_stmt (si) != stmt);
+
+ if (bsi_end_p (si))
+ continue;
+ }
+ }
+
+ FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
+ SET_USE (use_p, unshare_expr (SSA_NAME_VALUE (var)));
+
+ 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. */
+
+void
+adjust_debug_stmts_for_move (tree def, basic_block tobb,
+ const block_stmt_iterator *tobsip)
+{
+ 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_ALL_DEFS)
+ {
+ tree var = DEF_FROM_PTR (def_p);
+
+ if (TREE_CODE (var) != SSA_NAME)
+ continue;
+
+ adjust_debug_stmts_for_var_def_move (var, tobb, tobsip);
+ }
+}
+
+/* Wrapper struct for the function predicate passed to
+ check_and_update_debug_stmt_1 (). */
+
+struct check_debug_predicate
+{
+ bool (*available_p)(tree);
+};
+
+/* Look for an SSA_NAME in the expression *TP whose definition was
+ removed, or is about to be removed, per the available_p predicate
+ given by the check_debug_predicate *DATA. */
+
+static tree
+check_and_update_debug_stmt_1 (tree *tp, int *walk_subtrees,
+ void *data)
+{
+ tree t = *tp;
+
+ if (EXPR_P (t))
+ return NULL_TREE;
+
+ *walk_subtrees = 0;
+
+ if (TREE_CODE (t) == SSA_NAME)
+ {
+ struct check_debug_predicate *p = (struct check_debug_predicate *)data;
+
+ if (SSA_NAME_IN_FREE_LIST (t))
+ return t;
+
+ if (!SSA_NAME_DEF_STMT (t))
+ return t;
+
+ if (IS_EMPTY_STMT (SSA_NAME_DEF_STMT (t))
+ && TREE_CODE (SSA_NAME_VAR (t)) != PARM_DECL)
+ return t;
+
+ if (p->available_p && !p->available_p (t))
+ return t;
+ }
+
+ return NULL_TREE;
+}
+
+/* Look for any SSA_NAMEs in the VALUE of a VAR_DEBUG_VALUE statement
+ T that have become or are about to become unavailable.
+ AVAILABLE_P, if non-NULL, is used to determine whether the variable
+ is about to become unavailable. */
+
+void
+check_and_update_debug_stmt (tree t, bool (*available_p)(tree))
+{
+ struct check_debug_predicate p;
+
+ gcc_assert (IS_DEBUG_STMT (t));
+
+ if (VAR_DEBUG_VALUE_VALUE (t) == VAR_DEBUG_VALUE_NOVALUE)
+ return;
+
+ p.available_p = available_p;
+ if (walk_tree (&VAR_DEBUG_VALUE_VALUE (t), check_and_update_debug_stmt_1,
+ &p, NULL))
+ {
+ /* ??? Can we do better? */
+ VAR_DEBUG_VALUE_VALUE (t) = VAR_DEBUG_VALUE_NOVALUE;
+ update_stmt (t);
+ }
+}
/* Insert PHI nodes for variable VAR using the iterated dominance
frontier given in PHI_INSERTION_POINTS. If UPDATE_P is true, this
@@ -1173,6 +1353,12 @@ insert_phi_nodes_for (tree var, bitmap phi_insertion_points, bool update_p)
{
tree sym = DECL_P (var) ? var : SSA_NAME_VAR (var);
phi = create_phi_node (sym, bb);
+ if (!update_p && var_debug_value_for_decl (sym))
+ {
+ tree note = build_var_debug_value (sym, PHI_RESULT (phi));
+ block_stmt_iterator si = bsi_after_labels (bb);
+ bsi_insert_before (&si, note, BSI_SAME_STMT);
+ }
}
/* Mark this PHI node as interesting for update_ssa. */
@@ -1378,9 +1564,14 @@ rewrite_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
if (REGISTER_DEFS_IN_THIS_STMT (stmt))
FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_DEF)
{
- tree var = DEF_FROM_PTR (def_p);
+ tree var = DEF_FROM_PTR (def_p), name;
gcc_assert (DECL_P (var));
- SET_DEF (def_p, make_ssa_name (var, stmt));
+ SET_DEF (def_p, name = make_ssa_name (var, stmt));
+ if (var_debug_value_for_decl (var))
+ {
+ tree note = build_var_debug_value (var, name);
+ bsi_insert_after (&si, note, BSI_SAME_STMT);
+ }
register_new_def (DEF_FROM_PTR (def_p), var);
}
}
@@ -2363,7 +2554,12 @@ mark_use_interesting (tree var, tree stmt, basic_block bb, bool insert_phi_p)
if (TREE_CODE (stmt) == PHI_NODE)
mark_phi_for_rewrite (def_bb, stmt);
else
- REWRITE_THIS_STMT (stmt) = 1;
+ {
+ REWRITE_THIS_STMT (stmt) = 1;
+
+ if (IS_DEBUG_STMT (stmt))
+ return;
+ }
/* If VAR has not been defined in BB, then it is live-on-entry
to BB. Note that we cannot just use the block holding VAR's
@@ -2440,6 +2636,9 @@ prepare_block_for_update (basic_block bb, bool insert_phi_p)
stmt = bsi_stmt (si);
+ if (IS_DEBUG_STMT (stmt))
+ continue;
+
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, i, SSA_OP_ALL_USES)
{
tree use = USE_FROM_PTR (use_p);
diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c
index d01c663b2c5..7cd5d92ef80 100644
--- a/gcc/tree-outof-ssa.c
+++ b/gcc/tree-outof-ssa.c
@@ -563,7 +563,7 @@ replace_use_variable (var_map map, use_operand_p p, tree *expr)
SET_USE (p, new_expr);
/* Clear the stmt's RHS, or GC might bite us. */
- GIMPLE_STMT_OPERAND (expr[version], 1) = NULL_TREE;
+ /* GIMPLE_STMT_OPERAND (expr[version], 1) = NULL_TREE; */
return true;
}
}
@@ -918,11 +918,12 @@ analyze_edges_for_bb (basic_block bb)
if (!bsi_end_p (bsi))
{
stmt = bsi_stmt (bsi);
- bsi_next (&bsi);
+ bsi_next_nondebug (&bsi);
gcc_assert (stmt != NULL_TREE);
is_label = (TREE_CODE (stmt) == LABEL_EXPR);
/* Punt if it has non-label stmts, or isn't local. */
- if (!is_label || DECL_NONLOCAL (TREE_OPERAND (stmt, 0))
+ if (((!is_label || DECL_NONLOCAL (TREE_OPERAND (stmt, 0)))
+ && !IS_DEBUG_STMT (stmt))
|| !bsi_end_p (bsi))
{
bsi_commit_one_edge_insert (e, NULL);
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index a7b97cdcb5c..77a6538c488 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -1101,6 +1101,19 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
false);
break;
+ case VAR_DEBUG_VALUE:
+ pp_string (buffer, "# DEBUG ");
+ dump_generic_node (buffer, VAR_DEBUG_VALUE_VAR (node), spc, flags, false);
+ if (VAR_DEBUG_VALUE_VALUE (node) == VAR_DEBUG_VALUE_NOVALUE)
+ pp_string (buffer, " optimized away");
+ else
+ {
+ pp_string (buffer, " = ");
+ dump_generic_node (buffer, VAR_DEBUG_VALUE_VALUE (node), spc, flags,
+ false);
+ }
+ break;
+
case TARGET_EXPR:
pp_string (buffer, "TARGET_EXPR <");
dump_generic_node (buffer, TARGET_EXPR_SLOT (node), spc, flags, false);
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 1ff3821ed5a..d3f8f8c3359 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -3908,6 +3908,10 @@ find_used_portions (tree *tp, int *walk_subtrees, void *lhs_p)
{
switch (TREE_CODE (*tp))
{
+ case VAR_DEBUG_VALUE:
+ *walk_subtrees = 0;
+ break;
+
case GIMPLE_MODIFY_STMT:
/* Recurse manually here to track whether the use is in the
LHS of an assignment. */
diff --git a/gcc/tree-ssa-coalesce.c b/gcc/tree-ssa-coalesce.c
index ef1ebcab4a9..f682a9ff622 100644
--- a/gcc/tree-ssa-coalesce.c
+++ b/gcc/tree-ssa-coalesce.c
@@ -865,6 +865,8 @@ build_ssa_conflict_graph (tree_live_info_p liveinfo)
if (TREE_CODE (lhs) == SSA_NAME && TREE_CODE (rhs) == SSA_NAME)
live_track_clear_var (live, rhs);
}
+ else if (IS_DEBUG_STMT (stmt))
+ continue;
FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_DEF)
live_track_process_def (live, var, graph);
@@ -1027,6 +1029,9 @@ create_outofssa_var_map (coalesce_list_p cl, bitmap used_in_copy)
{
stmt = bsi_stmt (bsi);
+ if (IS_DEBUG_STMT (stmt))
+ continue;
+
/* Register USE and DEF operands in each statement. */
FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, (SSA_OP_DEF|SSA_OP_USE))
register_ssa_partition (map, var);
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index bc1700338d8..574e44a489b 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -317,6 +317,10 @@ mark_stmt_if_obviously_necessary (tree stmt, bool aggressive)
}
break;
+ case VAR_DEBUG_VALUE:
+ mark_stmt_necessary (stmt, false);
+ return;
+
case GOTO_EXPR:
gcc_assert (!simple_goto_p (stmt));
mark_stmt_necessary (stmt, true);
@@ -653,6 +657,15 @@ remove_dead_stmt (block_stmt_iterator *i, basic_block bb)
release_defs (t);
}
+/* Predicate used by check_and_update_debug_stmt. Return TRUE if the
+ T's definition is not about to be removed. T is assumed to be an
+ SSA_NAME. */
+
+static bool
+necessary_p (tree t)
+{
+ return NECESSARY (SSA_NAME_DEF_STMT (t));
+}
/* Eliminate unnecessary statements. Any instruction not marked as necessary
contributes nothing to the program, and can be deleted. */
@@ -691,8 +704,15 @@ eliminate_unnecessary_stmts (void)
}
else
{
- tree call = get_call_expr_in (t);
- if (call)
+ tree call;
+
+ if (TREE_CODE (t) == VAR_DEBUG_VALUE)
+ {
+ if (something_changed
+ && VAR_DEBUG_VALUE_VALUE (t) != VAR_DEBUG_VALUE_NOVALUE)
+ check_and_update_debug_stmt (t, necessary_p);
+ }
+ else if ((call = get_call_expr_in (t)))
{
tree name;
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 7bed1c292d8..53ca66e6041 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -2233,6 +2233,8 @@ propagate_rhs_into_lhs (tree stmt, tree lhs, tree rhs, bitmap interesting_names)
discard_stmt_changes (&use_stmt);
continue;
}
+ else if (IS_DEBUG_STMT (use_stmt))
+ check_and_update_debug_stmt (use_stmt, NULL);
/* From this point onward we are propagating into a
real statement. Folding may (or may not) be possible,
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 60e6ffa9e62..31cb70afd46 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -695,6 +695,7 @@ forward_propagate_addr_expr (tree name, tree rhs)
tree use_stmt;
bool all = true;
bool single_use_p = has_single_use (name);
+ bool debug = false;
FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
{
@@ -704,7 +705,10 @@ forward_propagate_addr_expr (tree name, tree rhs)
there is nothing we can do. */
if (TREE_CODE (use_stmt) != GIMPLE_MODIFY_STMT)
{
- all = false;
+ if (IS_DEBUG_STMT (use_stmt))
+ debug = true;
+ else
+ all = false;
continue;
}
@@ -738,6 +742,9 @@ forward_propagate_addr_expr (tree name, tree rhs)
}
}
+ if (all && debug)
+ adjust_debug_stmts_for_var_def_move (name, NULL, NULL);
+
return all;
}
diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c
index 4cf6620a759..a85da83a5e0 100644
--- a/gcc/tree-ssa-live.c
+++ b/gcc/tree-ssa-live.c
@@ -545,7 +545,8 @@ remove_unused_locals (void)
/* Walk the statements. */
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
- mark_all_vars_used (bsi_stmt_ptr (bsi));
+ if (TREE_CODE (bsi_stmt (bsi)) != VAR_DEBUG_VALUE)
+ mark_all_vars_used (bsi_stmt_ptr (bsi));
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
{
@@ -772,6 +773,8 @@ set_var_live_on_entry (tree ssa_name, tree_live_info_p live)
add_block = e->src;
}
}
+ else if (IS_DEBUG_STMT (use_stmt))
+ continue;
else
{
/* If its not defined in this block, its live on entry. */
diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c
index ff62c686c28..958c6797326 100644
--- a/gcc/tree-ssa-loop-ch.c
+++ b/gcc/tree-ssa-loop-ch.c
@@ -83,6 +83,9 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop,
if (TREE_CODE (last) == LABEL_EXPR)
continue;
+ if (IS_DEBUG_STMT (last))
+ continue;
+
if (get_call_expr_in (last))
return false;
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index d2ab41ce054..d2f624580b2 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -686,6 +686,7 @@ rewrite_bittest (block_stmt_iterator *bsi)
SET_USE (use, name);
bsi_insert_before (bsi, stmt1, BSI_SAME_STMT);
+ adjust_debug_stmts_for_move (bsi_stmt (*bsi), NULL, NULL);
bsi_replace (bsi, stmt2, true);
return stmt1;
@@ -852,6 +853,7 @@ move_computations_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED,
cost, level->num);
}
bsi_insert_on_edge (loop_preheader_edge (level), stmt);
+ adjust_debug_stmts_for_move (bsi_stmt (bsi), NULL, NULL);
bsi_remove (&bsi, false);
}
}
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index c8cefd418a1..7907fd69fae 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -1648,6 +1648,9 @@ find_interesting_uses_stmt (struct ivopts_data *data, tree stmt)
if (TREE_CODE (op) != SSA_NAME)
continue;
+ if (IS_DEBUG_STMT (USE_STMT (use_p)))
+ continue;
+
iv = get_iv (data, op);
if (!iv)
continue;
@@ -5196,7 +5199,24 @@ remove_unused_ivs (struct ivopts_data *data)
&& !info->inv_id
&& !info->iv->have_use_for
&& !info->preserve_biv)
- remove_statement (SSA_NAME_DEF_STMT (info->iv->ssa_name), true);
+ {
+ if (MAY_HAVE_DEBUG_STMTS)
+ {
+ tree stmt;
+ imm_use_iterator iter;
+
+ FOR_EACH_IMM_USE_STMT (stmt, iter, info->iv->ssa_name)
+ {
+ if (!IS_DEBUG_STMT (stmt))
+ continue;
+
+ /* ??? We can probably do better than this. */
+ VAR_DEBUG_VALUE_VALUE (stmt) = VAR_DEBUG_VALUE_NOVALUE;
+ update_stmt (stmt);
+ }
+ }
+ remove_statement (SSA_NAME_DEF_STMT (info->iv->ssa_name), true);
+ }
}
}
diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c
index 91aac3eb354..a4ec6577b42 100644
--- a/gcc/tree-ssa-loop-manip.c
+++ b/gcc/tree-ssa-loop-manip.c
@@ -271,6 +271,9 @@ find_uses_to_rename_stmt (tree stmt, bitmap *use_blocks, bitmap need_phis)
tree var;
basic_block bb = bb_for_stmt (stmt);
+ if (IS_DEBUG_STMT (stmt))
+ return;
+
FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_USES)
find_uses_to_rename_use (bb, var, use_blocks, need_phis);
}
@@ -422,6 +425,9 @@ check_loop_closed_ssa_stmt (basic_block bb, tree stmt)
ssa_op_iter iter;
tree var;
+ if (IS_DEBUG_STMT (stmt))
+ return;
+
FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_USES)
check_loop_closed_ssa_use (bb, var);
}
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index 3a944efa0b3..b798a85400d 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -126,6 +126,9 @@ static struct
clobbering sites like function calls or ASM_EXPRs. */
#define opf_implicit (1 << 2)
+/* Operand is a use only for purposes of debug information. */
+#define opf_debug_use (1 << 3)
+
/* Array for building all the def operands. */
static VEC(tree,heap) *build_defs;
@@ -2057,6 +2060,7 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
enum tree_code_class codeclass;
tree expr = *expr_p;
stmt_ann_t s_ann = stmt_ann (stmt);
+ int uflags = opf_use | (flags & opf_debug_use);
if (expr == NULL)
return;
@@ -2071,7 +2075,9 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
reference to it, but the fact that the statement takes its
address will be of interest to some passes (e.g. alias
resolution). */
- add_to_addressable_set (TREE_OPERAND (expr, 0), &s_ann->addresses_taken);
+ if (!(flags & opf_debug_use))
+ add_to_addressable_set (TREE_OPERAND (expr, 0),
+ &s_ann->addresses_taken);
/* If the address is invariant, there may be no interesting
variable references inside. */
@@ -2190,13 +2196,13 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
{
if (TREE_THIS_VOLATILE (TREE_OPERAND (expr, 1)))
s_ann->has_volatile_ops = true;
- get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_use);
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags);
}
else if (code == ARRAY_REF || code == ARRAY_RANGE_REF)
{
- get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_use);
- get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_use);
- get_expr_operands (stmt, &TREE_OPERAND (expr, 3), opf_use);
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags);
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags);
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 3), uflags);
}
return;
@@ -2205,7 +2211,7 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
case WITH_SIZE_EXPR:
/* WITH_SIZE_EXPR is a pass-through reference to its first argument,
and an rvalue reference to its second argument. */
- get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_use);
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags);
get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
return;
@@ -2215,15 +2221,21 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
case COND_EXPR:
case VEC_COND_EXPR:
- get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_use);
- get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_use);
- get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_use);
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 0), uflags);
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags);
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags);
return;
case GIMPLE_MODIFY_STMT:
get_modify_stmt_operands (stmt, expr);
return;
+ case VAR_DEBUG_VALUE:
+ if (VAR_DEBUG_VALUE_VALUE (stmt) != VAR_DEBUG_VALUE_NOVALUE)
+ get_expr_operands (stmt, &VAR_DEBUG_VALUE_VALUE (stmt),
+ opf_use | opf_debug_use);
+ return;
+
case CONSTRUCTOR:
{
/* General aggregate CONSTRUCTORs have been decomposed, but they
@@ -2234,7 +2246,7 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
for (idx = 0;
VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (expr), idx, ce);
idx++)
- get_expr_operands (stmt, &ce->value, opf_use);
+ get_expr_operands (stmt, &ce->value, uflags);
return;
}
@@ -2269,7 +2281,7 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
}
case CHANGE_DYNAMIC_TYPE_EXPR:
- get_expr_operands (stmt, &CHANGE_DYNAMIC_TYPE_LOCATION (expr), opf_use);
+ get_expr_operands (stmt, &CHANGE_DYNAMIC_TYPE_LOCATION (expr), uflags);
return;
case OMP_FOR:
@@ -2375,6 +2387,12 @@ parse_ssa_operands (tree stmt)
get_modify_stmt_operands (stmt, stmt);
break;
+ case VAR_DEBUG_VALUE:
+ if (VAR_DEBUG_VALUE_VALUE (stmt) != VAR_DEBUG_VALUE_NOVALUE)
+ get_expr_operands (stmt, &VAR_DEBUG_VALUE_VALUE (stmt),
+ opf_use | opf_debug_use);
+ return;
+
case COND_EXPR:
get_expr_operands (stmt, &COND_EXPR_COND (stmt), opf_use);
break;
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index a8376cf5885..4b356a668f2 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -387,7 +387,8 @@ empty_block_p (basic_block bb)
bsi = bsi_start (bb);
while (!bsi_end_p (bsi)
&& (TREE_CODE (bsi_stmt (bsi)) == LABEL_EXPR
- || IS_EMPTY_STMT (bsi_stmt (bsi))))
+ || IS_EMPTY_STMT (bsi_stmt (bsi))
+ || IS_DEBUG_STMT (bsi_stmt (bsi))))
bsi_next (&bsi);
if (!bsi_end_p (bsi))
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 33c44ee0d1b..0bde7aeb677 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -3553,7 +3553,6 @@ compute_avail (void)
}
continue;
}
-
else if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
&& !ann->has_volatile_ops
&& TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == SSA_NAME
@@ -3562,8 +3561,9 @@ compute_avail (void)
{
if (make_values_for_stmt (stmt, block))
continue;
-
}
+ else if (IS_DEBUG_STMT (stmt))
+ continue;
/* For any other statement that we don't recognize, simply
make the names generated by the statement available in
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index 17eec742138..490a83710ee 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -557,6 +557,9 @@ get_rhs (tree stmt)
else
return stmt;
+ case VAR_DEBUG_VALUE:
+ return VAR_DEBUG_VALUE_VALUE (stmt);
+
case COND_EXPR:
return COND_EXPR_COND (stmt);
case SWITCH_EXPR:
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 200088d7dd4..b0baf279b44 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -945,6 +945,7 @@ linearize_expr (tree stmt)
bsinow = bsi_for_stmt (stmt);
bsirhs = bsi_for_stmt (binrhs);
+ adjust_debug_stmts_for_move (binrhs, bb_for_stmt (stmt), &bsinow);
bsi_move_before (&bsirhs, &bsinow);
TREE_OPERAND (rhs, 1) = TREE_OPERAND (GIMPLE_STMT_OPERAND (binrhs, 1), 0);
@@ -1174,6 +1175,8 @@ linearize_expr_tree (VEC(operand_entry_t, heap) **ops, tree stmt)
rhscode, loop));
bsinow = bsi_for_stmt (stmt);
bsilhs = bsi_for_stmt (SSA_NAME_DEF_STMT (binlhs));
+ adjust_debug_stmts_for_move (SSA_NAME_DEF_STMT (binlhs),
+ bb_for_stmt (stmt), &bsinow);
bsi_move_before (&bsilhs, &bsinow);
linearize_expr_tree (ops, SSA_NAME_DEF_STMT (binlhs));
add_to_ops_vec (ops, binrhs);
diff --git a/gcc/tree-ssa-sink.c b/gcc/tree-ssa-sink.c
index cd57baa0d99..bb88bdfef29 100644
--- a/gcc/tree-ssa-sink.c
+++ b/gcc/tree-ssa-sink.c
@@ -119,6 +119,8 @@ all_immediate_uses_same_place (tree stmt)
{
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
{
+ if (IS_DEBUG_STMT (USE_STMT (use_p)))
+ continue;
if (firstuse == NULL_TREE)
firstuse = USE_STMT (use_p);
else
@@ -213,7 +215,7 @@ is_hidden_global_store (tree stmt)
/* Find the nearest common dominator of all of the immediate uses in IMM. */
static basic_block
-nearest_common_dominator_of_uses (tree stmt)
+nearest_common_dominator_of_uses (tree stmt, bool *debug_stmts)
{
bitmap blocks = BITMAP_ALLOC (NULL);
basic_block commondom;
@@ -238,6 +240,11 @@ nearest_common_dominator_of_uses (tree stmt)
useblock = PHI_ARG_EDGE (usestmt, idx)->src;
}
+ else if (IS_DEBUG_STMT (usestmt))
+ {
+ *debug_stmts = true;
+ continue;
+ }
else
{
useblock = bb_for_stmt (usestmt);
@@ -284,6 +291,9 @@ statement_sink_location (tree stmt, basic_block frombb, basic_block *tobb,
{
FOR_EACH_IMM_USE_FAST (one_use, imm_iter, def)
{
+ if (IS_DEBUG_STMT (USE_STMT (one_use)))
+ continue;
+
break;
}
if (one_use != NULL_USE_OPERAND_P)
@@ -349,7 +359,9 @@ statement_sink_location (tree stmt, basic_block frombb, basic_block *tobb,
that is where insertion would have to take place. */
if (!all_immediate_uses_same_place (stmt))
{
- basic_block commondom = nearest_common_dominator_of_uses (stmt);
+ bool debug_stmts = false;
+ basic_block commondom = nearest_common_dominator_of_uses (stmt,
+ &debug_stmts);
if (commondom == frombb)
return false;
@@ -378,8 +390,13 @@ statement_sink_location (tree stmt, basic_block frombb, basic_block *tobb,
fprintf (dump_file, "Common dominator of all uses is %d\n",
commondom->index);
}
+
*tobb = commondom;
*tobsi = bsi_after_labels (commondom);
+
+ if (debug_stmts)
+ adjust_debug_stmts_for_move (stmt, *tobb, tobsi);
+
return true;
}
@@ -392,6 +409,9 @@ statement_sink_location (tree stmt, basic_block frombb, basic_block *tobb,
return false;
*tobb = sinkbb;
*tobsi = bsi_for_stmt (use);
+
+ adjust_debug_stmts_for_move (stmt, *tobb, tobsi);
+
return true;
}
@@ -421,6 +441,8 @@ statement_sink_location (tree stmt, basic_block frombb, basic_block *tobb,
*tobb = sinkbb;
*tobsi = bsi_after_labels (sinkbb);
+ adjust_debug_stmts_for_move (stmt, *tobb, tobsi);
+
return true;
}
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index e2019f5e3f2..78191fcd3ba 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -5373,7 +5373,8 @@ compute_points_to_sets (struct alias_info *ai)
addresses, pointer dereferences for loads and stores.
This is used when creating name tags and alias
sets. */
- update_alias_info (stmt, ai);
+ if (!IS_DEBUG_STMT (stmt))
+ update_alias_info (stmt, ai);
/* The information in CHANGE_DYNAMIC_TYPE_EXPR nodes has now
been captured, and we can remove them. */
diff --git a/gcc/tree-ssa-ter.c b/gcc/tree-ssa-ter.c
index f0fef24aa4a..27fbaad9eb9 100644
--- a/gcc/tree-ssa-ter.c
+++ b/gcc/tree-ssa-ter.c
@@ -562,6 +562,10 @@ find_replaceable_in_bb (temp_expr_table_p tab, basic_block bb)
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
stmt = bsi_stmt (bsi);
+
+ if (IS_DEBUG_STMT (stmt))
+ continue;
+
ann = stmt_ann (stmt);
stmt_replaceable = is_replaceable_p (stmt);
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 9e7dd6eed56..3235ebcbcf0 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -230,7 +230,8 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
stmt = bsi_stmt (bsi);
/* Ignore empty statements and labels. */
- if (IS_EMPTY_STMT (stmt) || TREE_CODE (stmt) == LABEL_EXPR)
+ if (IS_EMPTY_STMT (stmt) || IS_DEBUG_STMT (stmt)
+ || TREE_CODE (stmt) == LABEL_EXPR)
continue;
/* If the statement has volatile operands, then we assume we
diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c
index 1d5500fe018..560249a1483 100644
--- a/gcc/tree-ssa-threadupdate.c
+++ b/gcc/tree-ssa-threadupdate.c
@@ -469,7 +469,8 @@ redirection_block_p (basic_block bb)
bsi = bsi_start (bb);
while (!bsi_end_p (bsi)
&& (TREE_CODE (bsi_stmt (bsi)) == LABEL_EXPR
- || IS_EMPTY_STMT (bsi_stmt (bsi))))
+ || IS_EMPTY_STMT (bsi_stmt (bsi))
+ || IS_DEBUG_STMT (bsi_stmt (bsi))))
bsi_next (&bsi);
/* Check if this is an empty block. */
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 9723afb0eec..8e481494402 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -699,6 +699,9 @@ verify_ssa (bool check_modified_stmt)
goto err;
}
}
+ else if (TREE_CODE (stmt) == VAR_DEBUG_VALUE
+ && VAR_DEBUG_VALUE_VALUE (stmt) == VAR_DEBUG_VALUE_NOVALUE)
+ continue;
FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_ALL_VIRTUALS)
{
@@ -1316,6 +1319,10 @@ execute_early_warn_uninitialized (void)
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
tree context = bsi_stmt (bsi);
+
+ if (TREE_CODE (context) == VAR_DEBUG_VALUE)
+ continue;
+
walk_tree (bsi_stmt_ptr (bsi), warn_uninitialized_var,
context, NULL);
}
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 956dd00206d..3f145a9db1d 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -203,6 +203,9 @@ release_ssa_name (tree var)
int saved_ssa_name_version = SSA_NAME_VERSION (var);
use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var));
+ if (MAY_HAVE_DEBUG_STMTS)
+ adjust_debug_stmts_for_var_def_move (var, NULL, NULL);
+
#ifdef ENABLE_CHECKING
verify_imm_links (stderr, var);
#endif
diff --git a/gcc/tree-stdarg.c b/gcc/tree-stdarg.c
index 168bd2f1564..6a175c73378 100644
--- a/gcc/tree-stdarg.c
+++ b/gcc/tree-stdarg.c
@@ -850,6 +850,8 @@ execute_optimize_stdarg (void)
continue;
}
}
+ else if (IS_DEBUG_STMT (stmt))
+ continue;
/* All other uses of va_list are either va_copy (that is not handled
in this optimization), taking address of va_list variable or
diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c
index bd3da886668..7dafa56e9a8 100644
--- a/gcc/tree-tailcall.c
+++ b/gcc/tree-tailcall.c
@@ -391,7 +391,7 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
stmt = bsi_stmt (bsi);
/* Ignore labels. */
- if (TREE_CODE (stmt) == LABEL_EXPR)
+ if (TREE_CODE (stmt) == LABEL_EXPR || IS_DEBUG_STMT (stmt))
continue;
/* Check for a call. */
@@ -495,6 +495,9 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
if (TREE_CODE (stmt) == RETURN_EXPR)
break;
+ if (IS_DEBUG_STMT (stmt))
+ continue;
+
if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
return;
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index dfb28203948..b8e0d5256aa 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -4067,6 +4067,9 @@ find_assert_locations (basic_block bb)
stmt = bsi_stmt (si);
+ if (IS_DEBUG_STMT (stmt))
+ continue;
+
/* See if we can derive an assertion for any of STMT's operands. */
FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_USE)
{
diff --git a/gcc/tree.c b/gcc/tree.c
index 88ec29e13e3..79b4e58f5fe 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -3160,6 +3160,21 @@ build_gimple_modify_stmt_stat (tree arg0, tree arg1 MEM_STAT_DECL)
return t;
}
+/* Build a VAR_DEBUG_VALUE node. This tree code doesn't have a
+ type, so we can't use build2 (a.k.a. build2_stat). */
+
+tree
+build_var_debug_value_stat (tree arg0, tree arg1 MEM_STAT_DECL)
+{
+ tree t;
+
+ t = make_node_stat (VAR_DEBUG_VALUE PASS_MEM_STAT);
+ /* ?? We don't care about setting flags for tuples... */
+ VAR_DEBUG_VALUE_SET_VAR (t, arg0);
+ VAR_DEBUG_VALUE_VALUE (t) = arg1;
+ return t;
+}
+
tree
build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
tree arg2 MEM_STAT_DECL)
@@ -8647,7 +8662,7 @@ empty_body_p (tree stmt)
tree_stmt_iterator i;
tree body;
- if (IS_EMPTY_STMT (stmt))
+ if (IS_EMPTY_STMT (stmt) || IS_DEBUG_STMT (stmt))
return true;
else if (TREE_CODE (stmt) == BIND_EXPR)
body = BIND_EXPR_BODY (stmt);
diff --git a/gcc/tree.def b/gcc/tree.def
index b9c2be1648c..7d7904c597e 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -1110,6 +1110,10 @@ DEFTREECODE (VEC_RSHIFT_EXPR, "vec_rshift_expr", tcc_binary, 2)
/* Assignment expression. Operand 0 is the what to set; 1, the new value. */
DEFTREECODE (GIMPLE_MODIFY_STMT, "gimple_modify_stmt", tcc_gimple_stmt, 2)
+/* Debug annotation. Operand 0 is a user variable; 1 is an expression
+ with its value, for purposes of debug information. */
+DEFTREECODE (VAR_DEBUG_VALUE, "var_debug_value", tcc_gimple_stmt, 2)
+
/* Widening vector multiplication.
The two operands are vectors with N elements of size S. Multiplying the
elements of the two vectors will result in N products of size 2*S.
diff --git a/gcc/tree.h b/gcc/tree.h
index 55b31912370..62e5589731c 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -829,6 +829,32 @@ enum tree_node_structure_enum {
__FILE__, __LINE__, __FUNCTION__); \
&__t->gstmt.operands[__i]; }))
+/* Set the variable set by the VAR_DEBUG_VALUE stmt. */
+#define VAR_DEBUG_VALUE_SET_VAR(T, V) __extension__ \
+ ({const tree __t = VAR_DEBUG_VALUE_CHECK (T); \
+ if (0 >= TREE_OPERAND_LENGTH (__t)) \
+ tree_operand_check_failed (0, __t, \
+ __FILE__, __LINE__, __FUNCTION__); \
+ __t->gstmt.operands[0] = (V); })
+
+/* Rvalue for the variable set by the VAR_DEBUG_VALUE stmt. */
+#define VAR_DEBUG_VALUE_VAR(T) __extension__ \
+ ({const tree __t = VAR_DEBUG_VALUE_CHECK (T); \
+ tree __var; \
+ if (0 >= TREE_OPERAND_LENGTH (__t)) \
+ tree_operand_check_failed (0, __t, \
+ __FILE__, __LINE__, __FUNCTION__); \
+ __var = __t->gstmt.operands[0]; \
+ __var; })
+
+/* Lvalue for the value of the variable. */
+#define VAR_DEBUG_VALUE_VALUE(T) __extension__ \
+(*({const tree __t = VAR_DEBUG_VALUE_CHECK (T); \
+ if (1 >= TREE_OPERAND_LENGTH (__t)) \
+ tree_operand_check_failed (1, __t, \
+ __FILE__, __LINE__, __FUNCTION__); \
+ &__t->gstmt.operands[1]; }))
+
#define TREE_RTL_OPERAND_CHECK(T, CODE, I) __extension__ \
(*(rtx *) \
({__typeof (T) const __t = (T); \
@@ -926,6 +952,9 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
#define TREE_OPERAND_CHECK(T, I) ((T)->exp.operands[I])
#define TREE_OPERAND_CHECK_CODE(T, CODE, I) ((T)->exp.operands[I])
#define GIMPLE_STMT_OPERAND_CHECK(T, I) ((T)->gstmt.operands[I])
+#define VAR_DEBUG_VALUE_SET_VAR(T, V) ((T)->gstmt.operands[0] = (V))
+#define VAR_DEBUG_VALUE_VAR(T) ((tree)(T)->gstmt.operands[0])
+#define VAR_DEBUG_VALUE_VALUE(T) ((T)->gstmt.operands[1])
#define TREE_RTL_OPERAND_CHECK(T, CODE, I) (*(rtx *) &((T)->exp.operands[I]))
#define PHI_NODE_ELT_CHECK(T, i) ((T)->phi.a[i])
#define OMP_CLAUSE_ELT_CHECK(T, i) ((T)->omp_clause.ops[i])
@@ -1572,6 +1601,12 @@ struct tree_constructor GTY(())
&& VOID_TYPE_P (TREE_TYPE (NODE)) \
&& integer_zerop (TREE_OPERAND (NODE, 0)))
+/* Nonzero if NODE is a debug statement (VAR_DEBUG_VALUE). */
+#define IS_DEBUG_STMT(NODE) (TREE_CODE (NODE) == VAR_DEBUG_VALUE)
+
+/* Nonzero if IS_DEBUG_STMT may possibly. */
+#define MAY_HAVE_DEBUG_STMTS (flag_var_tracking_assignments)
+
/* In ordinary expression nodes. */
#define TREE_OPERAND_LENGTH(NODE) tree_operand_length (NODE)
#define TREE_OPERAND(NODE, I) TREE_OPERAND_CHECK (NODE, I)
@@ -1589,6 +1624,10 @@ struct tree_constructor GTY(())
#define GIMPLE_STMT_LOCUS(NODE) (GIMPLE_STMT_CHECK (NODE)->gstmt.locus)
#define GIMPLE_STMT_BLOCK(NODE) (GIMPLE_STMT_CHECK (NODE)->gstmt.block)
+/* The second operand of a VAR_DEBUG_VALUE when the value was
+ optimized away. */
+#define VAR_DEBUG_VALUE_NOVALUE NULL_TREE /* error_mark_node */
+
/* In a LOOP_EXPR node. */
#define LOOP_EXPR_BODY(NODE) TREE_OPERAND_CHECK_CODE (NODE, LOOP_EXPR, 0)
@@ -3950,6 +3989,10 @@ extern tree build_gimple_modify_stmt_stat (tree, tree MEM_STAT_DECL);
#define build_gimple_modify_stmt(t1,t2) \
build_gimple_modify_stmt_stat (t1,t2 MEM_STAT_INFO)
+extern tree build_var_debug_value_stat (tree, tree MEM_STAT_DECL);
+#define build_var_debug_value(t1,t2) \
+ build_var_debug_value_stat (t1,t2 MEM_STAT_INFO)
+
extern tree build_int_cst (tree, HOST_WIDE_INT);
extern tree build_int_cst_type (tree, HOST_WIDE_INT);
extern tree build_int_cstu (tree, unsigned HOST_WIDE_INT);
@@ -5351,4 +5394,8 @@ more_const_call_expr_args_p (const const_call_expr_arg_iterator *iter)
for ((arg) = first_const_call_expr_arg ((call), &(iter)); (arg); \
(arg) = next_const_call_expr_arg (&(iter)))
+/* Determines whether the given TREE is subject to debug tracking. */
+
+bool var_debug_value_for_decl (tree);
+
#endif /* GCC_TREE_H */