Commit 1adbb361 by Alexandre Oliva Committed by Alexandre Oliva

re PR debug/48866 (gcc hangs when -g is set)

PR debug/48866
* df.h (enum debug_temp_where): New.
(dead_debug_init, dead_debug_finish) Declare.
(dead_debug_add, dead_debug_insert_temp): Declare.
(struct dead_debug_use, struct dead_debug): Moved from...
* df-problems.c: ... here.
(df_set_unused_notes_for_mw): Bind debug uses of unused regno
to a debug temp.
(df_create_unused_note): Likewise.
(df_set_dead_notes_for_mw): Move comment where it belongs.
(dead_debug_init): Export.
(dead_debug_reset_uses): New, factored out of...
(dead_debug_finish): ...this.  Export.
(dead_debug_reset): Remove.
(dead_debug_add): Export.
(dead_debug_insert_before): Rename to...
(dead_debug_insert_temp): ... this.  Add where argument.  Export.
Locate stored value for BEFORE_WITH_VALUE.  Avoid repeat inserts.
Return insertion count.
(df_note_bb_compute): Adjust.
* dce.c (word_dce_process_block): Adjust dead debug uses.
(dce_process_block): Likewise.

From-SVN: r186422
parent 6ae1d471
2012-04-13 Alexandre Oliva <aoliva@redhat.com>
PR debug/48866
* df.h (enum debug_temp_where): New.
(dead_debug_init, dead_debug_finish) Declare.
(dead_debug_add, dead_debug_insert_temp): Declare.
(struct dead_debug_use, struct dead_debug): Moved from...
* df-problems.c: ... here.
(df_set_unused_notes_for_mw): Bind debug uses of unused regno
to a debug temp.
(df_create_unused_note): Likewise.
(df_set_dead_notes_for_mw): Move comment where it belongs.
(dead_debug_init): Export.
(dead_debug_reset_uses): New, factored out of...
(dead_debug_finish): ...this. Export.
(dead_debug_reset): Remove.
(dead_debug_add): Export.
(dead_debug_insert_before): Rename to...
(dead_debug_insert_temp): ... this. Add where argument. Export.
Locate stored value for BEFORE_WITH_VALUE. Avoid repeat inserts.
Return insertion count.
(df_note_bb_compute): Adjust.
* dce.c (word_dce_process_block): Adjust dead debug uses.
(dce_process_block): Likewise.
2012-04-13 Alexandre Oliva <aoliva@redhat.com>
* df-problems.c (df_note_bb_compute): Do not take note of
debug uses for whose REGs we won't emit DEAD or UNUSED notes.
......
......@@ -807,6 +807,7 @@ word_dce_process_block (basic_block bb, bool redo_out)
bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack);
rtx insn;
bool block_changed;
struct dead_debug debug;
if (redo_out)
{
......@@ -828,11 +829,24 @@ word_dce_process_block (basic_block bb, bool redo_out)
}
bitmap_copy (local_live, DF_WORD_LR_OUT (bb));
dead_debug_init (&debug, NULL);
FOR_BB_INSNS_REVERSE (bb, insn)
if (NONDEBUG_INSN_P (insn))
if (DEBUG_INSN_P (insn))
{
df_ref *use_rec;
for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
if (DF_REF_REGNO (*use_rec) >= FIRST_PSEUDO_REGISTER
&& (GET_MODE_SIZE (GET_MODE (DF_REF_REAL_REG (*use_rec)))
== 2 * UNITS_PER_WORD)
&& !bitmap_bit_p (local_live, 2 * DF_REF_REGNO (*use_rec))
&& !bitmap_bit_p (local_live, 2 * DF_REF_REGNO (*use_rec) + 1))
dead_debug_add (&debug, *use_rec, DF_REF_REGNO (*use_rec));
}
else if (INSN_P (insn))
{
bool any_changed;
/* No matter if the instruction is needed or not, we remove
any regno in the defs from the live set. */
any_changed = df_word_lr_simulate_defs (insn, local_live);
......@@ -844,6 +858,15 @@ word_dce_process_block (basic_block bb, bool redo_out)
if (marked_insn_p (insn))
df_word_lr_simulate_uses (insn, local_live);
if (debug.used && !bitmap_empty_p (debug.used))
{
df_ref *def_rec;
for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
dead_debug_insert_temp (&debug, DF_REF_REGNO (*def_rec), insn,
DEBUG_TEMP_BEFORE_WITH_VALUE);
}
if (dump_file)
{
fprintf (dump_file, "finished processing insn %d live out = ",
......@@ -856,6 +879,7 @@ word_dce_process_block (basic_block bb, bool redo_out)
if (block_changed)
bitmap_copy (DF_WORD_LR_IN (bb), local_live);
dead_debug_finish (&debug, NULL);
BITMAP_FREE (local_live);
return block_changed;
}
......@@ -873,6 +897,7 @@ dce_process_block (basic_block bb, bool redo_out, bitmap au)
rtx insn;
bool block_changed;
df_ref *def_rec;
struct dead_debug debug;
if (redo_out)
{
......@@ -896,22 +921,36 @@ dce_process_block (basic_block bb, bool redo_out, bitmap au)
bitmap_copy (local_live, DF_LR_OUT (bb));
df_simulate_initialize_backwards (bb, local_live);
dead_debug_init (&debug, NULL);
FOR_BB_INSNS_REVERSE (bb, insn)
if (INSN_P (insn))
if (DEBUG_INSN_P (insn))
{
df_ref *use_rec;
for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
if (!bitmap_bit_p (local_live, DF_REF_REGNO (*use_rec))
&& !bitmap_bit_p (au, DF_REF_REGNO (*use_rec)))
dead_debug_add (&debug, *use_rec, DF_REF_REGNO (*use_rec));
}
else if (INSN_P (insn))
{
bool needed = marked_insn_p (insn);
/* The insn is needed if there is someone who uses the output. */
if (!needed)
for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
if (bitmap_bit_p (local_live, DF_REF_REGNO (*def_rec))
|| bitmap_bit_p (au, DF_REF_REGNO (*def_rec)))
{
needed = true;
mark_insn (insn, true);
break;
}
{
dead_debug_insert_temp (&debug, DF_REF_REGNO (*def_rec), insn,
DEBUG_TEMP_BEFORE_WITH_VALUE);
if (bitmap_bit_p (local_live, DF_REF_REGNO (*def_rec))
|| bitmap_bit_p (au, DF_REF_REGNO (*def_rec)))
{
needed = true;
mark_insn (insn, true);
break;
}
}
/* No matter if the instruction is needed or not, we remove
any regno in the defs from the live set. */
......@@ -923,6 +962,7 @@ dce_process_block (basic_block bb, bool redo_out, bitmap au)
df_simulate_uses (insn, local_live);
}
dead_debug_finish (&debug, NULL);
df_simulate_finalize_backwards (bb, local_live);
block_changed = !bitmap_equal_p (local_live, DF_LR_IN (bb));
......
......@@ -1101,4 +1101,46 @@ extern void union_defs (df_ref, struct web_entry *,
unsigned int *used, struct web_entry *,
bool (*fun) (struct web_entry *, struct web_entry *));
/* Debug uses of dead regs. */
/* Node of a linked list of uses of dead REGs in debug insns. */
struct dead_debug_use
{
df_ref use;
struct dead_debug_use *next;
};
/* Linked list of the above, with a bitmap of the REGs in the
list. */
struct dead_debug
{
struct dead_debug_use *head;
bitmap used;
bitmap to_rescan;
};
/* This type controls the behavior of dead_debug_insert_temp WRT
UREGNO and INSN. */
enum debug_temp_where
{
/* Bind a newly-created debug temporary to a REG for UREGNO, and
insert the debug insn before INSN. REG is expected to die at
INSN. */
DEBUG_TEMP_BEFORE_WITH_REG = -1,
/* Bind a newly-created debug temporary to the value INSN stores
in REG, and insert the debug insn before INSN. */
DEBUG_TEMP_BEFORE_WITH_VALUE = 0,
/* Bind a newly-created debug temporary to a REG for UREGNO, and
insert the debug insn after INSN. REG is expected to be set at
INSN. */
DEBUG_TEMP_AFTER_WITH_REG = 1
};
extern void dead_debug_init (struct dead_debug *, bitmap);
extern void dead_debug_finish (struct dead_debug *, bitmap);
extern void dead_debug_add (struct dead_debug *, df_ref, unsigned int);
extern int dead_debug_insert_temp (struct dead_debug *,
unsigned int uregno, rtx insn,
enum debug_temp_where);
#endif /* GCC_DF_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment