aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>2009-07-12 11:16:25 +0000
committeraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>2009-07-12 11:16:25 +0000
commit7c0af8e6e7b8380b2437f6e880e6259e049ffd7a (patch)
tree72a6ef9f532354981e41d06a4ae811b2d1f77105
parent68764e33c09ca351da16a6667f5d84c54051088b (diff)
* cfgexpand.c (expand_debug_expr): Enclose CONST_STRINGs in MEMs.var-tracking-assignments-merge-150235-before
(expand_debug_locations): Use NULL trees for no bind value. (expand_gimple_basic_block): Likewise. * gimple.h (GIMPLE_DEBUG_BIND): New. Replaces all uses of VAR_DEBUG_VALUE tree code. (GIMPLE_DEBUG_BIND_NOVALUE): New. (gimple_debug_bind_reset_value): New. Replace all assignments to VAR_DEBUG_VALUE_VALUE from VAR_DEBUG_VALUE_NOVALUE with it. (gimple_debug_bind_has_value_p): New. Replace all compares of VAR_DEBUG_VALUE_VALUE and VAR_DEBUG_VALUE_NOVALUE with it. (gsi_next_nondebug, gsi_prev_nondebug): Embrace do/while body. * tree-if-conv.c (tree_if_convert_stmt): Adjust. * tree-inline.c: Adjust. (copy_debug_stmt, copy_debug_stmts): Add comments. (insert_init_debug_bind): Use the var returned by target_for_debug_bind, renamed from... * tree-into-ssa.c (var_debug_value_for_decl): ... this. (insert_phi_nodes_for, rewrite_stmt): Likewise. (check_and_update_debug_stmt_1): Removed. (check_and_update_debug_stmt): Removed. Drop all callers. (maybe_replace_use_in_debug_insn): Renamed to... (maybe_replace_use_in_debug_stmt): ... this. Adjust all callers. Don't keep non-current SSA names. Don't assume default DEFs. (rewrite_update_stmt): Rearrange logic. (adjust_debug_stmts_for_var_def_move, adjust_debug_stmts_for_move): Moved to... * tree-ssa.c (propagate_var_def_into_debug_stmts, propagate_defs_into_debug_stmts): ... this. (target_for_debug_bind): Moved and renamed from var_debug_value_for_decl. Support DECL_HAS_VALUE_EXPR_P rather than ABSTRACT_ORIGINs. (verify_ssa): Adjust. * tree-parloops.c: Adjust. (separate_decls_in_region): Add comments. Drop unnecessary assertion check. * tree-ssa-dce.c (necessary_p): Remove. (eliminate_unnecessary_stmts): Iterate backwards. Adjust. * tree-ssa-loop-ivopts.c: Adjust. * tree.h (VAR_DEBUG_VALUE_NOVALUE): Removed. (VAR_DEBUG_VALUE_SET_VAR): Removed. Changed all callers to use gimple_debug_bind_set_var. (VAR_DEBUG_VALUE_VAR): Removed. Changed all callers to use gimple_debug_bind_get_var. (VAR_DEBUG_VALUE_VALUE): Removed. Changed all callers to use gimple_debug_bind_get_value, gimple_debug_bind_get_value_ptr, gimple_debug_bind_set_value, gimple_debug_bind_reset_value or gimple_debug_bind_has_value_p. (target_for_debug_bind): Declare. (var_debug_value_for_decl): Remove. * expr.c (expand_expr_real_1): Drop VAR_DEBUG_VALUE handling. * gimple-pretty-print.c (dump_gimple_debug): Adjust. * gimple.c (gimple_build_wtih_ops_stat): Take unsigned subcode. (gimple_build_assign_with_ops_stat): Type-cast subcode. (gimple_build_debug_bind_stat): Document stmt parameter. Use GIMPLE_DEBUG_BIND. * tree-flow.h: Rename and remove declarations. * tree-ssa-operands.c Adjust. (opf_debug_use): Removed. Test is_gimple_debug instead. (get_indirect_ref_operands): Pass down opf_no_vops. (get_expr_operands): Drop VAR_DEBUG_VALUE handling. * tree.def: Drop VAR_DEBUG_VALUE. * var-tracking.c: Adjust. * tree-cfg.c: Adjust. (remove_bb): Walk stmts backwards. (remove_edge_and_dominated_blocks): Visit blocks backwards. * tree-ssa-dom.c (propagate_rhs_into_lhs): Simplify handling of debug stmts. * tree-ssa-forwprop.c, tree-ssa-loop-im.c: Adjust. * tree-ssa-reassoc.c, tree-ssa-sink.c, tree-ssanames.c: Adjust. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/var-tracking-assignments-branch@149527 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog.vta72
-rw-r--r--gcc/cfgexpand.c13
-rw-r--r--gcc/expr.c4
-rw-r--r--gcc/gimple-pretty-print.c2
-rw-r--r--gcc/gimple.c9
-rw-r--r--gcc/gimple.h42
-rw-r--r--gcc/tree-cfg.c24
-rw-r--r--gcc/tree-flow.h9
-rw-r--r--gcc/tree-if-conv.c4
-rw-r--r--gcc/tree-inline.c33
-rw-r--r--gcc/tree-into-ssa.c328
-rw-r--r--gcc/tree-parloops.c10
-rw-r--r--gcc/tree-ssa-dce.c59
-rw-r--r--gcc/tree-ssa-dom.c9
-rw-r--r--gcc/tree-ssa-forwprop.c2
-rw-r--r--gcc/tree-ssa-loop-im.c4
-rw-r--r--gcc/tree-ssa-loop-ivopts.c2
-rw-r--r--gcc/tree-ssa-operands.c26
-rw-r--r--gcc/tree-ssa-reassoc.c4
-rw-r--r--gcc/tree-ssa-sink.c6
-rw-r--r--gcc/tree-ssa.c144
-rw-r--r--gcc/tree-ssanames.c2
-rw-r--r--gcc/tree.def5
-rw-r--r--gcc/tree.h15
-rw-r--r--gcc/var-tracking.c8
25 files changed, 442 insertions, 394 deletions
diff --git a/gcc/ChangeLog.vta b/gcc/ChangeLog.vta
index f5cc5b6600e..94338b384cb 100644
--- a/gcc/ChangeLog.vta
+++ b/gcc/ChangeLog.vta
@@ -1,3 +1,75 @@
+2009-07-12 Alexandre Oliva <aoliva@redhat.com>
+
+ * cfgexpand.c (expand_debug_expr): Enclose CONST_STRINGs in MEMs.
+ (expand_debug_locations): Use NULL trees for no bind value.
+ (expand_gimple_basic_block): Likewise.
+ * gimple.h (GIMPLE_DEBUG_BIND): New. Replaces all uses of
+ VAR_DEBUG_VALUE tree code.
+ (GIMPLE_DEBUG_BIND_NOVALUE): New.
+ (gimple_debug_bind_reset_value): New. Replace all assignments to
+ VAR_DEBUG_VALUE_VALUE from VAR_DEBUG_VALUE_NOVALUE with it.
+ (gimple_debug_bind_has_value_p): New. Replace all compares of
+ VAR_DEBUG_VALUE_VALUE and VAR_DEBUG_VALUE_NOVALUE with it.
+ (gsi_next_nondebug, gsi_prev_nondebug): Embrace do/while body.
+ * tree-if-conv.c (tree_if_convert_stmt): Adjust.
+ * tree-inline.c: Adjust.
+ (copy_debug_stmt, copy_debug_stmts): Add comments.
+ (insert_init_debug_bind): Use the var returned by
+ target_for_debug_bind, renamed from...
+ * tree-into-ssa.c (var_debug_value_for_decl): ... this.
+ (insert_phi_nodes_for, rewrite_stmt): Likewise.
+ (check_and_update_debug_stmt_1): Removed.
+ (check_and_update_debug_stmt): Removed. Drop all callers.
+ (maybe_replace_use_in_debug_insn): Renamed to...
+ (maybe_replace_use_in_debug_stmt): ... this. Adjust all callers.
+ Don't keep non-current SSA names. Don't assume default DEFs.
+ (rewrite_update_stmt): Rearrange logic.
+ (adjust_debug_stmts_for_var_def_move,
+ adjust_debug_stmts_for_move): Moved to...
+ * tree-ssa.c (propagate_var_def_into_debug_stmts,
+ propagate_defs_into_debug_stmts): ... this.
+ (target_for_debug_bind): Moved and renamed from
+ var_debug_value_for_decl. Support DECL_HAS_VALUE_EXPR_P rather
+ than ABSTRACT_ORIGINs.
+ (verify_ssa): Adjust.
+ * tree-parloops.c: Adjust.
+ (separate_decls_in_region): Add comments. Drop unnecessary
+ assertion check.
+ * tree-ssa-dce.c (necessary_p): Remove.
+ (eliminate_unnecessary_stmts): Iterate backwards. Adjust.
+ * tree-ssa-loop-ivopts.c: Adjust.
+ * tree.h (VAR_DEBUG_VALUE_NOVALUE): Removed.
+ (VAR_DEBUG_VALUE_SET_VAR): Removed. Changed all callers to use
+ gimple_debug_bind_set_var.
+ (VAR_DEBUG_VALUE_VAR): Removed. Changed all callers to use
+ gimple_debug_bind_get_var.
+ (VAR_DEBUG_VALUE_VALUE): Removed. Changed all callers to use
+ gimple_debug_bind_get_value, gimple_debug_bind_get_value_ptr,
+ gimple_debug_bind_set_value, gimple_debug_bind_reset_value or
+ gimple_debug_bind_has_value_p.
+ (target_for_debug_bind): Declare.
+ (var_debug_value_for_decl): Remove.
+ * expr.c (expand_expr_real_1): Drop VAR_DEBUG_VALUE handling.
+ * gimple-pretty-print.c (dump_gimple_debug): Adjust.
+ * gimple.c (gimple_build_wtih_ops_stat): Take unsigned subcode.
+ (gimple_build_assign_with_ops_stat): Type-cast subcode.
+ (gimple_build_debug_bind_stat): Document stmt parameter.
+ Use GIMPLE_DEBUG_BIND.
+ * tree-flow.h: Rename and remove declarations.
+ * tree-ssa-operands.c Adjust.
+ (opf_debug_use): Removed. Test is_gimple_debug instead.
+ (get_indirect_ref_operands): Pass down opf_no_vops.
+ (get_expr_operands): Drop VAR_DEBUG_VALUE handling.
+ * tree.def: Drop VAR_DEBUG_VALUE.
+ * var-tracking.c: Adjust.
+ * tree-cfg.c: Adjust.
+ (remove_bb): Walk stmts backwards.
+ (remove_edge_and_dominated_blocks): Visit blocks backwards.
+ * tree-ssa-dom.c (propagate_rhs_into_lhs): Simplify handling of
+ debug stmts.
+ * tree-ssa-forwprop.c, tree-ssa-loop-im.c: Adjust.
+ * tree-ssa-reassoc.c, tree-ssa-sink.c, tree-ssanames.c: Adjust.
+
2009-07-08 Jakub Jelinek <jakub@redhat.com>
* dwarf2out.c (add_location_or_const_value_attribute): Add
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 31f5c01a5f5..ff3933823ff 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -2194,6 +2194,8 @@ expand_debug_expr (tree exp)
if (!lookup_constant_def (exp))
{
op0 = gen_rtx_CONST_STRING (Pmode, TREE_STRING_POINTER (exp));
+ op0 = gen_rtx_MEM (BLKmode, op0);
+ set_mem_attributes (op0, exp, 0);
return op0;
}
/* Fall through... */
@@ -2751,7 +2753,7 @@ expand_debug_locations (void)
rtx val;
enum machine_mode mode;
- if (value == VAR_DEBUG_VALUE_NOVALUE)
+ if (value == NULL_TREE)
val = NULL_RTX;
else
{
@@ -2883,11 +2885,16 @@ expand_gimple_basic_block (basic_block bb)
for (;;)
{
- tree var = VAR_DEBUG_VALUE_VAR (stmt);
- tree value = VAR_DEBUG_VALUE_VALUE (stmt);
+ tree var = gimple_debug_bind_get_var (stmt);
+ tree value;
rtx val;
enum machine_mode mode;
+ if (gimple_debug_bind_has_value_p (stmt))
+ value = gimple_debug_bind_get_value (stmt);
+ else
+ value = NULL_TREE;
+
last = get_last_insn ();
set_curr_insn_source_location (gimple_location (stmt));
diff --git a/gcc/expr.c b/gcc/expr.c
index 4b32ae0b481..fbac5235a29 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -9261,10 +9261,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
return const0_rtx;
}
- case VAR_DEBUG_VALUE:
- /* Expanded by expand_gimple_basic_block only. */
- gcc_unreachable ();
-
case RETURN_EXPR:
if (!TREE_OPERAND (exp, 0))
expand_null_return ();
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 8d317e50199..7ef8d68cb12 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -789,7 +789,7 @@ dump_gimple_debug (pretty_printer *buffer, gimple gs, int spc, int flags)
{
switch (gs->gsbase.subcode)
{
- case VAR_DEBUG_VALUE:
+ case GIMPLE_DEBUG_BIND:
if (flags & TDF_RAW)
dump_gimple_fmt (buffer, spc, flags, "%G BIND <%T, %T>", gs,
gimple_debug_bind_get_var (gs),
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 02e283c9562..1e855ba8b85 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -254,7 +254,7 @@ gimple_set_subcode (gimple g, unsigned subcode)
gimple_build_with_ops_stat (c, s, n MEM_STAT_INFO)
static gimple
-gimple_build_with_ops_stat (enum gimple_code code, enum tree_code subcode,
+gimple_build_with_ops_stat (enum gimple_code code, unsigned subcode,
unsigned num_ops MEM_STAT_DECL)
{
gimple s = gimple_alloc_stat (code, num_ops PASS_MEM_STAT);
@@ -427,7 +427,7 @@ gimple_build_assign_with_ops_stat (enum tree_code subcode, tree lhs, tree op1,
code). */
num_ops = get_gimple_rhs_num_ops (subcode) + 1;
- p = gimple_build_with_ops_stat (GIMPLE_ASSIGN, subcode, num_ops
+ p = gimple_build_with_ops_stat (GIMPLE_ASSIGN, (unsigned)subcode, num_ops
PASS_MEM_STAT);
gimple_assign_set_lhs (p, lhs);
gimple_assign_set_rhs1 (p, op1);
@@ -832,12 +832,13 @@ gimple_build_switch_vec (tree index, tree default_label, VEC(tree, heap) *args)
/* Build a new GIMPLE_DEBUG_BIND statement.
- VAR is bound to VALUE. */
+ VAR is bound to VALUE; block and location are taken from STMT. */
gimple
gimple_build_debug_bind_stat (tree var, tree value, gimple stmt MEM_STAT_DECL)
{
- gimple p = gimple_build_with_ops_stat (GIMPLE_DEBUG, VAR_DEBUG_VALUE, 2
+ gimple p = gimple_build_with_ops_stat (GIMPLE_DEBUG,
+ (unsigned)GIMPLE_DEBUG_BIND, 2
PASS_MEM_STAT);
gimple_debug_bind_set_var (p, var);
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 34518ab138b..6d30941cd66 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -114,7 +114,9 @@ enum gf_mask {
GF_OMP_RETURN_NOWAIT = 1 << 0,
GF_OMP_SECTION_LAST = 1 << 0,
- GF_PREDICT_TAKEN = 1 << 15
+ GF_PREDICT_TAKEN = 1 << 15,
+
+ GIMPLE_DEBUG_BIND = 0
};
/* Masks for selecting a pass local flag (PLF) to work on. These
@@ -3177,7 +3179,7 @@ static inline bool
gimple_debug_bind_p (const_gimple s)
{
if (is_gimple_debug (s))
- return s->gsbase.subcode == VAR_DEBUG_VALUE;
+ return s->gsbase.subcode == GIMPLE_DEBUG_BIND;
return false;
}
@@ -3235,6 +3237,34 @@ gimple_debug_bind_set_value (gimple dbg, tree value)
gimple_set_op (dbg, 1, value);
}
+/* The second operand of a GIMPLE_DEBUG_BIND, when the value was
+ optimized away. */
+#define GIMPLE_DEBUG_BIND_NOVALUE NULL_TREE /* error_mark_node */
+
+/* Remove the value bound to the variable in a GIMPLE_DEBUG bind
+ statement. */
+
+static inline void
+gimple_debug_bind_reset_value (gimple dbg)
+{
+ GIMPLE_CHECK (dbg, GIMPLE_DEBUG);
+ gcc_assert (gimple_debug_bind_p (dbg));
+ gimple_set_op (dbg, 1, GIMPLE_DEBUG_BIND_NOVALUE);
+}
+
+/* Return true if the GIMPLE_DEBUG bind statement is bound to a
+ value. */
+
+static inline bool
+gimple_debug_bind_has_value_p (gimple dbg)
+{
+ GIMPLE_CHECK (dbg, GIMPLE_DEBUG);
+ gcc_assert (gimple_debug_bind_p (dbg));
+ return gimple_op (dbg, 1) != GIMPLE_DEBUG_BIND_NOVALUE;
+}
+
+#undef GIMPLE_DEBUG_BIND_NOVALUE
+
/* Return the body for the OMP statement GS. */
static inline gimple_seq
@@ -4390,7 +4420,9 @@ static inline void
gsi_next_nondebug (gimple_stmt_iterator *i)
{
do
- gsi_next (i);
+ {
+ gsi_next (i);
+ }
while (!gsi_end_p (*i) && is_gimple_debug (gsi_stmt (*i)));
}
@@ -4400,7 +4432,9 @@ static inline void
gsi_prev_nondebug (gimple_stmt_iterator *i)
{
do
- gsi_prev (i);
+ {
+ gsi_prev (i);
+ }
while (!gsi_end_p (*i) && is_gimple_debug (gsi_stmt (*i)));
}
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 6e86ba539a2..19fc262310e 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -2258,7 +2258,11 @@ remove_bb (basic_block bb)
/* Remove all the instructions in the block. */
if (bb_seq (bb) != NULL)
{
- for (i = gsi_start_bb (bb); !gsi_end_p (i);)
+ /* Walk backwards so as to get a chance to substitute all
+ released DEFs into debug stmts. See
+ eliminate_unnecessary_stmts() in tree-ssa-dce.c for more
+ details. */
+ for (i = gsi_last_bb (bb); !gsi_end_p (i);)
{
gimple stmt = gsi_stmt (i);
if (gimple_code (stmt) == GIMPLE_LABEL
@@ -2294,6 +2298,11 @@ remove_bb (basic_block bb)
gsi_remove (&i, true);
}
+ if (gsi_end_p (i))
+ i = gsi_last_bb (bb);
+ else
+ gsi_prev (&i);
+
/* Don't warn for removed gotos. Gotos are often removed due to
jump threading, thus resulting in bogus warnings. Not great,
since this way we lose warnings for gotos in the original
@@ -4292,10 +4301,7 @@ verify_stmt (gimple_stmt_iterator *gsi)
}
if (is_gimple_debug (stmt))
- {
- check_and_update_debug_stmt (stmt, NULL);
- return false;
- }
+ return false;
memset (&wi, 0, sizeof (wi));
addr = walk_gimple_op (gsi_stmt (*gsi), verify_expr, &wi);
@@ -6950,8 +6956,12 @@ remove_edge_and_dominated_blocks (edge e)
remove_edge (e);
else
{
- for (i = 0; VEC_iterate (basic_block, bbs_to_remove, i, bb); i++)
- delete_basic_block (bb);
+ /* Walk backwards so as to get a chance to substitute all
+ released DEFs into debug stmts. See
+ eliminate_unnecessary_stmts() in tree-ssa-dce.c for more
+ details. */
+ for (i = VEC_length (basic_block, bbs_to_remove); i-- > 0; )
+ delete_basic_block (VEC_index (basic_block, bbs_to_remove, i));
}
/* Update the dominance information. The immediate dominator may change only
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index 8835ccc3259..520e4038e44 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -629,6 +629,10 @@ typedef bool (*walk_use_def_chains_fn) (tree, gimple, void *);
extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
+void propagate_defs_into_debug_stmts (gimple, basic_block,
+ const gimple_stmt_iterator *);
+void propagate_var_def_into_debug_stmts (tree, basic_block,
+ const gimple_stmt_iterator *);
/* In tree-into-ssa.c */
void update_ssa (unsigned);
@@ -645,11 +649,6 @@ 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 (gimple, basic_block,
- const gimple_stmt_iterator *);
-void adjust_debug_stmts_for_var_def_move (tree, basic_block,
- const gimple_stmt_iterator *);
-void check_and_update_debug_stmt (gimple, bool (*)(tree));
/* In tree-ssanames.c */
extern void init_ssanames (struct function *, int);
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 792db72fa10..d82e0b06792 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -240,10 +240,10 @@ tree_if_convert_stmt (struct loop * loop, gimple t, tree cond,
break;
case GIMPLE_DEBUG:
- /* ??? Should there be conditional VAR_DEBUG_VALUEs? */
+ /* ??? Should there be conditional GIMPLE_DEBUG_BINDs? */
if (gimple_debug_bind_p (gsi_stmt (*gsi)))
{
- VAR_DEBUG_VALUE_VALUE (gsi_stmt (*gsi)) = VAR_DEBUG_VALUE_NOVALUE;
+ gimple_debug_bind_reset_value (gsi_stmt (*gsi));
update_stmt (gsi_stmt (*gsi));
}
break;
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 681ab081e07..66eb1de83f0 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -159,7 +159,7 @@ insert_debug_decl_map (copy_body_data *id, tree key, tree value)
if (!MAY_HAVE_DEBUG_STMTS)
return;
- if (!var_debug_value_for_decl (key))
+ if (!target_for_debug_bind (key))
return;
gcc_assert (TREE_CODE (key) == PARM_DECL);
@@ -1323,8 +1323,8 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id)
if (gimple_debug_bind_p (stmt))
{
- copy = gimple_build_debug_bind (VAR_DEBUG_VALUE_VAR (stmt),
- VAR_DEBUG_VALUE_VALUE (stmt),
+ copy = gimple_build_debug_bind (gimple_debug_bind_get_var (stmt),
+ gimple_debug_bind_get_value (stmt),
stmt);
VARRAY_PUSH_GENERIC_PTR (id->debug_stmts, copy);
return copy;
@@ -2052,6 +2052,12 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency,
return new_fndecl;
}
+/* Copy the debug STMT using ID. We deal with these statements in a
+ special way: if any variable in their VALUE expression wasn't
+ remapped yet, we won't remap it, because that would get decl uids
+ out of sync, causing codegen differences between -g and -g0. If
+ this arises, we drop the VALUE expression altogether. */
+
static void
copy_debug_stmt (gimple stmt, copy_body_data *id)
{
@@ -2074,7 +2080,7 @@ copy_debug_stmt (gimple stmt, copy_body_data *id)
processing_debug_stmt = 1;
- t = VAR_DEBUG_VALUE_VAR (stmt);
+ t = gimple_debug_bind_get_var (stmt);
if (TREE_CODE (t) == PARM_DECL && id->debug_map
&& (n = (tree *) pointer_map_contains (id->debug_map, t)))
@@ -2085,14 +2091,15 @@ copy_debug_stmt (gimple stmt, copy_body_data *id)
else
walk_tree (&t, remap_gimple_op_r, &wi, NULL);
- VAR_DEBUG_VALUE_SET_VAR (stmt, t);
+ gimple_debug_bind_set_var (stmt, t);
- if (VAR_DEBUG_VALUE_VALUE (stmt) != VAR_DEBUG_VALUE_NOVALUE)
- walk_tree (&VAR_DEBUG_VALUE_VALUE (stmt), remap_gimple_op_r, &wi, NULL);
+ if (gimple_debug_bind_has_value_p (stmt))
+ walk_tree (gimple_debug_bind_get_value_ptr (stmt),
+ remap_gimple_op_r, &wi, NULL);
/* Punt if any decl couldn't be remapped. */
if (processing_debug_stmt < 0)
- VAR_DEBUG_VALUE_VALUE (stmt) = VAR_DEBUG_VALUE_NOVALUE;
+ gimple_debug_bind_reset_value (stmt);
processing_debug_stmt = 0;
@@ -2101,6 +2108,10 @@ copy_debug_stmt (gimple stmt, copy_body_data *id)
mark_symbols_for_renaming (stmt);
}
+/* Process deferred debug stmts. In order to give values better odds
+ of being successfully remapped, we delay the processing of debug
+ stmts. */
+
static void
copy_debug_stmts (copy_body_data *id)
{
@@ -2174,6 +2185,7 @@ insert_init_debug_bind (copy_body_data *id,
{
gimple note;
gimple_stmt_iterator gsi;
+ tree tracked_var;
if (!gimple_in_ssa_p (id->src_cfun))
return NULL;
@@ -2181,7 +2193,8 @@ insert_init_debug_bind (copy_body_data *id,
if (!MAY_HAVE_DEBUG_STMTS)
return NULL;
- if (!var_debug_value_for_decl (var))
+ tracked_var = target_for_debug_bind (var);
+ if (!tracked_var)
return NULL;
if (bb)
@@ -2191,7 +2204,7 @@ insert_init_debug_bind (copy_body_data *id,
base_stmt = gsi_stmt (gsi);
}
- note = gimple_build_debug_bind (var, value, base_stmt);
+ note = gimple_build_debug_bind (tracked_var, value, base_stmt);
if (bb)
{
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index 2b2c33471c1..57de827e418 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -1054,244 +1054,6 @@ mark_phi_for_rewrite (basic_block bb, gimple phi)
VEC_replace (gimple_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 (!DECL_NAME (var))
- {
- tree origin = DECL_ABSTRACT_ORIGIN (var);
-
- if (!origin)
- return false;
-
- if (!DECL_P (origin))
- return false;
-
- if (!DECL_NAME (origin))
- 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 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. */
-void
-adjust_debug_stmts_for_var_def_move (tree var,
- basic_block tobb,
- const gimple_stmt_iterator *togsip)
-{
- imm_use_iterator imm_iter;
- gimple stmt;
- use_operand_p use_p;
- tree value = NULL;
- bool no_value = false;
-
- if (!MAY_HAVE_DEBUG_STMTS)
- return;
-
- FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
- {
- basic_block bb;
- gimple_stmt_iterator si;
-
- if (!is_gimple_debug (stmt))
- continue;
-
- if (tobb)
- {
- bb = gimple_bb (stmt);
-
- if (bb != tobb)
- {
- if (dominated_by_p (CDI_DOMINATORS, bb, tobb))
- continue;
- }
- else
- {
- si = *togsip;
-
- if (gsi_end_p (si))
- continue;
-
- do
- {
- gsi_prev (&si);
- if (gsi_end_p (si))
- break;
- }
- while (gsi_stmt (si) != stmt);
-
- if (gsi_end_p (si))
- continue;
- }
- }
-
- if (!value && !no_value)
- {
- if (SSA_NAME_VALUE (var))
- value = SSA_NAME_VALUE (var);
- else
- {
- gimple def_stmt = SSA_NAME_DEF_STMT (var);
-
- if (gimple_code (def_stmt) == GIMPLE_ASSIGN
- && TREE_TYPE (gimple_assign_rhs1 (def_stmt))
- && gimple_assign_rhs2 (def_stmt)
- && TREE_TYPE (gimple_assign_rhs2 (def_stmt)))
- value = gimple_assign_rhs_to_tree (def_stmt);
- }
-
- if (!value)
- no_value = true;
- }
-
- if (no_value)
- VAR_DEBUG_VALUE_VALUE (stmt) = VAR_DEBUG_VALUE_NOVALUE;
- else
- FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
- SET_USE (use_p, unshare_expr (value));
-
- 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 (gimple def, basic_block tobb,
- const gimple_stmt_iterator *togsip)
-{
- 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, togsip);
- }
-}
-
-/* Wrapper struct for the function predicate passed to
- check_and_update_debug_stmt_1 (). */
-
-struct check_debug_predicate
-{
- bool (*available_p)(tree);
- gimple stmt;
-};
-
-/* 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))
- {
- /* Default definitions are never removed. */
- if (SSA_NAME_IS_DEFAULT_DEF (t))
- return NULL_TREE;
- else
- return t;
- }
-
- if (gimple_nop_p (SSA_NAME_DEF_STMT (t)))
- {
- if (SSA_NAME_IS_DEFAULT_DEF (t))
- return NULL_TREE;
- else
- return t;
- }
-
- if (p->available_p && !p->available_p (t))
- return t;
-
- if (dom_info_available_p (CDI_DOMINATORS))
- {
- basic_block bbuse = gimple_bb (p->stmt);
- basic_block bbdef = gimple_bb (SSA_NAME_DEF_STMT (t));
-
- if (bbuse != bbdef
- && !dominated_by_p (CDI_DOMINATORS, bbuse, bbdef))
- 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 (gimple t, bool (*available_p)(tree))
-{
- struct check_debug_predicate p;
-
- gcc_assert (is_gimple_debug (t));
-
- if (VAR_DEBUG_VALUE_VALUE (t) == VAR_DEBUG_VALUE_NOVALUE)
- return;
-
- p.available_p = available_p;
- p.stmt = t;
- 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
function assumes that the caller is incrementally updating the
@@ -1358,11 +1120,13 @@ insert_phi_nodes_for (tree var, bitmap phi_insertion_points, bool update_p)
}
else
{
+ tree tracked_var;
gcc_assert (DECL_P (var));
phi = create_phi_node (var, bb);
- if (!update_p && var_debug_value_for_decl (var))
+ if (!update_p && (tracked_var = target_for_debug_bind (var)))
{
- gimple note = gimple_build_debug_bind (var, PHI_RESULT (phi),
+ gimple note = gimple_build_debug_bind (tracked_var,
+ PHI_RESULT (phi),
phi);
gimple_stmt_iterator si = gsi_after_labels (bb);
gsi_insert_before (&si, note, GSI_SAME_STMT);
@@ -1540,15 +1304,19 @@ rewrite_stmt (gimple_stmt_iterator si)
if (register_defs_p (stmt))
FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_DEF)
{
- tree var = DEF_FROM_PTR (def_p), name;
+ tree var = DEF_FROM_PTR (def_p);
+ tree name = make_ssa_name (var, stmt);
+ tree tracked_var;
gcc_assert (DECL_P (var));
- SET_DEF (def_p, name = make_ssa_name (var, stmt));
- if (var_debug_value_for_decl (var))
+ SET_DEF (def_p, name);
+ register_new_def (DEF_FROM_PTR (def_p), var);
+
+ tracked_var = target_for_debug_bind (var);
+ if (tracked_var)
{
- gimple note = gimple_build_debug_bind (var, name, stmt);
+ gimple note = gimple_build_debug_bind (tracked_var, name, stmt);
gsi_insert_after (&si, note, GSI_SAME_STMT);
}
- register_new_def (DEF_FROM_PTR (def_p), var);
}
}
@@ -2013,7 +1781,7 @@ maybe_replace_use (use_operand_p use_p)
returning false to indicate a need to do so. */
static inline bool
-maybe_replace_use_in_debug_insn (use_operand_p use_p)
+maybe_replace_use_in_debug_stmt (use_operand_p use_p)
{
tree rdef = NULL_TREE;
tree use = USE_FROM_PTR (use_p);
@@ -2024,11 +1792,15 @@ maybe_replace_use_in_debug_insn (use_operand_p use_p)
else if (is_old_name (use))
{
rdef = get_current_def (use);
- if (!rdef && SSA_NAME_DEF_STMT (use))
- return true;
+ /* We can't assume that, if there's no current definition, the
+ default one should be used. It could be the case that we've
+ rearranged blocks so that the earlier definition no longer
+ dominates the use. */
+ if (!rdef && SSA_NAME_IS_DEFAULT_DEF (use))
+ rdef = use;
}
else
- return true;
+ rdef = use;
if (rdef && rdef != use)
SET_USE (use_p, rdef);
@@ -2102,37 +1874,41 @@ rewrite_update_stmt (gimple stmt)
/* Rewrite USES included in OLD_SSA_NAMES and USES whose underlying
symbol is marked for renaming. */
- if (rewrite_uses_p (stmt) && !is_gimple_debug (stmt))
- FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
- maybe_replace_use (use_p);
-
- else if (rewrite_uses_p (stmt) && is_gimple_debug (stmt))
+ if (rewrite_uses_p (stmt))
{
- bool failed = false;
+ if (is_gimple_debug (stmt))
+ {
+ bool failed = false;
- FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
- if (!maybe_replace_use_in_debug_insn (use_p))
- {
- failed = true;
- break;
- }
+ FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
+ if (!maybe_replace_use_in_debug_stmt (use_p))
+ {
+ failed = true;
+ break;
+ }
- if (failed)
+ if (failed)
+ {
+ /* DOM sometimes threads jumps in such a way that a
+ debug stmt ends up referencing a SSA variable that no
+ longer dominates the debug stmt, but such that all
+ incoming definitions refer to the same definition in
+ an earlier dominator. We could try to recover that
+ definition somehow, but this will have to do for now.
+
+ Introducing a default definition, which is what
+ maybe_replace_use() would do in such cases, may
+ modify code generation, for the otherwise-unused
+ default definition would never go away, modifying SSA
+ version numbers all over. */
+ gimple_debug_bind_reset_value (stmt);
+ update_stmt (stmt);
+ }
+ }
+ else
{
- /* DOM sometimes threads jumps in such a way that a debug
- stmt ends up referencing a SSA variable that no longer
- dominates the debug stmt, but such that all incoming
- definitions refer to the same definition in an earlier
- dominator. We could try to recover that definition
- somehow, but this will have to do for now.
-
- Introducing a default definition, which is what
- maybe_replace_use() would do in such cases, may modify
- code generation, for the otherwise-unused default
- definition would never go away, modifying SSA version
- numbers all over. */
- VAR_DEBUG_VALUE_VALUE (stmt) = VAR_DEBUG_VALUE_NOVALUE;
- update_stmt (stmt);
+ FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
+ maybe_replace_use (use_p);
}
}
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index 8012bba156e..c3b73a4566e 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -883,7 +883,7 @@ separate_decls_in_region_debug_bind (gimple stmt,
slot = htab_find_slot_with_hash (name_copies, &elt, elt.version, NO_INSERT);
if (!slot)
{
- gimple_debug_bind_set_value (stmt, VAR_DEBUG_VALUE_NOVALUE);
+ gimple_debug_bind_reset_value (stmt);
update_stmt (stmt);
break;
}
@@ -1253,6 +1253,12 @@ separate_decls_in_region (edge entry, edge exit, htab_t reduction_list,
}
}
+ /* Now process debug bind stmts. We must not create decls while
+ processing debug stmts, so we defer their processing so as to
+ make sure we will have debug info for as many variables as
+ possible (all of those that were dealt with in the loop above),
+ and discard those for which we know there's nothing we can
+ do. */
if (has_debug_stmt)
for (i = 0; VEC_iterate (basic_block, body, i, bb); i++)
if (bb != entry_bb && bb != exit_bb)
@@ -1271,8 +1277,6 @@ separate_decls_in_region (edge entry, edge exit, htab_t reduction_list,
continue;
}
}
- else
- gcc_assert (!is_gimple_debug (stmt));
gsi_next (&gsi);
}
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index 48ea86338c1..a58a9f68a04 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -1,5 +1,5 @@
/* Dead code elimination pass for the GNU compiler.
- Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Ben Elliston <bje@redhat.com>
and Andrew MacLeod <amacleod@redhat.com>
@@ -1062,16 +1062,6 @@ remove_dead_stmt (gimple_stmt_iterator *i, basic_block bb)
release_defs (stmt);
}
-/* 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 gimple_plf (SSA_NAME_DEF_STMT (t), STMT_NECESSARY);
-}
-
/* Eliminate unnecessary statements. Any instruction not marked as necessary
contributes nothing to the program, and can be deleted. */
@@ -1089,10 +1079,32 @@ eliminate_unnecessary_stmts (void)
clear_special_calls ();
- FOR_EACH_BB (bb)
+ /* Walking basic blocks and statements in reverse order avoids
+ releasing SSA names before any other DEFs that refer to them are
+ released. This helps avoid loss of debug information, as we get
+ a chance to propagate all RHSs of removed SSAs into debug uses,
+ rather than only the latest ones. E.g., consider:
+
+ x_3 = y_1 + z_2;
+ a_5 = x_3 - b_4;
+ # DEBUG a => a_5
+
+ If we were to release x_3 before a_5, when we reached a_5 and
+ tried to substitute it into the debug stmt, we'd see x_3 there,
+ but x_3's DEF, type, etc would have already been disconnected.
+ By going backwards, the debug stmt first changes to:
+
+ # DEBUG a => x_3 - b_4
+
+ and then to:
+
+ # DEBUG a => y_1 + z_2 - b_4
+
+ as desired. */
+ FOR_EACH_BB_REVERSE (bb)
{
/* Remove dead statements. */
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
+ for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi);)
{
stmt = gsi_stmt (gsi);
@@ -1103,6 +1115,14 @@ eliminate_unnecessary_stmts (void)
{
remove_dead_stmt (&gsi, bb);
something_changed = true;
+
+ /* If stmt was the last stmt in the block, we want to
+ move gsi to the stmt that became the last stmt, but
+ gsi_prev would crash. */
+ if (gsi_end_p (gsi))
+ gsi = gsi_last_bb (bb);
+ else
+ gsi_prev (&gsi);
}
else if (is_gimple_call (stmt))
{
@@ -1132,19 +1152,10 @@ eliminate_unnecessary_stmts (void)
}
notice_special_calls (stmt);
}
- gsi_next (&gsi);
+ gsi_prev (&gsi);
}
else
- {
- if (gimple_debug_bind_p (stmt))
- {
- if (something_changed
- && (VAR_DEBUG_VALUE_VALUE (stmt)
- != VAR_DEBUG_VALUE_NOVALUE))
- check_and_update_debug_stmt (stmt, necessary_p);
- }
- gsi_next (&gsi);
- }
+ gsi_prev (&gsi);
}
}
/* Since we don't track liveness of virtual PHI nodes, it is possible that we
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 94f1332a97e..e8c81ff6c61 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -1,5 +1,5 @@
/* SSA Dominator optimizations for trees
- Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@redhat.com>
@@ -2523,6 +2523,11 @@ propagate_rhs_into_lhs (gimple stmt, tree lhs, tree rhs, bitmap interesting_name
be successful would be if the use occurs in an ASM_EXPR. */
FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
{
+ /* Leave debug stmts alone. If we succeed in propagating
+ all non-debug uses, we'll drop the DEF, and propagation
+ into debug stmts will occur then. */
+ if (gimple_debug_bind_p (use_stmt))
+ continue;
/* It's not always safe to propagate into an ASM_EXPR. */
if (gimple_code (use_stmt) == GIMPLE_ASM
@@ -2575,8 +2580,6 @@ propagate_rhs_into_lhs (gimple stmt, tree lhs, tree rhs, bitmap interesting_name
continue;
}
- else if (gimple_debug_bind_p (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 7e380b196ea..ac446dbb697 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -984,7 +984,7 @@ forward_propagate_addr_expr (tree name, tree rhs)
}
if (all && debug)
- adjust_debug_stmts_for_var_def_move (name, NULL, NULL);
+ propagate_var_def_into_debug_stmts (name, NULL, NULL);
return all;
}
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 1eb954d3143..738249445b0 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -879,7 +879,7 @@ rewrite_bittest (gimple_stmt_iterator *bsi)
gimple_cond_set_rhs (use_stmt, build_int_cst_type (TREE_TYPE (name), 0));
gsi_insert_before (bsi, stmt1, GSI_SAME_STMT);
- adjust_debug_stmts_for_move (gsi_stmt (*bsi), NULL, NULL);
+ propagate_defs_into_debug_stmts (gsi_stmt (*bsi), NULL, NULL);
gsi_replace (bsi, stmt2, true);
return stmt1;
@@ -1060,7 +1060,7 @@ move_computations_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED,
mark_virtual_ops_for_renaming (stmt);
gsi_insert_on_edge (loop_preheader_edge (level), stmt);
- adjust_debug_stmts_for_move (gsi_stmt (bsi), NULL, NULL);
+ propagate_defs_into_debug_stmts (gsi_stmt (bsi), NULL, NULL);
gsi_remove (&bsi, false);
}
}
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 2047b944bec..94e926b0a25 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -5426,7 +5426,7 @@ remove_unused_ivs (struct ivopts_data *data)
continue;
/* ??? We can probably do better than this. */
- VAR_DEBUG_VALUE_VALUE (stmt) = VAR_DEBUG_VALUE_NOVALUE;
+ gimple_debug_bind_reset_value (stmt);
update_stmt (stmt);
}
}
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index 8640fa75a01..ac84fb978b0 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -126,9 +126,6 @@ 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;
@@ -638,7 +635,7 @@ add_virtual_operand (gimple stmt ATTRIBUTE_UNUSED, int flags)
if (flags & opf_no_vops)
return;
- gcc_assert ((flags & opf_debug_use) == 0);
+ gcc_assert (!is_gimple_debug (stmt));
if (flags & opf_def)
append_vdef (gimple_vop (cfun));
@@ -727,7 +724,8 @@ get_indirect_ref_operands (gimple stmt, tree expr, int flags,
/* If requested, add a USE operand for the base pointer. */
if (recurse_on_base)
- get_expr_operands (stmt, pptr, opf_use);
+ get_expr_operands (stmt, pptr,
+ opf_use | (flags & opf_no_vops));
}
@@ -856,8 +854,8 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags)
if (expr == NULL)
return;
- if ((flags & opf_debug_use) != 0)
- uflags |= (flags & (opf_debug_use | opf_no_vops));
+ if (is_gimple_debug (stmt))
+ uflags |= (flags & opf_no_vops);
code = TREE_CODE (expr);
codeclass = TREE_CODE_CLASS (code);
@@ -869,7 +867,7 @@ get_expr_operands (gimple 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). */
- if (!(flags & opf_debug_use))
+ if (!is_gimple_debug (stmt))
mark_address_taken (TREE_OPERAND (expr, 0));
/* If the address is invariant, there may be no interesting
@@ -950,12 +948,6 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags)
get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags);
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 | opf_no_vops);
- return;
-
case CONSTRUCTOR:
{
/* General aggregate CONSTRUCTORs have been decomposed, but they
@@ -1045,9 +1037,9 @@ parse_ssa_operands (gimple stmt)
else if (is_gimple_debug (stmt))
{
if (gimple_debug_bind_p (stmt)
- && VAR_DEBUG_VALUE_VALUE (stmt) != VAR_DEBUG_VALUE_NOVALUE)
- get_expr_operands (stmt, &VAR_DEBUG_VALUE_VALUE (stmt),
- opf_use | opf_debug_use | opf_no_vops);
+ && gimple_debug_bind_has_value_p (stmt))
+ get_expr_operands (stmt, gimple_debug_bind_get_value_ptr (stmt),
+ opf_use | opf_no_vops);
}
else
{
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 8bddac3f70e..d97f51367e2 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -1405,7 +1405,7 @@ rewrite_expr_tree (gimple stmt, unsigned int opindex,
{
stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt1));
gsirhs1 = gsi_for_stmt (stmt2);
- adjust_debug_stmts_for_move (stmt2, gimple_bb (stmt), &gsinow);
+ propagate_defs_into_debug_stmts (stmt2, gimple_bb (stmt), &gsinow);
gsi_move_before (&gsirhs1, &gsinow);
gsi_prev (&gsinow);
stmt1 = stmt2;
@@ -1452,7 +1452,7 @@ linearize_expr (gimple stmt)
gsinow = gsi_for_stmt (stmt);
gsirhs = gsi_for_stmt (binrhs);
- adjust_debug_stmts_for_move (binrhs, gimple_bb (stmt), &gsinow);
+ propagate_defs_into_debug_stmts (binrhs, gimple_bb (stmt), &gsinow);
gsi_move_before (&gsirhs, &gsinow);
gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs));
diff --git a/gcc/tree-ssa-sink.c b/gcc/tree-ssa-sink.c
index 52a55a38cfe..5b9b4be3090 100644
--- a/gcc/tree-ssa-sink.c
+++ b/gcc/tree-ssa-sink.c
@@ -388,7 +388,7 @@ statement_sink_location (gimple stmt, basic_block frombb,
*togsi = gsi_after_labels (commondom);
if (debug_stmts)
- adjust_debug_stmts_for_move (stmt, commondom, togsi);
+ propagate_defs_into_debug_stmts (stmt, commondom, togsi);
return true;
}
@@ -408,7 +408,7 @@ statement_sink_location (gimple stmt, basic_block frombb,
*togsi = gsi_for_stmt (use);
- adjust_debug_stmts_for_move (stmt, sinkbb, togsi);
+ propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
return true;
}
@@ -443,7 +443,7 @@ statement_sink_location (gimple stmt, basic_block frombb,
*togsi = gsi_after_labels (sinkbb);
- adjust_debug_stmts_for_move (stmt, sinkbb, togsi);
+ propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
return true;
}
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 56358894eb5..629bf76687d 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -239,6 +239,148 @@ flush_pending_stmts (edge e)
redirect_edge_var_map_clear (e);
}
+/* Given a tree for an expression for which we might want to emit
+ locations or values in debug information (generally a variable, but
+ we might deal with other kinds of trees in the future), return the
+ tree that should be used as the variable of a DEBUG_BIND STMT or
+ VAR_LOCATION INSN or NOTE. Return NULL if VAR is not to be tracked. */
+
+tree
+target_for_debug_bind (tree var)
+{
+ if (!MAY_HAVE_DEBUG_STMTS)
+ return NULL_TREE;
+
+ if (TREE_CODE (var) != VAR_DECL
+ && TREE_CODE (var) != PARM_DECL)
+ return NULL_TREE;
+
+ if (DECL_HAS_VALUE_EXPR_P (var))
+ return target_for_debug_bind (DECL_VALUE_EXPR (var));
+
+#if 0
+ /* Should we deal with DECL_DEBUG_EXPR_IS_FROM as well? */
+ if (DECL_DEBUG_EXPR_IS_FROM (var))
+ return target_for_debug_bind (DECL_DEBUG_EXPR (var));
+#endif
+
+ if (DECL_IGNORED_P (var))
+ return NULL_TREE;
+
+ if (!is_gimple_reg (var))
+ return NULL_TREE;
+
+ return var;
+}
+
+/* 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. */
+void
+propagate_var_def_into_debug_stmts (tree var,
+ basic_block tobb,
+ const gimple_stmt_iterator *togsip)
+{
+ imm_use_iterator imm_iter;
+ gimple stmt;
+ use_operand_p use_p;
+ tree value = NULL;
+ bool no_value = false;
+
+ if (!MAY_HAVE_DEBUG_STMTS)
+ return;
+
+ FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
+ {
+ basic_block bb;
+ gimple_stmt_iterator si;
+
+ if (!is_gimple_debug (stmt))
+ continue;
+
+ if (tobb)
+ {
+ bb = gimple_bb (stmt);
+
+ if (bb != tobb)
+ {
+ gcc_assert (dom_info_available_p (CDI_DOMINATORS));
+ if (dominated_by_p (CDI_DOMINATORS, bb, tobb))
+ continue;
+ }
+ else
+ {
+ si = *togsip;
+
+ if (gsi_end_p (si))
+ continue;
+
+ do
+ {
+ gsi_prev (&si);
+ if (gsi_end_p (si))
+ break;
+ }
+ while (gsi_stmt (si) != stmt);
+
+ if (gsi_end_p (si))
+ continue;
+ }
+ }
+
+ /* 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)
+ {
+ gimple def_stmt = SSA_NAME_DEF_STMT (var);
+
+ if (is_gimple_assign (def_stmt))
+ value = gimple_assign_rhs_to_tree (def_stmt);
+
+ if (!value)
+ no_value = true;
+ }
+
+ if (no_value)
+ gimple_debug_bind_reset_value (stmt);
+ else
+ FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
+ SET_USE (use_p, unshare_expr (value));
+
+ 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
+propagate_defs_into_debug_stmts (gimple def, basic_block tobb,
+ const gimple_stmt_iterator *togsip)
+{
+ 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;
+
+ propagate_var_def_into_debug_stmts (var, tobb, togsip);
+ }
+}
+
/* Return true if SSA_NAME is malformed and mark it visited.
IS_VIRTUAL is true if this SSA_NAME was found inside a virtual
@@ -633,7 +775,7 @@ verify_ssa (bool check_modified_stmt)
}
}
else if (gimple_debug_bind_p (stmt)
- && VAR_DEBUG_VALUE_VALUE (stmt) == VAR_DEBUG_VALUE_NOVALUE)
+ && !gimple_debug_bind_has_value_p (stmt))
continue;
/* Verify the single virtual operand and its constraints. */
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 0b1ff301abe..45183218a2c 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -206,7 +206,7 @@ release_ssa_name (tree 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);
+ propagate_var_def_into_debug_stmts (var, NULL, NULL);
#ifdef ENABLE_CHECKING
verify_imm_links (stderr, var);
diff --git a/gcc/tree.def b/gcc/tree.def
index 08f6b7eb505..b4828ad9478 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -948,11 +948,6 @@ DEFTREECODE (STATEMENT_LIST, "statement_list", tcc_exceptional, 0)
The type of the expression is the same as Y. */
DEFTREECODE (ASSERT_EXPR, "assert_expr", tcc_expression, 2)
-/* Debug bind operation. Operand 0 is a tree that represents a user
- variable; 1 is an expression that evaluates to the value of the
- variable. */
-DEFTREECODE (VAR_DEBUG_VALUE, "var_debug_value", tcc_statement, 2)
-
/* Base class information. Holds information about a class as a
baseclass of itself or another class. */
DEFTREECODE (TREE_BINFO, "tree_binfo", tcc_exceptional, 0)
diff --git a/gcc/tree.h b/gcc/tree.h
index 71cd42da27a..5a15e938c93 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1534,13 +1534,6 @@ struct GTY(()) tree_constructor {
/* Nonzero if is_gimple_debug() may possibly hold. */
#define MAY_HAVE_DEBUG_STMTS (flag_var_tracking_assignments)
-/* The second operand of a VAR_DEBUG_VALUE when the value was
- optimized away. */
-#define VAR_DEBUG_VALUE_NOVALUE NULL_TREE /* error_mark_node */
-#define VAR_DEBUG_VALUE_SET_VAR(T, V) (gimple_debug_bind_set_var ((T), (V)))
-#define VAR_DEBUG_VALUE_VAR(T) (gimple_debug_bind_get_var (T))
-#define VAR_DEBUG_VALUE_VALUE(T) (*gimple_debug_bind_get_value_ptr (T))
-
/* In a LOOP_EXPR node. */
#define LOOP_EXPR_BODY(NODE) TREE_OPERAND_CHECK_CODE (NODE, LOOP_EXPR, 0)
@@ -5173,6 +5166,10 @@ struct GTY(()) tree_priority_map {
#define tree_priority_map_hash tree_map_base_hash
#define tree_priority_map_marked_p tree_map_base_marked_p
+/* In tree-ssa.c */
+
+tree target_for_debug_bind (tree);
+
/* In tree-ssa-ccp.c */
extern tree maybe_fold_offset_to_reference (location_t, tree, tree, tree);
extern tree maybe_fold_offset_to_address (location_t, tree, tree, tree);
@@ -5313,8 +5310,4 @@ 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 */
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index 25bf28999a5..ad65da7fb0d 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -779,7 +779,7 @@ dv_onepart_p (decl_or_value dv)
if (!decl)
return true;
- return var_debug_value_for_decl (decl);
+ return (target_for_debug_bind (decl) != NULL_TREE);
}
/* Return the variable pool to be used for dv, depending on whether it
@@ -4490,7 +4490,7 @@ use_type (rtx *loc, struct count_use_info *cui, enum machine_mode *modep)
if (!expr)
return MO_USE_NO_VAR;
- else if (var_debug_value_for_decl (var_debug_decl (expr)))
+ else if (target_for_debug_bind (var_debug_decl (expr)))
return MO_CLOBBER;
else if (track_loc_p (*loc, expr, REG_OFFSET (*loc),
false, modep, NULL))
@@ -4504,7 +4504,7 @@ use_type (rtx *loc, struct count_use_info *cui, enum machine_mode *modep)
if (!expr)
return MO_CLOBBER;
- else if (var_debug_value_for_decl (var_debug_decl (expr)))
+ else if (target_for_debug_bind (var_debug_decl (expr)))
return MO_CLOBBER;
else if (track_loc_p (*loc, expr, INT_MEM_OFFSET (*loc),
false, modep, NULL))
@@ -7124,7 +7124,7 @@ vt_add_function_parameters (void)
dv = dv_from_decl (parm);
- if (var_debug_value_for_decl (parm)
+ if (target_for_debug_bind (parm)
/* We can't deal with these right now, because this kind of
variable is single-part. ??? We could handle parallels
that describe multiple locations for the same single