mirror of git://gcc.gnu.org/git/gcc.git
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:
parent
2e723874b5
commit
0ca5af51ab
|
@ -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>
|
2009-10-12 Hans-Peter Nilsson <hp@axis.com>
|
||||||
|
|
||||||
PR target/26515
|
PR target/26515
|
||||||
|
|
|
@ -2361,6 +2361,18 @@ expand_debug_expr (tree exp)
|
||||||
op1 = wrap_constant (GET_MODE_INNER (mode), op1);
|
op1 = wrap_constant (GET_MODE_INNER (mode), op1);
|
||||||
return gen_rtx_CONCAT (mode, op0, 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 VAR_DECL:
|
||||||
case PARM_DECL:
|
case PARM_DECL:
|
||||||
case FUNCTION_DECL:
|
case FUNCTION_DECL:
|
||||||
|
|
12
gcc/cselib.c
12
gcc/cselib.c
|
@ -585,6 +585,7 @@ rtx_equal_for_cselib_p (rtx x, rtx y)
|
||||||
{
|
{
|
||||||
case CONST_DOUBLE:
|
case CONST_DOUBLE:
|
||||||
case CONST_FIXED:
|
case CONST_FIXED:
|
||||||
|
case DEBUG_EXPR:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case LABEL_REF:
|
case LABEL_REF:
|
||||||
|
@ -703,6 +704,10 @@ cselib_hash_rtx (rtx x, int create)
|
||||||
|
|
||||||
return e->value;
|
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:
|
case CONST_INT:
|
||||||
hash += ((unsigned) CONST_INT << 7) + INTVAL (x);
|
hash += ((unsigned) CONST_INT << 7) + INTVAL (x);
|
||||||
return hash ? hash : (unsigned int) CONST_INT;
|
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);
|
result = expand_loc (CSELIB_VAL_PTR (orig)->locs, evd, max_depth);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case DEBUG_EXPR:
|
||||||
|
if (evd->callback)
|
||||||
|
return evd->callback (orig, evd->regs_active, max_depth,
|
||||||
|
evd->callback_arg);
|
||||||
|
return orig;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2393,6 +2393,8 @@ verify_rtx_sharing (rtx orig, rtx insn)
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case REG:
|
case REG:
|
||||||
|
case DEBUG_EXPR:
|
||||||
|
case VALUE:
|
||||||
case CONST_INT:
|
case CONST_INT:
|
||||||
case CONST_DOUBLE:
|
case CONST_DOUBLE:
|
||||||
case CONST_FIXED:
|
case CONST_FIXED:
|
||||||
|
@ -2593,6 +2595,8 @@ repeat:
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case REG:
|
case REG:
|
||||||
|
case DEBUG_EXPR:
|
||||||
|
case VALUE:
|
||||||
case CONST_INT:
|
case CONST_INT:
|
||||||
case CONST_DOUBLE:
|
case CONST_DOUBLE:
|
||||||
case CONST_FIXED:
|
case CONST_FIXED:
|
||||||
|
@ -2712,6 +2716,8 @@ repeat:
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case REG:
|
case REG:
|
||||||
|
case DEBUG_EXPR:
|
||||||
|
case VALUE:
|
||||||
case CONST_INT:
|
case CONST_INT:
|
||||||
case CONST_DOUBLE:
|
case CONST_DOUBLE:
|
||||||
case CONST_FIXED:
|
case CONST_FIXED:
|
||||||
|
@ -2783,6 +2789,8 @@ set_used_flags (rtx x)
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case REG:
|
case REG:
|
||||||
|
case DEBUG_EXPR:
|
||||||
|
case VALUE:
|
||||||
case CONST_INT:
|
case CONST_INT:
|
||||||
case CONST_DOUBLE:
|
case CONST_DOUBLE:
|
||||||
case CONST_FIXED:
|
case CONST_FIXED:
|
||||||
|
|
|
@ -1117,6 +1117,8 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
|
||||||
t = scalar_tp, subname = "rt_int";
|
t = scalar_tp, subname = "rt_int";
|
||||||
else if (i == VALUE && aindex == 0)
|
else if (i == VALUE && aindex == 0)
|
||||||
t = scalar_tp, subname = "rt_int";
|
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)
|
else if (i == REG && aindex == 1)
|
||||||
t = scalar_tp, subname = "rt_int";
|
t = scalar_tp, subname = "rt_int";
|
||||||
else if (i == REG && aindex == 2)
|
else if (i == REG && aindex == 2)
|
||||||
|
|
|
@ -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
|
/* Replace the statement pointed-to by GSI to STMT. If UPDATE_EH_INFO
|
||||||
is true, the exception handling information of the original
|
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
|
void
|
||||||
gsi_replace (gimple_stmt_iterator *gsi, gimple stmt, bool update_eh_info)
|
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)
|
if (stmt == orig_stmt)
|
||||||
return;
|
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_location (stmt, gimple_location (orig_stmt));
|
||||||
gimple_set_bb (stmt, gsi_bb (*gsi));
|
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_seq_node cur, next, prev;
|
||||||
gimple stmt = gsi_stmt (*i);
|
gimple stmt = gsi_stmt (*i);
|
||||||
|
|
||||||
|
insert_debug_temps_for_defs (i);
|
||||||
|
|
||||||
/* Free all the data flow information for STMT. */
|
/* Free all the data flow information for STMT. */
|
||||||
gimple_set_bb (stmt, NULL);
|
gimple_set_bb (stmt, NULL);
|
||||||
delink_stmt_imm_use (stmt);
|
delink_stmt_imm_use (stmt);
|
||||||
|
|
|
@ -316,6 +316,12 @@ print_rtx (const_rtx in_rtx)
|
||||||
fprintf (outfile, " %i", val->value);
|
fprintf (outfile, " %i", val->value);
|
||||||
dump_addr (outfile, " @", in_rtx);
|
dump_addr (outfile, " @", in_rtx);
|
||||||
dump_addr (outfile, "/", (void*)val);
|
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
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -232,6 +232,8 @@ copy_rtx (rtx orig)
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case REG:
|
case REG:
|
||||||
|
case DEBUG_EXPR:
|
||||||
|
case VALUE:
|
||||||
case CONST_INT:
|
case CONST_INT:
|
||||||
case CONST_DOUBLE:
|
case CONST_DOUBLE:
|
||||||
case CONST_FIXED:
|
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:
|
case SYMBOL_REF:
|
||||||
return XSTR (x, 0) == XSTR (y, 0);
|
return XSTR (x, 0) == XSTR (y, 0);
|
||||||
|
|
||||||
|
case DEBUG_EXPR:
|
||||||
case VALUE:
|
case VALUE:
|
||||||
case SCRATCH:
|
case SCRATCH:
|
||||||
case CONST_DOUBLE:
|
case CONST_DOUBLE:
|
||||||
|
@ -496,6 +499,7 @@ rtx_equal_p (const_rtx x, const_rtx y)
|
||||||
case SYMBOL_REF:
|
case SYMBOL_REF:
|
||||||
return XSTR (x, 0) == XSTR (y, 0);
|
return XSTR (x, 0) == XSTR (y, 0);
|
||||||
|
|
||||||
|
case DEBUG_EXPR:
|
||||||
case VALUE:
|
case VALUE:
|
||||||
case SCRATCH:
|
case SCRATCH:
|
||||||
case CONST_DOUBLE:
|
case CONST_DOUBLE:
|
||||||
|
|
|
@ -88,6 +88,10 @@ DEF_RTL_EXPR(UNKNOWN, "UnKnown", "*", RTX_EXTRA)
|
||||||
DECL codes in trees. */
|
DECL codes in trees. */
|
||||||
DEF_RTL_EXPR(VALUE, "value", "0", RTX_OBJ)
|
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.
|
Expressions used in constructing lists.
|
||||||
--------------------------------------------------------------------- */
|
--------------------------------------------------------------------- */
|
||||||
|
|
|
@ -521,6 +521,10 @@ print_value (char *buf, const_rtx x, int verbose)
|
||||||
cur = safe_concat (buf, cur, t);
|
cur = safe_concat (buf, cur, t);
|
||||||
cur = safe_concat (buf, cur, "]");
|
cur = safe_concat (buf, cur, "]");
|
||||||
break;
|
break;
|
||||||
|
case DEBUG_EXPR:
|
||||||
|
sprintf (t, "D#%i", DEBUG_TEMP_UID (XTREE (x, 0)));
|
||||||
|
cur = safe_concat (buf, cur, t);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
print_exp (t, x, verbose);
|
print_exp (t, x, verbose);
|
||||||
cur = safe_concat (buf, cur, t);
|
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)))
|
if (DECL_P (INSN_VAR_LOCATION_DECL (insn)))
|
||||||
{
|
{
|
||||||
tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (insn));
|
tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (insn));
|
||||||
|
char idbuf[32];
|
||||||
if (id)
|
if (id)
|
||||||
name = IDENTIFIER_POINTER (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
|
else
|
||||||
{
|
{
|
||||||
char idbuf[32];
|
|
||||||
sprintf (idbuf, "D.%i",
|
sprintf (idbuf, "D.%i",
|
||||||
DECL_UID (INSN_VAR_LOCATION_DECL (insn)));
|
DECL_UID (INSN_VAR_LOCATION_DECL (insn)));
|
||||||
name = idbuf;
|
name = idbuf;
|
||||||
|
|
|
@ -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>
|
2009-10-12 Hans-Peter Nilsson <hp@axis.com>
|
||||||
|
|
||||||
PR target/26515
|
PR target/26515
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -511,6 +511,10 @@ dequeue_and_dump (dump_info_p di)
|
||||||
dump_child ("cnst", DECL_INITIAL (t));
|
dump_child ("cnst", DECL_INITIAL (t));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DEBUG_EXPR_DECL:
|
||||||
|
dump_int (di, "-uid", DEBUG_TEMP_UID (t));
|
||||||
|
/* Fall through. */
|
||||||
|
|
||||||
case VAR_DECL:
|
case VAR_DECL:
|
||||||
case PARM_DECL:
|
case PARM_DECL:
|
||||||
case FIELD_DECL:
|
case FIELD_DECL:
|
||||||
|
|
|
@ -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);
|
extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
|
||||||
|
|
||||||
void propagate_defs_into_debug_stmts (gimple, basic_block,
|
void insert_debug_temps_for_defs (gimple_stmt_iterator *);
|
||||||
const gimple_stmt_iterator *);
|
void insert_debug_temp_for_var_def (gimple_stmt_iterator *, tree);
|
||||||
void propagate_var_def_into_debug_stmts (tree, basic_block,
|
|
||||||
const gimple_stmt_iterator *);
|
|
||||||
void release_defs_bitset (bitmap toremove);
|
void release_defs_bitset (bitmap toremove);
|
||||||
|
|
||||||
/* In tree-into-ssa.c */
|
/* In tree-into-ssa.c */
|
||||||
|
|
|
@ -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)
|
if (TREE_CODE (node) == LABEL_DECL && LABEL_DECL_UID (node) != -1)
|
||||||
pp_printf (buffer, "L.%d", (int) LABEL_DECL_UID (node));
|
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
|
else
|
||||||
{
|
{
|
||||||
char c = TREE_CODE (node) == CONST_DECL ? 'C' : 'D';
|
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 VAR_DECL:
|
||||||
case PARM_DECL:
|
case PARM_DECL:
|
||||||
case FIELD_DECL:
|
case FIELD_DECL:
|
||||||
|
case DEBUG_EXPR_DECL:
|
||||||
case NAMESPACE_DECL:
|
case NAMESPACE_DECL:
|
||||||
dump_decl_name (buffer, node, flags);
|
dump_decl_name (buffer, node, flags);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -325,7 +325,13 @@ mark_stmt_if_obviously_necessary (gimple stmt, bool aggressive)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GIMPLE_DEBUG:
|
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;
|
return;
|
||||||
|
|
||||||
case GIMPLE_GOTO:
|
case GIMPLE_GOTO:
|
||||||
|
@ -1071,7 +1077,7 @@ eliminate_unnecessary_stmts (void)
|
||||||
{
|
{
|
||||||
bool something_changed = false;
|
bool something_changed = false;
|
||||||
basic_block bb;
|
basic_block bb;
|
||||||
gimple_stmt_iterator gsi;
|
gimple_stmt_iterator gsi, psi;
|
||||||
gimple stmt;
|
gimple stmt;
|
||||||
tree call;
|
tree call;
|
||||||
VEC (basic_block, heap) *h;
|
VEC (basic_block, heap) *h;
|
||||||
|
@ -1111,10 +1117,13 @@ eliminate_unnecessary_stmts (void)
|
||||||
bb = VEC_pop (basic_block, h);
|
bb = VEC_pop (basic_block, h);
|
||||||
|
|
||||||
/* Remove dead statements. */
|
/* 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);
|
stmt = gsi_stmt (gsi);
|
||||||
|
|
||||||
|
psi = gsi;
|
||||||
|
gsi_prev (&psi);
|
||||||
|
|
||||||
stats.total++;
|
stats.total++;
|
||||||
|
|
||||||
/* If GSI is not necessary then remove it. */
|
/* If GSI is not necessary then remove it. */
|
||||||
|
@ -1122,14 +1131,6 @@ eliminate_unnecessary_stmts (void)
|
||||||
{
|
{
|
||||||
remove_dead_stmt (&gsi, bb);
|
remove_dead_stmt (&gsi, bb);
|
||||||
something_changed = true;
|
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))
|
else if (is_gimple_call (stmt))
|
||||||
{
|
{
|
||||||
|
@ -1159,10 +1160,7 @@ eliminate_unnecessary_stmts (void)
|
||||||
}
|
}
|
||||||
notice_special_calls (stmt);
|
notice_special_calls (stmt);
|
||||||
}
|
}
|
||||||
gsi_prev (&gsi);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
gsi_prev (&gsi);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -939,7 +939,6 @@ forward_propagate_addr_expr (tree name, tree rhs)
|
||||||
gimple use_stmt;
|
gimple use_stmt;
|
||||||
bool all = true;
|
bool all = true;
|
||||||
bool single_use_p = has_single_use (name);
|
bool single_use_p = has_single_use (name);
|
||||||
bool debug = false;
|
|
||||||
|
|
||||||
FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
|
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. */
|
there is nothing we can do. */
|
||||||
if (gimple_code (use_stmt) != GIMPLE_ASSIGN)
|
if (gimple_code (use_stmt) != GIMPLE_ASSIGN)
|
||||||
{
|
{
|
||||||
if (is_gimple_debug (use_stmt))
|
if (!is_gimple_debug (use_stmt))
|
||||||
debug = true;
|
|
||||||
else
|
|
||||||
all = false;
|
all = false;
|
||||||
continue;
|
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;
|
return all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -764,6 +764,7 @@ rewrite_reciprocal (gimple_stmt_iterator *bsi)
|
||||||
gimple stmt, stmt1, stmt2;
|
gimple stmt, stmt1, stmt2;
|
||||||
tree var, name, lhs, type;
|
tree var, name, lhs, type;
|
||||||
tree real_one;
|
tree real_one;
|
||||||
|
gimple_stmt_iterator gsi;
|
||||||
|
|
||||||
stmt = gsi_stmt (*bsi);
|
stmt = gsi_stmt (*bsi);
|
||||||
lhs = gimple_assign_lhs (stmt);
|
lhs = gimple_assign_lhs (stmt);
|
||||||
|
@ -798,8 +799,9 @@ rewrite_reciprocal (gimple_stmt_iterator *bsi)
|
||||||
/* Replace division stmt with reciprocal and multiply stmts.
|
/* Replace division stmt with reciprocal and multiply stmts.
|
||||||
The multiply stmt is not invariant, so update iterator
|
The multiply stmt is not invariant, so update iterator
|
||||||
and avoid rescanning. */
|
and avoid rescanning. */
|
||||||
gsi_replace (bsi, stmt1, true);
|
gsi = *bsi;
|
||||||
gsi_insert_after (bsi, stmt2, GSI_NEW_STMT);
|
gsi_insert_before (bsi, stmt1, GSI_NEW_STMT);
|
||||||
|
gsi_replace (&gsi, stmt2, true);
|
||||||
|
|
||||||
/* Continue processing with invariant reciprocal statement. */
|
/* Continue processing with invariant reciprocal statement. */
|
||||||
return stmt1;
|
return stmt1;
|
||||||
|
@ -858,6 +860,8 @@ rewrite_bittest (gimple_stmt_iterator *bsi)
|
||||||
if (outermost_invariant_loop (b, loop_containing_stmt (stmt1)) != NULL
|
if (outermost_invariant_loop (b, loop_containing_stmt (stmt1)) != NULL
|
||||||
&& outermost_invariant_loop (a, loop_containing_stmt (stmt1)) == NULL)
|
&& outermost_invariant_loop (a, loop_containing_stmt (stmt1)) == NULL)
|
||||||
{
|
{
|
||||||
|
gimple_stmt_iterator rsi;
|
||||||
|
|
||||||
/* 1 << B */
|
/* 1 << B */
|
||||||
var = create_tmp_var (TREE_TYPE (a), "shifttmp");
|
var = create_tmp_var (TREE_TYPE (a), "shifttmp");
|
||||||
add_referenced_var (var);
|
add_referenced_var (var);
|
||||||
|
@ -878,9 +882,14 @@ rewrite_bittest (gimple_stmt_iterator *bsi)
|
||||||
SET_USE (use, name);
|
SET_USE (use, name);
|
||||||
gimple_cond_set_rhs (use_stmt, build_int_cst_type (TREE_TYPE (name), 0));
|
gimple_cond_set_rhs (use_stmt, build_int_cst_type (TREE_TYPE (name), 0));
|
||||||
|
|
||||||
gsi_insert_before (bsi, stmt1, GSI_SAME_STMT);
|
/* Don't use gsi_replace here, none of the new assignments sets
|
||||||
propagate_defs_into_debug_stmts (gsi_stmt (*bsi), NULL, NULL);
|
the variable originally set in stmt. Move bsi to stmt1, and
|
||||||
gsi_replace (bsi, stmt2, true);
|
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;
|
return stmt1;
|
||||||
}
|
}
|
||||||
|
@ -1060,7 +1069,6 @@ move_computations_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED,
|
||||||
|
|
||||||
mark_virtual_ops_for_renaming (stmt);
|
mark_virtual_ops_for_renaming (stmt);
|
||||||
gsi_insert_on_edge (loop_preheader_edge (level), stmt);
|
gsi_insert_on_edge (loop_preheader_edge (level), stmt);
|
||||||
propagate_defs_into_debug_stmts (gsi_stmt (bsi), NULL, NULL);
|
|
||||||
gsi_remove (&bsi, false);
|
gsi_remove (&bsi, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -894,6 +894,10 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags)
|
||||||
add_stmt_operand (expr_p, stmt, flags);
|
add_stmt_operand (expr_p, stmt, flags);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case DEBUG_EXPR_DECL:
|
||||||
|
gcc_assert (gimple_debug_bind_p (stmt));
|
||||||
|
return;
|
||||||
|
|
||||||
case MISALIGNED_INDIRECT_REF:
|
case MISALIGNED_INDIRECT_REF:
|
||||||
get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
|
get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
|
@ -1405,7 +1405,6 @@ rewrite_expr_tree (gimple stmt, unsigned int opindex,
|
||||||
{
|
{
|
||||||
stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt1));
|
stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt1));
|
||||||
gsirhs1 = gsi_for_stmt (stmt2);
|
gsirhs1 = gsi_for_stmt (stmt2);
|
||||||
propagate_defs_into_debug_stmts (stmt2, gimple_bb (stmt), &gsinow);
|
|
||||||
gsi_move_before (&gsirhs1, &gsinow);
|
gsi_move_before (&gsirhs1, &gsinow);
|
||||||
gsi_prev (&gsinow);
|
gsi_prev (&gsinow);
|
||||||
stmt1 = stmt2;
|
stmt1 = stmt2;
|
||||||
|
@ -1452,7 +1451,6 @@ linearize_expr (gimple stmt)
|
||||||
|
|
||||||
gsinow = gsi_for_stmt (stmt);
|
gsinow = gsi_for_stmt (stmt);
|
||||||
gsirhs = gsi_for_stmt (binrhs);
|
gsirhs = gsi_for_stmt (binrhs);
|
||||||
propagate_defs_into_debug_stmts (binrhs, gimple_bb (stmt), &gsinow);
|
|
||||||
gsi_move_before (&gsirhs, &gsinow);
|
gsi_move_before (&gsirhs, &gsinow);
|
||||||
|
|
||||||
gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs));
|
gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs));
|
||||||
|
|
|
@ -385,9 +385,6 @@ statement_sink_location (gimple stmt, basic_block frombb,
|
||||||
|
|
||||||
*togsi = gsi_after_labels (commondom);
|
*togsi = gsi_after_labels (commondom);
|
||||||
|
|
||||||
if (debug_stmts)
|
|
||||||
propagate_defs_into_debug_stmts (stmt, commondom, togsi);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,8 +403,6 @@ statement_sink_location (gimple stmt, basic_block frombb,
|
||||||
|
|
||||||
*togsi = gsi_for_stmt (use);
|
*togsi = gsi_for_stmt (use);
|
||||||
|
|
||||||
propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,8 +436,6 @@ statement_sink_location (gimple stmt, basic_block frombb,
|
||||||
|
|
||||||
*togsi = gsi_after_labels (sinkbb);
|
*togsi = gsi_after_labels (sinkbb);
|
||||||
|
|
||||||
propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
240
gcc/tree-ssa.c
240
gcc/tree-ssa.c
|
@ -295,152 +295,198 @@ find_released_ssa_name (tree *tp, int *walk_subtrees, void *data_)
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given a VAR whose definition STMT is to be moved to the iterator
|
/* Insert a DEBUG BIND stmt before the DEF of VAR if VAR is referenced
|
||||||
position TOGSIP in the TOBB basic block, verify whether we're
|
by other DEBUG stmts, and replace uses of the DEF with the
|
||||||
moving it across any of the debug statements that use it, and
|
newly-created debug temp. */
|
||||||
adjust them as needed. If TOBB is NULL, then the definition is
|
|
||||||
understood as being removed, and TOGSIP is unused. */
|
|
||||||
void
|
void
|
||||||
propagate_var_def_into_debug_stmts (tree var,
|
insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var)
|
||||||
basic_block tobb,
|
|
||||||
const gimple_stmt_iterator *togsip)
|
|
||||||
{
|
{
|
||||||
imm_use_iterator imm_iter;
|
imm_use_iterator imm_iter;
|
||||||
gimple stmt;
|
|
||||||
use_operand_p use_p;
|
use_operand_p use_p;
|
||||||
|
gimple stmt;
|
||||||
|
gimple def_stmt = NULL;
|
||||||
|
int usecount = 0;
|
||||||
tree value = NULL;
|
tree value = NULL;
|
||||||
bool no_value = false;
|
|
||||||
|
|
||||||
if (!MAY_HAVE_DEBUG_STMTS)
|
if (!MAY_HAVE_DEBUG_STMTS)
|
||||||
return;
|
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;
|
stmt = USE_STMT (use_p);
|
||||||
gimple_stmt_iterator si;
|
|
||||||
|
|
||||||
if (!is_gimple_debug (stmt))
|
if (!gimple_debug_bind_p (stmt))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (tobb)
|
if (usecount++)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (gimple_debug_bind_get_value (stmt) != var)
|
||||||
{
|
{
|
||||||
bb = gimple_bb (stmt);
|
/* Count this as an additional use, so as to make sure we
|
||||||
|
use a temp unless VAR's definition has a SINGLE_RHS that
|
||||||
if (bb != tobb)
|
can be shared. */
|
||||||
{
|
usecount++;
|
||||||
gcc_assert (dom_info_available_p (CDI_DOMINATORS));
|
break;
|
||||||
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
|
if (!usecount)
|
||||||
remember if we tried before and failed, so that we don't try
|
return;
|
||||||
again. */
|
|
||||||
if (!value && !no_value)
|
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))
|
memset (&wi, 0, sizeof (wi));
|
||||||
{
|
|
||||||
if (!dom_info_available_p (CDI_DOMINATORS))
|
|
||||||
{
|
|
||||||
struct walk_stmt_info wi;
|
|
||||||
|
|
||||||
memset (&wi, 0, sizeof (wi));
|
/* When removing blocks without following reverse dominance
|
||||||
|
order, we may sometimes encounter SSA_NAMEs that have
|
||||||
|
already been released, referenced in other SSA_DEFs that
|
||||||
|
we're about to release. Consider:
|
||||||
|
|
||||||
/* When removing blocks without following reverse
|
<bb X>:
|
||||||
dominance order, we may sometimes encounter SSA_NAMEs
|
v_1 = foo;
|
||||||
that have already been released, referenced in other
|
|
||||||
SSA_DEFs that we're about to release. Consider:
|
|
||||||
|
|
||||||
<bb X>:
|
<bb Y>:
|
||||||
v_1 = foo;
|
w_2 = v_1 + bar;
|
||||||
|
# DEBUG w => w_2
|
||||||
|
|
||||||
<bb Y>:
|
If we deleted BB X first, propagating the value of w_2
|
||||||
w_2 = v_1 + bar;
|
won't do us any good. It's too late to recover their
|
||||||
# DEBUG w => w_2
|
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
|
When dominator information is not readily available, we
|
||||||
w_2 won't do us any good. It's too late to recover
|
check for and accept some loss of debug information. But
|
||||||
their original definition of v_1: when it was
|
if it is available, there's no excuse for us to remove
|
||||||
deleted, it was only referenced in other DEFs, it
|
blocks in the wrong order, so we don't even check for
|
||||||
couldn't possibly know it should have been retained,
|
dead SSA NAMEs. SSA verification shall catch any
|
||||||
and propagating every single DEF just in case it
|
errors. */
|
||||||
might have to be propagated into a DEBUG STMT would
|
if ((!gsi && !gimple_bb (def_stmt))
|
||||||
probably be too wasteful.
|
|| !walk_gimple_op (def_stmt, find_released_ssa_name,
|
||||||
|
&wi))
|
||||||
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)
|
|
||||||
no_value = true;
|
no_value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (no_value)
|
if (!no_value)
|
||||||
gimple_debug_bind_reset_value (stmt);
|
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
|
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)
|
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);
|
update_stmt (stmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Given a STMT to be moved to the iterator position TOBSIP in the
|
/* Insert a DEBUG BIND stmt before STMT for each DEF referenced by
|
||||||
TOBB basic block, verify whether we're moving it across any of the
|
other DEBUG stmts, and replace uses of the DEF with the
|
||||||
debug statements that use it. If TOBB is NULL, then the definition
|
newly-created debug temp. */
|
||||||
is understood as being removed, and TOBSIP is unused. */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
propagate_defs_into_debug_stmts (gimple def, basic_block tobb,
|
insert_debug_temps_for_defs (gimple_stmt_iterator *gsi)
|
||||||
const gimple_stmt_iterator *togsip)
|
|
||||||
{
|
{
|
||||||
|
gimple stmt;
|
||||||
ssa_op_iter op_iter;
|
ssa_op_iter op_iter;
|
||||||
def_operand_p def_p;
|
def_operand_p def_p;
|
||||||
|
|
||||||
if (!MAY_HAVE_DEBUG_STMTS)
|
if (!MAY_HAVE_DEBUG_STMTS)
|
||||||
return;
|
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);
|
tree var = DEF_FROM_PTR (def_p);
|
||||||
|
|
||||||
if (TREE_CODE (var) != SSA_NAME)
|
if (TREE_CODE (var) != SSA_NAME)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
propagate_var_def_into_debug_stmts (var, tobb, togsip);
|
insert_debug_temp_for_var_def (gsi, var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -206,7 +206,7 @@ release_ssa_name (tree var)
|
||||||
use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var));
|
use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var));
|
||||||
|
|
||||||
if (MAY_HAVE_DEBUG_STMTS)
|
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
|
#ifdef ENABLE_CHECKING
|
||||||
verify_imm_links (stderr, var);
|
verify_imm_links (stderr, var);
|
||||||
|
|
13
gcc/tree.c
13
gcc/tree.c
|
@ -152,6 +152,9 @@ static const char * const tree_node_kind_names[] = {
|
||||||
static GTY(()) int next_decl_uid;
|
static GTY(()) int next_decl_uid;
|
||||||
/* Unique id for next type created. */
|
/* Unique id for next type created. */
|
||||||
static GTY(()) int next_type_uid = 1;
|
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
|
/* Since we cannot rehash a type after it is in the table, we have to
|
||||||
keep the hash code. */
|
keep the hash code. */
|
||||||
|
@ -872,7 +875,10 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
|
||||||
DECL_ALIGN (t) = 1;
|
DECL_ALIGN (t) = 1;
|
||||||
}
|
}
|
||||||
DECL_SOURCE_LOCATION (t) = input_location;
|
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)
|
if (TREE_CODE (t) == LABEL_DECL)
|
||||||
LABEL_DECL_UID (t) = -1;
|
LABEL_DECL_UID (t) = -1;
|
||||||
|
|
||||||
|
@ -948,7 +954,10 @@ copy_node_stat (tree node MEM_STAT_DECL)
|
||||||
|
|
||||||
if (TREE_CODE_CLASS (code) == tcc_declaration)
|
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)
|
if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL)
|
||||||
&& DECL_HAS_VALUE_EXPR_P (node))
|
&& DECL_HAS_VALUE_EXPR_P (node))
|
||||||
{
|
{
|
||||||
|
|
|
@ -351,6 +351,10 @@ DEFTREECODE (PARM_DECL, "parm_decl", tcc_declaration, 0)
|
||||||
DEFTREECODE (TYPE_DECL, "type_decl", tcc_declaration, 0)
|
DEFTREECODE (TYPE_DECL, "type_decl", tcc_declaration, 0)
|
||||||
DEFTREECODE (RESULT_DECL, "result_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
|
/* A namespace declaration. Namespaces appear in DECL_CONTEXT of other
|
||||||
_DECLs, providing a hierarchy of names. */
|
_DECLs, providing a hierarchy of names. */
|
||||||
DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0)
|
DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0)
|
||||||
|
|
|
@ -2455,6 +2455,10 @@ struct function;
|
||||||
/* Every ..._DECL node gets a unique number. */
|
/* Every ..._DECL node gets a unique number. */
|
||||||
#define DECL_UID(NODE) (DECL_MINIMAL_CHECK (NODE)->decl_minimal.uid)
|
#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
|
/* These two fields describe where in the source code the declaration
|
||||||
was. If the declaration appears in several places (as for a C
|
was. If the declaration appears in several places (as for a C
|
||||||
function that is declared first and then defined later), this
|
function that is declared first and then defined later), this
|
||||||
|
|
|
@ -732,6 +732,7 @@ dv_is_decl_p (decl_or_value dv)
|
||||||
case (int)PARM_DECL:
|
case (int)PARM_DECL:
|
||||||
case (int)RESULT_DECL:
|
case (int)RESULT_DECL:
|
||||||
case (int)FUNCTION_DECL:
|
case (int)FUNCTION_DECL:
|
||||||
|
case (int)DEBUG_EXPR_DECL:
|
||||||
case (int)COMPONENT_REF:
|
case (int)COMPONENT_REF:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -2222,7 +2223,7 @@ dataflow_set_union (dataflow_set *dst, dataflow_set *src)
|
||||||
|
|
||||||
/* Whether the value is currently being expanded. */
|
/* Whether the value is currently being expanded. */
|
||||||
#define VALUE_RECURSED_INTO(x) \
|
#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. */
|
/* Whether the value is in changed_variables hash table. */
|
||||||
#define VALUE_CHANGED(x) \
|
#define VALUE_CHANGED(x) \
|
||||||
(RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
|
(RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
|
||||||
|
@ -4112,6 +4113,9 @@ track_expr_p (tree expr, bool need_rtl)
|
||||||
rtx decl_rtl;
|
rtx decl_rtl;
|
||||||
tree realdecl;
|
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 EXPR is not a parameter or a variable do not track it. */
|
||||||
if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
|
if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -6271,11 +6275,12 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
|
||||||
decl_or_value dv;
|
decl_or_value dv;
|
||||||
variable var;
|
variable var;
|
||||||
location_chain loc;
|
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)
|
if (GET_CODE (SUBREG_REG (x)) != VALUE)
|
||||||
return x;
|
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));
|
result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
|
||||||
|
|
||||||
return result;
|
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))
|
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));
|
var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
|
||||||
|
|
||||||
if (!var)
|
if (!var)
|
||||||
return x;
|
return xret;
|
||||||
|
|
||||||
if (var->n_var_parts == 0)
|
if (var->n_var_parts == 0)
|
||||||
return x;
|
return xret;
|
||||||
|
|
||||||
gcc_assert (var->n_var_parts == 1);
|
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)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
else
|
else
|
||||||
return x;
|
return xret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expand VALUEs in LOC, using VARS as well as cselib's equivalence
|
/* 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);
|
decl = dv_as_decl (var->dv);
|
||||||
|
|
||||||
|
if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
|
||||||
|
goto clear;
|
||||||
|
|
||||||
gcc_assert (decl);
|
gcc_assert (decl);
|
||||||
|
|
||||||
complete = true;
|
complete = true;
|
||||||
|
|
Loading…
Reference in New Issue