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> 2009-10-12 Hans-Peter Nilsson <hp@axis.com>
PR target/26515 PR target/26515

View File

@ -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:

View File

@ -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;
} }

View File

@ -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:

View File

@ -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)

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 /* 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);

View File

@ -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;

View File

@ -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:

View File

@ -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.
--------------------------------------------------------------------- */ --------------------------------------------------------------------- */

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, 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;

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> 2009-10-12 Hans-Peter Nilsson <hp@axis.com>
PR target/26515 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)); 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:

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); 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 */

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) 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;

View File

@ -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);
} }
} }

View File

@ -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;
} }

View File

@ -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);
} }
} }

View File

@ -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 */

View File

@ -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));

View File

@ -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;
} }

View File

@ -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);
} }
} }

View File

@ -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);

View File

@ -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))
{ {

View File

@ -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)

View File

@ -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

View File

@ -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;