re PR debug/41343 (sysdeps/ieee754/dbl-64/dosincos.c from glibc causes excessive memory use)

gcc/ChangeLog:
PR debug/41343
PR debug/41447
PR debug/41264
PR debug/41338
* tree.def (DEBUG_EXPR_DECL): New.
* rtl.def (DEBUG_EXPR): New.
* gengtype.c (adjust_field_rtx_def): Handle it.
* tree-ssa.c (propagate_var_def_into_debug_stmts): Rename to...
(insert_debug_temp_for_var_def): ... this.  Drop support for
moving.  Take iterator for def stmt; insert debug stmt before it.
Scan early for use count and kind in debug stmts.
(propagate_defs_into_debug_stmts): Rename to...
(insert_debug_temps_for_defs): ... this.  Likewise.
* tree.h (DEBUG_TEMP_UID): New.
* tree.c (next_debug_decl_uid): New.
(make_node_stat): Count debug decls separately.
(copy_node_stat): Likewise.
* cfgexpand.c (expand_debug_expr): Handle DEBUG_EXPR_DECL.
* var-tracking.c (dv_is_decl_p): Recognize it.
(VALUE_RECURSED_INTO): Apply to DEBUG_EXPRs too.
(track_expr_p): Track expanded DEBUG_EXPR_DECLs.
(vt_expand_loc_callback): Expand DEBUG_EXPRs.
(emit_note_insn_var_location): Don't emit notes for DEBUG_EXPR_DECLs.
* cselib.c (rtx_equal_for_cselib_p): Handle DEBUG_EXPR.
(cselib_hash_rtx): Likewise.
(cselib_expand_value_rtx_1): Use callback for DEBUG_EXPR.
* tree-ssa-operands.c (get_expr_operands): Skip DEBUG_EXPR_DECLs in
debug bind stmts.
* emit-rtl.c (verify_rtx_sharing): Handle DEBUG_EXPR and VALUE.
(copy_rtx_if_shared_1, reset_used_flags, set_used_flags): Likewise.
* rtl.c (copy_rtx): Likewise.
(rtx_equal_p_cb, rtx_equal_p): Handle DEBUG_EXPR.
* print-rtl.c (print_rtx): Likewise.
* sched-vis.c (print_value): Likewise.
(print_insn): Handle DEBUG_EXPR_DECL.
* tree-dump.c (dequeue_and_dump): Likewise.
* tree-pretty-print.c (dump_decl_name, dump_generic_node): Likewise.
* gimple-iterator (gsi_replace): Check for same lhs.
(gsi_remove): Insert debug temps.
* tree-ssa-loop-im.c (rewrite_reciprocal): Replace with same lhs.
(move_computations_stmt): Drop explicit propagation into debug stmts.
(rewrite_bittest): Likewise.  Use gsi_remove for propagation.
* tree-ssa-reassoc.c (rewrite_expr_tree, linearize_expr): Likewise.
* tree-ssa-sink.c (statement_sink_location): Likewise.
* tree-ssa-forwprop (forward_propagate_addr_expr): Likewise.
* tree-ssanames.c (release_ssa_name): Adjust for rename.
* tree-flow.h: Likewise.
* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Don't mark
debug temps without values.
(eliminate_unnecessary_stmts): Don't discard just-inserted
debug stmts.
gcc/testsuite/ChangeLog:
PR debug/41343
PR debug/41447
PR debug/41264
PR debug/41338
* gcc.dg/guality/pr41447-1.c: New.
* gcc.dg/debug/pr41264-1.c: New.
* gcc.dg/debug/pr41343-1.c: New.

From-SVN: r152681
This commit is contained in:
Alexandre Oliva 2009-10-12 18:58:38 +00:00 committed by Alexandre Oliva
parent 2e723874b5
commit 0ca5af51ab
29 changed files with 444 additions and 154 deletions

View File

@ -1,3 +1,57 @@
2009-10-12 Alexandre Oliva <aoliva@redhat.com>
PR debug/41343
PR debug/41447
PR debug/41264
PR debug/41338
* tree.def (DEBUG_EXPR_DECL): New.
* rtl.def (DEBUG_EXPR): New.
* gengtype.c (adjust_field_rtx_def): Handle it.
* tree-ssa.c (propagate_var_def_into_debug_stmts): Rename to...
(insert_debug_temp_for_var_def): ... this. Drop support for
moving. Take iterator for def stmt; insert debug stmt before it.
Scan early for use count and kind in debug stmts.
(propagate_defs_into_debug_stmts): Rename to...
(insert_debug_temps_for_defs): ... this. Likewise.
* tree.h (DEBUG_TEMP_UID): New.
* tree.c (next_debug_decl_uid): New.
(make_node_stat): Count debug decls separately.
(copy_node_stat): Likewise.
* cfgexpand.c (expand_debug_expr): Handle DEBUG_EXPR_DECL.
* var-tracking.c (dv_is_decl_p): Recognize it.
(VALUE_RECURSED_INTO): Apply to DEBUG_EXPRs too.
(track_expr_p): Track expanded DEBUG_EXPR_DECLs.
(vt_expand_loc_callback): Expand DEBUG_EXPRs.
(emit_note_insn_var_location): Don't emit notes for DEBUG_EXPR_DECLs.
* cselib.c (rtx_equal_for_cselib_p): Handle DEBUG_EXPR.
(cselib_hash_rtx): Likewise.
(cselib_expand_value_rtx_1): Use callback for DEBUG_EXPR.
* tree-ssa-operands.c (get_expr_operands): Skip DEBUG_EXPR_DECLs in
debug bind stmts.
* emit-rtl.c (verify_rtx_sharing): Handle DEBUG_EXPR and VALUE.
(copy_rtx_if_shared_1, reset_used_flags, set_used_flags): Likewise.
* rtl.c (copy_rtx): Likewise.
(rtx_equal_p_cb, rtx_equal_p): Handle DEBUG_EXPR.
* print-rtl.c (print_rtx): Likewise.
* sched-vis.c (print_value): Likewise.
(print_insn): Handle DEBUG_EXPR_DECL.
* tree-dump.c (dequeue_and_dump): Likewise.
* tree-pretty-print.c (dump_decl_name, dump_generic_node): Likewise.
* gimple-iterator (gsi_replace): Check for same lhs.
(gsi_remove): Insert debug temps.
* tree-ssa-loop-im.c (rewrite_reciprocal): Replace with same lhs.
(move_computations_stmt): Drop explicit propagation into debug stmts.
(rewrite_bittest): Likewise. Use gsi_remove for propagation.
* tree-ssa-reassoc.c (rewrite_expr_tree, linearize_expr): Likewise.
* tree-ssa-sink.c (statement_sink_location): Likewise.
* tree-ssa-forwprop (forward_propagate_addr_expr): Likewise.
* tree-ssanames.c (release_ssa_name): Adjust for rename.
* tree-flow.h: Likewise.
* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Don't mark
debug temps without values.
(eliminate_unnecessary_stmts): Don't discard just-inserted
debug stmts.
2009-10-12 Hans-Peter Nilsson <hp@axis.com>
PR target/26515

View File

@ -2361,6 +2361,18 @@ expand_debug_expr (tree exp)
op1 = wrap_constant (GET_MODE_INNER (mode), op1);
return gen_rtx_CONCAT (mode, op0, op1);
case DEBUG_EXPR_DECL:
op0 = DECL_RTL_IF_SET (exp);
if (op0)
return op0;
op0 = gen_rtx_DEBUG_EXPR (mode);
XTREE (op0, 0) = exp;
SET_DECL_RTL (exp, op0);
return op0;
case VAR_DECL:
case PARM_DECL:
case FUNCTION_DECL:

View File

@ -585,6 +585,7 @@ rtx_equal_for_cselib_p (rtx x, rtx y)
{
case CONST_DOUBLE:
case CONST_FIXED:
case DEBUG_EXPR:
return 0;
case LABEL_REF:
@ -703,6 +704,10 @@ cselib_hash_rtx (rtx x, int create)
return e->value;
case DEBUG_EXPR:
hash += ((unsigned) DEBUG_EXPR << 7) + DEBUG_TEMP_UID (XTREE (x, 0));
return hash ? hash : (unsigned int) DEBUG_EXPR;
case CONST_INT:
hash += ((unsigned) CONST_INT << 7) + INTVAL (x);
return hash ? hash : (unsigned int) CONST_INT;
@ -1213,6 +1218,13 @@ cselib_expand_value_rtx_1 (rtx orig, struct expand_value_data *evd,
result = expand_loc (CSELIB_VAL_PTR (orig)->locs, evd, max_depth);
return result;
}
case DEBUG_EXPR:
if (evd->callback)
return evd->callback (orig, evd->regs_active, max_depth,
evd->callback_arg);
return orig;
default:
break;
}

View File

@ -2393,6 +2393,8 @@ verify_rtx_sharing (rtx orig, rtx insn)
switch (code)
{
case REG:
case DEBUG_EXPR:
case VALUE:
case CONST_INT:
case CONST_DOUBLE:
case CONST_FIXED:
@ -2593,6 +2595,8 @@ repeat:
switch (code)
{
case REG:
case DEBUG_EXPR:
case VALUE:
case CONST_INT:
case CONST_DOUBLE:
case CONST_FIXED:
@ -2712,6 +2716,8 @@ repeat:
switch (code)
{
case REG:
case DEBUG_EXPR:
case VALUE:
case CONST_INT:
case CONST_DOUBLE:
case CONST_FIXED:
@ -2783,6 +2789,8 @@ set_used_flags (rtx x)
switch (code)
{
case REG:
case DEBUG_EXPR:
case VALUE:
case CONST_INT:
case CONST_DOUBLE:
case CONST_FIXED:

View File

@ -1117,6 +1117,8 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
t = scalar_tp, subname = "rt_int";
else if (i == VALUE && aindex == 0)
t = scalar_tp, subname = "rt_int";
else if (i == DEBUG_EXPR && aindex == 0)
t = tree_tp, subname = "rt_tree";
else if (i == REG && aindex == 1)
t = scalar_tp, subname = "rt_int";
else if (i == REG && aindex == 2)

View File

@ -358,7 +358,8 @@ gsi_split_seq_before (gimple_stmt_iterator *i)
/* Replace the statement pointed-to by GSI to STMT. If UPDATE_EH_INFO
is true, the exception handling information of the original
statement is moved to the new statement. */
statement is moved to the new statement. Assignments must only be
replaced with assignments to the same LHS. */
void
gsi_replace (gimple_stmt_iterator *gsi, gimple stmt, bool update_eh_info)
@ -368,6 +369,9 @@ gsi_replace (gimple_stmt_iterator *gsi, gimple stmt, bool update_eh_info)
if (stmt == orig_stmt)
return;
gcc_assert (!gimple_has_lhs (orig_stmt)
|| gimple_get_lhs (orig_stmt) == gimple_get_lhs (stmt));
gimple_set_location (stmt, gimple_location (orig_stmt));
gimple_set_bb (stmt, gsi_bb (*gsi));
@ -470,6 +474,8 @@ gsi_remove (gimple_stmt_iterator *i, bool remove_permanently)
gimple_seq_node cur, next, prev;
gimple stmt = gsi_stmt (*i);
insert_debug_temps_for_defs (i);
/* Free all the data flow information for STMT. */
gimple_set_bb (stmt, NULL);
delink_stmt_imm_use (stmt);

View File

@ -316,6 +316,12 @@ print_rtx (const_rtx in_rtx)
fprintf (outfile, " %i", val->value);
dump_addr (outfile, " @", in_rtx);
dump_addr (outfile, "/", (void*)val);
#endif
}
else if (i == 0 && GET_CODE (in_rtx) == DEBUG_EXPR)
{
#ifndef GENERATOR_FILE
fprintf (outfile, " D#%i", DEBUG_TEMP_UID (XTREE (in_rtx, 0)));
#endif
}
break;

View File

@ -232,6 +232,8 @@ copy_rtx (rtx orig)
switch (code)
{
case REG:
case DEBUG_EXPR:
case VALUE:
case CONST_INT:
case CONST_DOUBLE:
case CONST_FIXED:
@ -381,6 +383,7 @@ rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb)
case SYMBOL_REF:
return XSTR (x, 0) == XSTR (y, 0);
case DEBUG_EXPR:
case VALUE:
case SCRATCH:
case CONST_DOUBLE:
@ -496,6 +499,7 @@ rtx_equal_p (const_rtx x, const_rtx y)
case SYMBOL_REF:
return XSTR (x, 0) == XSTR (y, 0);
case DEBUG_EXPR:
case VALUE:
case SCRATCH:
case CONST_DOUBLE:

View File

@ -88,6 +88,10 @@ DEF_RTL_EXPR(UNKNOWN, "UnKnown", "*", RTX_EXTRA)
DECL codes in trees. */
DEF_RTL_EXPR(VALUE, "value", "0", RTX_OBJ)
/* The RTL generated for a DEBUG_EXPR_DECL. It links back to the
DEBUG_EXPR_DECL in the first operand. */
DEF_RTL_EXPR(DEBUG_EXPR, "debug_expr", "0", RTX_OBJ)
/* ---------------------------------------------------------------------
Expressions used in constructing lists.
--------------------------------------------------------------------- */

View File

@ -521,6 +521,10 @@ print_value (char *buf, const_rtx x, int verbose)
cur = safe_concat (buf, cur, t);
cur = safe_concat (buf, cur, "]");
break;
case DEBUG_EXPR:
sprintf (t, "D#%i", DEBUG_TEMP_UID (XTREE (x, 0)));
cur = safe_concat (buf, cur, t);
break;
default:
print_exp (t, x, verbose);
cur = safe_concat (buf, cur, t);
@ -670,11 +674,18 @@ print_insn (char *buf, const_rtx x, int verbose)
if (DECL_P (INSN_VAR_LOCATION_DECL (insn)))
{
tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (insn));
char idbuf[32];
if (id)
name = IDENTIFIER_POINTER (id);
else if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn))
== DEBUG_EXPR_DECL)
{
sprintf (idbuf, "D#%i",
DEBUG_TEMP_UID (INSN_VAR_LOCATION_DECL (insn)));
name = idbuf;
}
else
{
char idbuf[32];
sprintf (idbuf, "D.%i",
DECL_UID (INSN_VAR_LOCATION_DECL (insn)));
name = idbuf;

View File

@ -1,3 +1,13 @@
2009-10-12 Alexandre Oliva <aoliva@redhat.com>
PR debug/41343
PR debug/41447
PR debug/41264
PR debug/41338
* gcc.dg/guality/pr41447-1.c: New.
* gcc.dg/debug/pr41264-1.c: New.
* gcc.dg/debug/pr41343-1.c: New.
2009-10-12 Hans-Peter Nilsson <hp@axis.com>
PR target/26515

View File

@ -0,0 +1,36 @@
/* { dg-do compile } */
typedef unsigned int hashval_t;
static hashval_t __attribute__((always_inline))
iterative_hash_host_wide_int (long val, hashval_t val2)
{
hashval_t a = (hashval_t) val;
int zero = 0;
hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 8 + zero));
a -= b; a -= val2; a ^= (val2>>13);
b -= val2; b -= a; b ^= (a<< 8);
val2 -= a; val2 -= b; val2 ^= ((b&0xffffffff)>>13);
a -= b; a -= val2; a ^= ((val2&0xffffffff)>>12);
b -= val2; b -= a; b = (b ^ (a<<16)) & 0xffffffff;
val2 -= a; val2 -= b; val2 = (val2 ^ (b>> 5)) & 0xffffffff;
a -= b; a -= val2; a = (a ^ (val2>> 3)) & 0xffffffff;
b -= val2; b -= a; b = (b ^ (a<<10)) & 0xffffffff;
val2 -= a; val2 -= b; val2 = (val2 ^ (b>>15)) & 0xffffffff;
return val2;
}
hashval_t
bla (int nunits, int mode)
{
hashval_t hashcode = 0;
hashcode = iterative_hash_host_wide_int (14, hashcode);
hashcode = iterative_hash_host_wide_int (nunits, hashcode);
hashcode = iterative_hash_host_wide_int (mode, hashcode);
if (nunits)
return 0;
else
return hashcode;
}

View File

@ -0,0 +1,20 @@
/* { dg-do compile } */
#define X(new,old) int i ## new = i ## old + i ## old;
#define Y(pfx) X(pfx ## 1, pfx) \
X(pfx ## 2, pfx ## 1) \
X(pfx ## 3, pfx ## 2) \
X(pfx ## 4, pfx ## 3) \
X(pfx ## 5, pfx ## 4) \
X(pfx ## 6, pfx ## 5) \
X(pfx ## 7, pfx ## 6) \
X(pfx ## 8, pfx ## 7) \
X(pfx ## 9, pfx ## 8)
void foo (int i1)
{
Y(1)
Y(11)
Y(111)
asm ("" : : "X" (i1));
}

View File

@ -0,0 +1,25 @@
/* { dg-do run { xfail *-*-* } } */
/* { dg-options "-g -O2" } */
#include "guality.h"
int a;
int foo()
{
int tmp = a;
int tmp2 = a;
int tmp3;
int res;
GUALCHKVAL (a);
GUALCHKVAL (tmp);
GUALCHKVAL (tmp2);
a = 0;
tmp3 = tmp2;
GUALCHKVAL (a);
GUALCHKVAL (tmp);
GUALCHKVAL (tmp2);
GUALCHKVAL (tmp3);
res = tmp - tmp2 + 1;
return res;
}

View File

@ -511,6 +511,10 @@ dequeue_and_dump (dump_info_p di)
dump_child ("cnst", DECL_INITIAL (t));
break;
case DEBUG_EXPR_DECL:
dump_int (di, "-uid", DEBUG_TEMP_UID (t));
/* Fall through. */
case VAR_DECL:
case PARM_DECL:
case FIELD_DECL:

View File

@ -637,10 +637,8 @@ 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 *);
void insert_debug_temps_for_defs (gimple_stmt_iterator *);
void insert_debug_temp_for_var_def (gimple_stmt_iterator *, tree);
void release_defs_bitset (bitmap toremove);
/* In tree-into-ssa.c */

View File

@ -183,6 +183,8 @@ dump_decl_name (pretty_printer *buffer, tree node, int flags)
{
if (TREE_CODE (node) == LABEL_DECL && LABEL_DECL_UID (node) != -1)
pp_printf (buffer, "L.%d", (int) LABEL_DECL_UID (node));
else if (TREE_CODE (node) == DEBUG_EXPR_DECL)
pp_printf (buffer, "D#%i", DEBUG_TEMP_UID (node));
else
{
char c = TREE_CODE (node) == CONST_DECL ? 'C' : 'D';
@ -1051,6 +1053,7 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
case VAR_DECL:
case PARM_DECL:
case FIELD_DECL:
case DEBUG_EXPR_DECL:
case NAMESPACE_DECL:
dump_decl_name (buffer, node, flags);
break;

View File

@ -325,7 +325,13 @@ mark_stmt_if_obviously_necessary (gimple stmt, bool aggressive)
break;
case GIMPLE_DEBUG:
mark_stmt_necessary (stmt, false);
/* Debug temps without a value are not useful. ??? If we could
easily locate the debug temp bind stmt for a use thereof,
would could refrain from marking all debug temps here, and
mark them only if they're used. */
if (gimple_debug_bind_has_value_p (stmt)
|| TREE_CODE (gimple_debug_bind_get_var (stmt)) != DEBUG_EXPR_DECL)
mark_stmt_necessary (stmt, false);
return;
case GIMPLE_GOTO:
@ -1071,7 +1077,7 @@ eliminate_unnecessary_stmts (void)
{
bool something_changed = false;
basic_block bb;
gimple_stmt_iterator gsi;
gimple_stmt_iterator gsi, psi;
gimple stmt;
tree call;
VEC (basic_block, heap) *h;
@ -1111,10 +1117,13 @@ eliminate_unnecessary_stmts (void)
bb = VEC_pop (basic_block, h);
/* Remove dead statements. */
for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi);)
for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi = psi)
{
stmt = gsi_stmt (gsi);
psi = gsi;
gsi_prev (&psi);
stats.total++;
/* If GSI is not necessary then remove it. */
@ -1122,14 +1131,6 @@ 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))
{
@ -1159,10 +1160,7 @@ eliminate_unnecessary_stmts (void)
}
notice_special_calls (stmt);
}
gsi_prev (&gsi);
}
else
gsi_prev (&gsi);
}
}

View File

@ -939,7 +939,6 @@ forward_propagate_addr_expr (tree name, tree rhs)
gimple use_stmt;
bool all = true;
bool single_use_p = has_single_use (name);
bool debug = false;
FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
{
@ -950,9 +949,7 @@ forward_propagate_addr_expr (tree name, tree rhs)
there is nothing we can do. */
if (gimple_code (use_stmt) != GIMPLE_ASSIGN)
{
if (is_gimple_debug (use_stmt))
debug = true;
else
if (!is_gimple_debug (use_stmt))
all = false;
continue;
}
@ -995,9 +992,6 @@ forward_propagate_addr_expr (tree name, tree rhs)
}
}
if (all && debug)
propagate_var_def_into_debug_stmts (name, NULL, NULL);
return all;
}

View File

@ -764,6 +764,7 @@ rewrite_reciprocal (gimple_stmt_iterator *bsi)
gimple stmt, stmt1, stmt2;
tree var, name, lhs, type;
tree real_one;
gimple_stmt_iterator gsi;
stmt = gsi_stmt (*bsi);
lhs = gimple_assign_lhs (stmt);
@ -798,8 +799,9 @@ rewrite_reciprocal (gimple_stmt_iterator *bsi)
/* Replace division stmt with reciprocal and multiply stmts.
The multiply stmt is not invariant, so update iterator
and avoid rescanning. */
gsi_replace (bsi, stmt1, true);
gsi_insert_after (bsi, stmt2, GSI_NEW_STMT);
gsi = *bsi;
gsi_insert_before (bsi, stmt1, GSI_NEW_STMT);
gsi_replace (&gsi, stmt2, true);
/* Continue processing with invariant reciprocal statement. */
return stmt1;
@ -858,6 +860,8 @@ rewrite_bittest (gimple_stmt_iterator *bsi)
if (outermost_invariant_loop (b, loop_containing_stmt (stmt1)) != NULL
&& outermost_invariant_loop (a, loop_containing_stmt (stmt1)) == NULL)
{
gimple_stmt_iterator rsi;
/* 1 << B */
var = create_tmp_var (TREE_TYPE (a), "shifttmp");
add_referenced_var (var);
@ -878,9 +882,14 @@ rewrite_bittest (gimple_stmt_iterator *bsi)
SET_USE (use, name);
gimple_cond_set_rhs (use_stmt, build_int_cst_type (TREE_TYPE (name), 0));
gsi_insert_before (bsi, stmt1, GSI_SAME_STMT);
propagate_defs_into_debug_stmts (gsi_stmt (*bsi), NULL, NULL);
gsi_replace (bsi, stmt2, true);
/* Don't use gsi_replace here, none of the new assignments sets
the variable originally set in stmt. Move bsi to stmt1, and
then remove the original stmt, so that we get a chance to
retain debug info for it. */
rsi = *bsi;
gsi_insert_before (bsi, stmt1, GSI_NEW_STMT);
gsi_insert_before (&rsi, stmt2, GSI_SAME_STMT);
gsi_remove (&rsi, true);
return stmt1;
}
@ -1060,7 +1069,6 @@ 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);
propagate_defs_into_debug_stmts (gsi_stmt (bsi), NULL, NULL);
gsi_remove (&bsi, false);
}
}

View File

@ -894,6 +894,10 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags)
add_stmt_operand (expr_p, stmt, flags);
return;
case DEBUG_EXPR_DECL:
gcc_assert (gimple_debug_bind_p (stmt));
return;
case MISALIGNED_INDIRECT_REF:
get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
/* fall through */

View File

@ -1405,7 +1405,6 @@ rewrite_expr_tree (gimple stmt, unsigned int opindex,
{
stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt1));
gsirhs1 = gsi_for_stmt (stmt2);
propagate_defs_into_debug_stmts (stmt2, gimple_bb (stmt), &gsinow);
gsi_move_before (&gsirhs1, &gsinow);
gsi_prev (&gsinow);
stmt1 = stmt2;
@ -1452,7 +1451,6 @@ linearize_expr (gimple stmt)
gsinow = gsi_for_stmt (stmt);
gsirhs = gsi_for_stmt (binrhs);
propagate_defs_into_debug_stmts (binrhs, gimple_bb (stmt), &gsinow);
gsi_move_before (&gsirhs, &gsinow);
gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs));

View File

@ -385,9 +385,6 @@ statement_sink_location (gimple stmt, basic_block frombb,
*togsi = gsi_after_labels (commondom);
if (debug_stmts)
propagate_defs_into_debug_stmts (stmt, commondom, togsi);
return true;
}
@ -406,8 +403,6 @@ statement_sink_location (gimple stmt, basic_block frombb,
*togsi = gsi_for_stmt (use);
propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
return true;
}
@ -441,8 +436,6 @@ statement_sink_location (gimple stmt, basic_block frombb,
*togsi = gsi_after_labels (sinkbb);
propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
return true;
}

View File

@ -295,152 +295,198 @@ find_released_ssa_name (tree *tp, int *walk_subtrees, void *data_)
return NULL_TREE;
}
/* Given a VAR whose definition STMT is to be moved to the iterator
position TOGSIP in the TOBB basic block, verify whether we're
moving it across any of the debug statements that use it, and
adjust them as needed. If TOBB is NULL, then the definition is
understood as being removed, and TOGSIP is unused. */
/* Insert a DEBUG BIND stmt before the DEF of VAR if VAR is referenced
by other DEBUG stmts, and replace uses of the DEF with the
newly-created debug temp. */
void
propagate_var_def_into_debug_stmts (tree var,
basic_block tobb,
const gimple_stmt_iterator *togsip)
insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var)
{
imm_use_iterator imm_iter;
gimple stmt;
use_operand_p use_p;
gimple stmt;
gimple def_stmt = NULL;
int usecount = 0;
tree value = NULL;
bool no_value = false;
if (!MAY_HAVE_DEBUG_STMTS)
return;
FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
/* First of all, check whether there are debug stmts that reference
this variable and, if there are, decide whether we should use a
debug temp. */
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
{
basic_block bb;
gimple_stmt_iterator si;
stmt = USE_STMT (use_p);
if (!is_gimple_debug (stmt))
if (!gimple_debug_bind_p (stmt))
continue;
if (tobb)
if (usecount++)
break;
if (gimple_debug_bind_get_value (stmt) != var)
{
bb = gimple_bb (stmt);
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;
}
/* Count this as an additional use, so as to make sure we
use a temp unless VAR's definition has a SINGLE_RHS that
can be shared. */
usecount++;
break;
}
}
/* Here we compute (lazily) the value assigned to VAR, but we
remember if we tried before and failed, so that we don't try
again. */
if (!value && !no_value)
if (!usecount)
return;
if (gsi)
def_stmt = gsi_stmt (*gsi);
else
def_stmt = SSA_NAME_DEF_STMT (var);
/* If we didn't get an insertion point, and the stmt has already
been removed, we won't be able to insert the debug bind stmt, so
we'll have to drop debug information. */
if (is_gimple_assign (def_stmt))
{
bool no_value = false;
if (!dom_info_available_p (CDI_DOMINATORS))
{
gimple def_stmt = SSA_NAME_DEF_STMT (var);
struct walk_stmt_info wi;
if (is_gimple_assign (def_stmt))
{
if (!dom_info_available_p (CDI_DOMINATORS))
{
struct walk_stmt_info wi;
memset (&wi, 0, sizeof (wi));
memset (&wi, 0, sizeof (wi));
/* When removing blocks without following reverse dominance
order, we may sometimes encounter SSA_NAMEs that have
already been released, referenced in other SSA_DEFs that
we're about to release. Consider:
/* When removing blocks without following reverse
dominance order, we may sometimes encounter SSA_NAMEs
that have already been released, referenced in other
SSA_DEFs that we're about to release. Consider:
<bb X>:
v_1 = foo;
<bb X>:
v_1 = foo;
<bb Y>:
w_2 = v_1 + bar;
# DEBUG w => w_2
<bb Y>:
w_2 = v_1 + bar;
# DEBUG w => w_2
If we deleted BB X first, propagating the value of w_2
won't do us any good. It's too late to recover their
original definition of v_1: when it was deleted, it was
only referenced in other DEFs, it couldn't possibly know
it should have been retained, and propagating every
single DEF just in case it might have to be propagated
into a DEBUG STMT would probably be too wasteful.
If we deleted BB X first, propagating the value of
w_2 won't do us any good. It's too late to recover
their original definition of v_1: when it was
deleted, it was only referenced in other DEFs, it
couldn't possibly know it should have been retained,
and propagating every single DEF just in case it
might have to be propagated into a DEBUG STMT would
probably be too wasteful.
When dominator information is not readily
available, we check for and accept some loss of
debug information. But if it is available,
there's no excuse for us to remove blocks in the
wrong order, so we don't even check for dead SSA
NAMEs. SSA verification shall catch any
errors. */
if (!walk_gimple_op (def_stmt, find_released_ssa_name, &wi))
no_value = true;
}
if (!no_value)
value = gimple_assign_rhs_to_tree (def_stmt);
}
if (!value)
When dominator information is not readily available, we
check for and accept some loss of debug information. But
if it is available, there's no excuse for us to remove
blocks in the wrong order, so we don't even check for
dead SSA NAMEs. SSA verification shall catch any
errors. */
if ((!gsi && !gimple_bb (def_stmt))
|| !walk_gimple_op (def_stmt, find_released_ssa_name,
&wi))
no_value = true;
}
if (no_value)
gimple_debug_bind_reset_value (stmt);
if (!no_value)
value = gimple_assign_rhs_to_tree (def_stmt);
}
if (value)
{
/* If there's a single use of VAR, and VAR is the entire debug
expression (usecount would have been incremented again
otherwise), and the definition involves only constants and
SSA names, then we can propagate VALUE into this single use,
avoiding the temp.
We can also avoid using a temp if VALUE can be shared and
propagated into all uses, without generating expressions that
wouldn't be valid gimple RHSs.
Other cases that would require unsharing or non-gimple RHSs
are deferred to a debug temp, although we could avoid temps
at the expense of duplication of expressions. */
if (CONSTANT_CLASS_P (value)
|| (usecount == 1
&& (!gimple_assign_single_p (def_stmt)
|| is_gimple_min_invariant (value)))
|| is_gimple_reg (value))
value = unshare_expr (value);
else
{
gimple def_temp;
tree vexpr = make_node (DEBUG_EXPR_DECL);
def_temp = gimple_build_debug_bind (vexpr,
unshare_expr (value),
def_stmt);
DECL_ARTIFICIAL (vexpr) = 1;
TREE_TYPE (vexpr) = TREE_TYPE (value);
if (DECL_P (value))
DECL_MODE (vexpr) = DECL_MODE (value);
else
DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (value));
if (gsi)
gsi_insert_before (gsi, def_temp, GSI_SAME_STMT);
else
{
gimple_stmt_iterator ngsi = gsi_for_stmt (def_stmt);
gsi_insert_before (&ngsi, def_temp, GSI_SAME_STMT);
}
value = vexpr;
}
}
FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
{
if (!gimple_debug_bind_p (stmt))
continue;
if (value)
FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
SET_USE (use_p, unshare_expr (value));
/* unshare_expr is not needed here. vexpr is either a
SINGLE_RHS, that can be safely shared, some other RHS
that was unshared when we found it had a single debug
use, or a DEBUG_EXPR_DECL, that can be safely
shared. */
SET_USE (use_p, value);
else
gimple_debug_bind_reset_value (stmt);
update_stmt (stmt);
}
}
/* Given a STMT to be moved to the iterator position TOBSIP in the
TOBB basic block, verify whether we're moving it across any of the
debug statements that use it. If TOBB is NULL, then the definition
is understood as being removed, and TOBSIP is unused. */
/* Insert a DEBUG BIND stmt before STMT for each DEF referenced by
other DEBUG stmts, and replace uses of the DEF with the
newly-created debug temp. */
void
propagate_defs_into_debug_stmts (gimple def, basic_block tobb,
const gimple_stmt_iterator *togsip)
insert_debug_temps_for_defs (gimple_stmt_iterator *gsi)
{
gimple stmt;
ssa_op_iter op_iter;
def_operand_p def_p;
if (!MAY_HAVE_DEBUG_STMTS)
return;
FOR_EACH_SSA_DEF_OPERAND (def_p, def, op_iter, SSA_OP_DEF)
stmt = gsi_stmt (*gsi);
FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, op_iter, SSA_OP_DEF)
{
tree var = DEF_FROM_PTR (def_p);
if (TREE_CODE (var) != SSA_NAME)
continue;
propagate_var_def_into_debug_stmts (var, tobb, togsip);
insert_debug_temp_for_var_def (gsi, var);
}
}

View File

@ -206,7 +206,7 @@ release_ssa_name (tree var)
use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var));
if (MAY_HAVE_DEBUG_STMTS)
propagate_var_def_into_debug_stmts (var, NULL, NULL);
insert_debug_temp_for_var_def (NULL, var);
#ifdef ENABLE_CHECKING
verify_imm_links (stderr, var);

View File

@ -152,6 +152,9 @@ static const char * const tree_node_kind_names[] = {
static GTY(()) int next_decl_uid;
/* Unique id for next type created. */
static GTY(()) int next_type_uid = 1;
/* Unique id for next debug decl created. Use negative numbers,
to catch erroneous uses. */
static GTY(()) int next_debug_decl_uid;
/* Since we cannot rehash a type after it is in the table, we have to
keep the hash code. */
@ -872,7 +875,10 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
DECL_ALIGN (t) = 1;
}
DECL_SOURCE_LOCATION (t) = input_location;
DECL_UID (t) = next_decl_uid++;
if (TREE_CODE (t) == DEBUG_EXPR_DECL)
DECL_UID (t) = --next_debug_decl_uid;
else
DECL_UID (t) = next_decl_uid++;
if (TREE_CODE (t) == LABEL_DECL)
LABEL_DECL_UID (t) = -1;
@ -948,7 +954,10 @@ copy_node_stat (tree node MEM_STAT_DECL)
if (TREE_CODE_CLASS (code) == tcc_declaration)
{
DECL_UID (t) = next_decl_uid++;
if (code == DEBUG_EXPR_DECL)
DECL_UID (t) = --next_debug_decl_uid;
else
DECL_UID (t) = next_decl_uid++;
if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL)
&& DECL_HAS_VALUE_EXPR_P (node))
{

View File

@ -351,6 +351,10 @@ DEFTREECODE (PARM_DECL, "parm_decl", tcc_declaration, 0)
DEFTREECODE (TYPE_DECL, "type_decl", tcc_declaration, 0)
DEFTREECODE (RESULT_DECL, "result_decl", tcc_declaration, 0)
/* A "declaration" of a debug temporary. It should only appear in
DEBUG stmts. */
DEFTREECODE (DEBUG_EXPR_DECL, "debug_expr_decl", tcc_declaration, 0)
/* A namespace declaration. Namespaces appear in DECL_CONTEXT of other
_DECLs, providing a hierarchy of names. */
DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0)

View File

@ -2455,6 +2455,10 @@ struct function;
/* Every ..._DECL node gets a unique number. */
#define DECL_UID(NODE) (DECL_MINIMAL_CHECK (NODE)->decl_minimal.uid)
/* DEBUG_EXPR_DECLs get negative UID numbers, to catch erroneous
uses. */
#define DEBUG_TEMP_UID(NODE) (-DECL_UID (TREE_CHECK ((NODE), DEBUG_EXPR_DECL)))
/* These two fields describe where in the source code the declaration
was. If the declaration appears in several places (as for a C
function that is declared first and then defined later), this

View File

@ -732,6 +732,7 @@ dv_is_decl_p (decl_or_value dv)
case (int)PARM_DECL:
case (int)RESULT_DECL:
case (int)FUNCTION_DECL:
case (int)DEBUG_EXPR_DECL:
case (int)COMPONENT_REF:
return true;
@ -2222,7 +2223,7 @@ dataflow_set_union (dataflow_set *dst, dataflow_set *src)
/* Whether the value is currently being expanded. */
#define VALUE_RECURSED_INTO(x) \
(RTL_FLAG_CHECK1 ("VALUE_RECURSED_INTO", (x), VALUE)->used)
(RTL_FLAG_CHECK2 ("VALUE_RECURSED_INTO", (x), VALUE, DEBUG_EXPR)->used)
/* Whether the value is in changed_variables hash table. */
#define VALUE_CHANGED(x) \
(RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
@ -4112,6 +4113,9 @@ track_expr_p (tree expr, bool need_rtl)
rtx decl_rtl;
tree realdecl;
if (TREE_CODE (expr) == DEBUG_EXPR_DECL)
return DECL_RTL_SET_P (expr);
/* If EXPR is not a parameter or a variable do not track it. */
if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
return 0;
@ -6271,11 +6275,12 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
decl_or_value dv;
variable var;
location_chain loc;
rtx result;
rtx result, subreg, xret;
if (GET_CODE (x) == SUBREG)
switch (GET_CODE (x))
{
rtx subreg = SUBREG_REG (x);
case SUBREG:
subreg = SUBREG_REG (x);
if (GET_CODE (SUBREG_REG (x)) != VALUE)
return x;
@ -6297,22 +6302,31 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
return result;
case DEBUG_EXPR:
dv = dv_from_decl (XTREE (x, 0));
xret = NULL;
break;
case VALUE:
dv = dv_from_value (x);
xret = x;
break;
default:
return x;
}
if (GET_CODE (x) != VALUE)
return x;
if (VALUE_RECURSED_INTO (x))
return x;
return NULL;
dv = dv_from_value (x);
var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
if (!var)
return x;
return xret;
if (var->n_var_parts == 0)
return x;
return xret;
gcc_assert (var->n_var_parts == 1);
@ -6332,7 +6346,7 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
if (result)
return result;
else
return x;
return xret;
}
/* Expand VALUEs in LOC, using VARS as well as cselib's equivalence
@ -6382,6 +6396,9 @@ emit_note_insn_var_location (void **varp, void *data)
decl = dv_as_decl (var->dv);
if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
goto clear;
gcc_assert (decl);
complete = true;