diff options
author | aoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-07-12 11:16:25 +0000 |
---|---|---|
committer | aoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-07-12 11:16:25 +0000 |
commit | 7c0af8e6e7b8380b2437f6e880e6259e049ffd7a (patch) | |
tree | 72a6ef9f532354981e41d06a4ae811b2d1f77105 | |
parent | 68764e33c09ca351da16a6667f5d84c54051088b (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.vta | 72 | ||||
-rw-r--r-- | gcc/cfgexpand.c | 13 | ||||
-rw-r--r-- | gcc/expr.c | 4 | ||||
-rw-r--r-- | gcc/gimple-pretty-print.c | 2 | ||||
-rw-r--r-- | gcc/gimple.c | 9 | ||||
-rw-r--r-- | gcc/gimple.h | 42 | ||||
-rw-r--r-- | gcc/tree-cfg.c | 24 | ||||
-rw-r--r-- | gcc/tree-flow.h | 9 | ||||
-rw-r--r-- | gcc/tree-if-conv.c | 4 | ||||
-rw-r--r-- | gcc/tree-inline.c | 33 | ||||
-rw-r--r-- | gcc/tree-into-ssa.c | 328 | ||||
-rw-r--r-- | gcc/tree-parloops.c | 10 | ||||
-rw-r--r-- | gcc/tree-ssa-dce.c | 59 | ||||
-rw-r--r-- | gcc/tree-ssa-dom.c | 9 | ||||
-rw-r--r-- | gcc/tree-ssa-forwprop.c | 2 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-im.c | 4 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-ivopts.c | 2 | ||||
-rw-r--r-- | gcc/tree-ssa-operands.c | 26 | ||||
-rw-r--r-- | gcc/tree-ssa-reassoc.c | 4 | ||||
-rw-r--r-- | gcc/tree-ssa-sink.c | 6 | ||||
-rw-r--r-- | gcc/tree-ssa.c | 144 | ||||
-rw-r--r-- | gcc/tree-ssanames.c | 2 | ||||
-rw-r--r-- | gcc/tree.def | 5 | ||||
-rw-r--r-- | gcc/tree.h | 15 | ||||
-rw-r--r-- | gcc/var-tracking.c | 8 |
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 |