mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-03 07:10:28 +08:00
re PR debug/54551 (DF resets some DEBUG_INSNs unnecessarily)
gcc/ChangeLog: PR debug/54551 * Makefile.in (VALTRACK_H): Add hash-table.h. * valtrack.h: Include hash-table.h. (struct dead_debug_global_entry): New. (struct dead_debug_hash_descr): New. (struct dead_debug_global): New. (struct dead_debug): Rename to... (struct dead_debug_local): ... this. Adjust all uses. (dead_debug_global_init, dead_debug_global_finish): New. (dead_debug_init): Rename to... (dead_debug_local_init): ... this. Adjust all callers. (dead_debug_finish): Rename to... (dead_debug_local_finish): ... this. Adjust all callers. * valtrack.c (dead_debug_global_init): New. (dead_debug_init): Rename to... (dead_debug_local_init): ... this. Take global parameter. Save it and initialize used bitmap from it. (dead_debug_global_find, dead_debug_global_insert): New. (dead_debug_global_replace_temp): New. (dead_debug_promote_uses): New. (dead_debug_finish): Rename to... (dead_debug_local_finish): ... this. Promote remaining uses. (dead_debug_global_finish): New. (dead_debug_add): Try to replace global temps first. (dead_debug_insert_temp): Support global replacements. * dce.c (word_dce_process_block, dce_process_block): Add global_debug parameter. Pass it on. (fast_dce): Initialize, pass on and finalize global_debug. * df-problems.c (df_set_unused_notes_for_mw): Adjusted. (df_create_unused_notes, df_note_bb_compute): Likewise. (df_note_compute): Justify local-only dead debug analysis. gcc/testsuite/ChangeLog: PR debug/54551 * gcc.dg/guality/pr54551.c: New. From-SVN: r192001
This commit is contained in:
parent
58b88be9de
commit
e9f950ba0d
@ -1,3 +1,37 @@
|
||||
2012-10-02 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
PR debug/54551
|
||||
* Makefile.in (VALTRACK_H): Add hash-table.h.
|
||||
* valtrack.h: Include hash-table.h.
|
||||
(struct dead_debug_global_entry): New.
|
||||
(struct dead_debug_hash_descr): New.
|
||||
(struct dead_debug_global): New.
|
||||
(struct dead_debug): Rename to...
|
||||
(struct dead_debug_local): ... this. Adjust all uses.
|
||||
(dead_debug_global_init, dead_debug_global_finish): New.
|
||||
(dead_debug_init): Rename to...
|
||||
(dead_debug_local_init): ... this. Adjust all callers.
|
||||
(dead_debug_finish): Rename to...
|
||||
(dead_debug_local_finish): ... this. Adjust all callers.
|
||||
* valtrack.c (dead_debug_global_init): New.
|
||||
(dead_debug_init): Rename to...
|
||||
(dead_debug_local_init): ... this. Take global parameter.
|
||||
Save it and initialize used bitmap from it.
|
||||
(dead_debug_global_find, dead_debug_global_insert): New.
|
||||
(dead_debug_global_replace_temp): New.
|
||||
(dead_debug_promote_uses): New.
|
||||
(dead_debug_finish): Rename to...
|
||||
(dead_debug_local_finish): ... this. Promote remaining uses.
|
||||
(dead_debug_global_finish): New.
|
||||
(dead_debug_add): Try to replace global temps first.
|
||||
(dead_debug_insert_temp): Support global replacements.
|
||||
* dce.c (word_dce_process_block, dce_process_block): Add
|
||||
global_debug parameter. Pass it on.
|
||||
(fast_dce): Initialize, pass on and finalize global_debug.
|
||||
* df-problems.c (df_set_unused_notes_for_mw): Adjusted.
|
||||
(df_create_unused_notes, df_note_bb_compute): Likewise.
|
||||
(df_note_compute): Justify local-only dead debug analysis.
|
||||
|
||||
2012-10-02 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
PR debug/53135
|
||||
|
@ -888,7 +888,8 @@ CGRAPH_H = cgraph.h $(VEC_H) $(TREE_H) $(BASIC_BLOCK_H) $(FUNCTION_H) \
|
||||
cif-code.def ipa-ref.h ipa-ref-inline.h $(LINKER_PLUGIN_API_H)
|
||||
DF_H = df.h $(BITMAP_H) $(REGSET_H) sbitmap.h $(BASIC_BLOCK_H) \
|
||||
alloc-pool.h $(TIMEVAR_H)
|
||||
VALTRACK_H = valtrack.h $(BITMAP_H) $(DF_H) $(RTL_H) $(BASIC_BLOCK_H)
|
||||
VALTRACK_H = valtrack.h $(BITMAP_H) $(DF_H) $(RTL_H) $(BASIC_BLOCK_H) \
|
||||
$(HASH_TABLE_H)
|
||||
RESOURCE_H = resource.h hard-reg-set.h $(DF_H)
|
||||
DDG_H = ddg.h sbitmap.h $(DF_H)
|
||||
GCC_H = gcc.h version.h $(DIAGNOSTIC_CORE_H)
|
||||
|
35
gcc/dce.c
35
gcc/dce.c
@ -806,15 +806,17 @@ struct rtl_opt_pass pass_ud_rtl_dce =
|
||||
/* Process basic block BB. Return true if the live_in set has
|
||||
changed. REDO_OUT is true if the info at the bottom of the block
|
||||
needs to be recalculated before starting. AU is the proper set of
|
||||
artificial uses. */
|
||||
artificial uses. Track global substitution of uses of dead pseudos
|
||||
in debug insns using GLOBAL_DEBUG. */
|
||||
|
||||
static bool
|
||||
word_dce_process_block (basic_block bb, bool redo_out)
|
||||
word_dce_process_block (basic_block bb, bool redo_out,
|
||||
struct dead_debug_global *global_debug)
|
||||
{
|
||||
bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack);
|
||||
rtx insn;
|
||||
bool block_changed;
|
||||
struct dead_debug debug;
|
||||
struct dead_debug_local debug;
|
||||
|
||||
if (redo_out)
|
||||
{
|
||||
@ -836,7 +838,7 @@ word_dce_process_block (basic_block bb, bool redo_out)
|
||||
}
|
||||
|
||||
bitmap_copy (local_live, DF_WORD_LR_OUT (bb));
|
||||
dead_debug_init (&debug, NULL);
|
||||
dead_debug_local_init (&debug, NULL, global_debug);
|
||||
|
||||
FOR_BB_INSNS_REVERSE (bb, insn)
|
||||
if (DEBUG_INSN_P (insn))
|
||||
@ -890,7 +892,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);
|
||||
dead_debug_local_finish (&debug, NULL);
|
||||
BITMAP_FREE (local_live);
|
||||
return block_changed;
|
||||
}
|
||||
@ -899,16 +901,18 @@ word_dce_process_block (basic_block bb, bool redo_out)
|
||||
/* Process basic block BB. Return true if the live_in set has
|
||||
changed. REDO_OUT is true if the info at the bottom of the block
|
||||
needs to be recalculated before starting. AU is the proper set of
|
||||
artificial uses. */
|
||||
artificial uses. Track global substitution of uses of dead pseudos
|
||||
in debug insns using GLOBAL_DEBUG. */
|
||||
|
||||
static bool
|
||||
dce_process_block (basic_block bb, bool redo_out, bitmap au)
|
||||
dce_process_block (basic_block bb, bool redo_out, bitmap au,
|
||||
struct dead_debug_global *global_debug)
|
||||
{
|
||||
bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack);
|
||||
rtx insn;
|
||||
bool block_changed;
|
||||
df_ref *def_rec;
|
||||
struct dead_debug debug;
|
||||
struct dead_debug_local debug;
|
||||
|
||||
if (redo_out)
|
||||
{
|
||||
@ -932,7 +936,7 @@ 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);
|
||||
dead_debug_local_init (&debug, NULL, global_debug);
|
||||
|
||||
FOR_BB_INSNS_REVERSE (bb, insn)
|
||||
if (DEBUG_INSN_P (insn))
|
||||
@ -977,7 +981,7 @@ dce_process_block (basic_block bb, bool redo_out, bitmap au)
|
||||
DEBUG_TEMP_BEFORE_WITH_VALUE);
|
||||
}
|
||||
|
||||
dead_debug_finish (&debug, NULL);
|
||||
dead_debug_local_finish (&debug, NULL);
|
||||
df_simulate_finalize_backwards (bb, local_live);
|
||||
|
||||
block_changed = !bitmap_equal_p (local_live, DF_LR_IN (bb));
|
||||
@ -1014,12 +1018,15 @@ fast_dce (bool word_level)
|
||||
bitmap au = &df->regular_block_artificial_uses;
|
||||
bitmap au_eh = &df->eh_block_artificial_uses;
|
||||
int i;
|
||||
struct dead_debug_global global_debug;
|
||||
|
||||
prescan_insns_for_dce (true);
|
||||
|
||||
for (i = 0; i < n_blocks; i++)
|
||||
bitmap_set_bit (all_blocks, postorder[i]);
|
||||
|
||||
dead_debug_global_init (&global_debug, NULL);
|
||||
|
||||
while (global_changed)
|
||||
{
|
||||
global_changed = false;
|
||||
@ -1038,11 +1045,13 @@ fast_dce (bool word_level)
|
||||
|
||||
if (word_level)
|
||||
local_changed
|
||||
= word_dce_process_block (bb, bitmap_bit_p (redo_out, index));
|
||||
= word_dce_process_block (bb, bitmap_bit_p (redo_out, index),
|
||||
&global_debug);
|
||||
else
|
||||
local_changed
|
||||
= dce_process_block (bb, bitmap_bit_p (redo_out, index),
|
||||
bb_has_eh_pred (bb) ? au_eh : au);
|
||||
bb_has_eh_pred (bb) ? au_eh : au,
|
||||
&global_debug);
|
||||
bitmap_set_bit (processed, index);
|
||||
|
||||
if (local_changed)
|
||||
@ -1090,6 +1099,8 @@ fast_dce (bool word_level)
|
||||
}
|
||||
}
|
||||
|
||||
dead_debug_global_finish (&global_debug, NULL);
|
||||
|
||||
delete_unmarked_insns ();
|
||||
|
||||
BITMAP_FREE (processed);
|
||||
|
@ -2892,7 +2892,7 @@ static void
|
||||
df_set_unused_notes_for_mw (rtx insn, struct df_mw_hardreg *mws,
|
||||
bitmap live, bitmap do_not_gen,
|
||||
bitmap artificial_uses,
|
||||
struct dead_debug *debug)
|
||||
struct dead_debug_local *debug)
|
||||
{
|
||||
unsigned int r;
|
||||
|
||||
@ -3021,7 +3021,7 @@ df_set_dead_notes_for_mw (rtx insn, struct df_mw_hardreg *mws,
|
||||
static void
|
||||
df_create_unused_note (rtx insn, df_ref def,
|
||||
bitmap live, bitmap artificial_uses,
|
||||
struct dead_debug *debug)
|
||||
struct dead_debug_local *debug)
|
||||
{
|
||||
unsigned int dregno = DF_REF_REGNO (def);
|
||||
|
||||
@ -3060,9 +3060,9 @@ df_note_bb_compute (unsigned int bb_index,
|
||||
rtx insn;
|
||||
df_ref *def_rec;
|
||||
df_ref *use_rec;
|
||||
struct dead_debug debug;
|
||||
struct dead_debug_local debug;
|
||||
|
||||
dead_debug_init (&debug, NULL);
|
||||
dead_debug_local_init (&debug, NULL, NULL);
|
||||
|
||||
bitmap_copy (live, df_get_live_out (bb));
|
||||
bitmap_clear (artificial_uses);
|
||||
@ -3268,7 +3268,7 @@ df_note_bb_compute (unsigned int bb_index,
|
||||
}
|
||||
}
|
||||
|
||||
dead_debug_finish (&debug, NULL);
|
||||
dead_debug_local_finish (&debug, NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -3286,6 +3286,11 @@ df_note_compute (bitmap all_blocks)
|
||||
|
||||
EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi)
|
||||
{
|
||||
/* ??? Unlike fast DCE, we don't use global_debug for uses of dead
|
||||
pseudos in debug insns because we don't always (re)visit blocks
|
||||
with death points after visiting dead uses. Even changing this
|
||||
loop to postorder would still leave room for visiting a death
|
||||
point before visiting a subsequent debug use. */
|
||||
df_note_bb_compute (bb_index, &live, &do_not_gen, &artificial_uses);
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
2012-10-02 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
PR debug/54551
|
||||
* gcc.dg/guality/pr54551.c: New.
|
||||
|
||||
2012-10-02 Pat Haugen <pthaugen@us.ibm.com>
|
||||
|
||||
* gcc.target/powerpc/pr46728-1.c: Accept xssqrtdp.
|
||||
|
28
gcc/testsuite/gcc.dg/guality/pr54551.c
Normal file
28
gcc/testsuite/gcc.dg/guality/pr54551.c
Normal file
@ -0,0 +1,28 @@
|
||||
/* PR debug/54551 */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-g" } */
|
||||
|
||||
void __attribute__((__noinline__))
|
||||
bar (void)
|
||||
{
|
||||
asm volatile ("");
|
||||
}
|
||||
|
||||
int __attribute__((__noinline__))
|
||||
foo (int x, int y, int z)
|
||||
{
|
||||
if (x != z)
|
||||
{
|
||||
int a = z + 1;
|
||||
bar (); /* { dg-final { gdb-test 18 "a" "4" } } */
|
||||
bar (); /* { dg-final { gdb-test 18 "z" "3" } } */
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
foo (1, 2, 3);
|
||||
return 0;
|
||||
}
|
222
gcc/valtrack.c
222
gcc/valtrack.c
@ -182,16 +182,110 @@ propagate_for_debug (rtx insn, rtx last, rtx dest, rtx src,
|
||||
}
|
||||
|
||||
/* Initialize DEBUG to an empty list, and clear USED, if given. */
|
||||
|
||||
void
|
||||
dead_debug_init (struct dead_debug *debug, bitmap used)
|
||||
dead_debug_global_init (struct dead_debug_global *debug, bitmap used)
|
||||
{
|
||||
debug->head = NULL;
|
||||
debug->used = used;
|
||||
debug->to_rescan = NULL;
|
||||
if (used)
|
||||
bitmap_clear (used);
|
||||
}
|
||||
|
||||
/* Initialize DEBUG to an empty list, and clear USED, if given. Link
|
||||
back to GLOBAL, if given, and bring in used bits from it. */
|
||||
|
||||
void
|
||||
dead_debug_local_init (struct dead_debug_local *debug, bitmap used,
|
||||
struct dead_debug_global *global)
|
||||
{
|
||||
if (!used && global && global->used)
|
||||
used = BITMAP_ALLOC (NULL);
|
||||
|
||||
debug->head = NULL;
|
||||
debug->global = global;
|
||||
debug->used = used;
|
||||
debug->to_rescan = NULL;
|
||||
|
||||
if (used)
|
||||
{
|
||||
if (global && global->used)
|
||||
bitmap_copy (used, global->used);
|
||||
else
|
||||
bitmap_clear (used);
|
||||
}
|
||||
}
|
||||
|
||||
/* Locate the entry for REG in GLOBAL->htab. */
|
||||
|
||||
static dead_debug_global_entry *
|
||||
dead_debug_global_find (struct dead_debug_global *global, rtx reg)
|
||||
{
|
||||
dead_debug_global_entry temp_entry;
|
||||
temp_entry.reg = reg;
|
||||
|
||||
dead_debug_global_entry *entry = global->htab.find (&temp_entry);
|
||||
gcc_checking_assert (entry && entry->reg == temp_entry.reg);
|
||||
gcc_checking_assert (entry->dtemp);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/* Insert an entry mapping REG to DTEMP in GLOBAL->htab. */
|
||||
|
||||
static void
|
||||
dead_debug_global_insert (struct dead_debug_global *global, rtx reg, rtx dtemp)
|
||||
{
|
||||
dead_debug_global_entry temp_entry;
|
||||
temp_entry.reg = reg;
|
||||
temp_entry.dtemp = dtemp;
|
||||
|
||||
if (!global->htab.is_created ())
|
||||
global->htab.create (31);
|
||||
|
||||
dead_debug_global_entry **slot = global->htab.find_slot (&temp_entry, INSERT);
|
||||
gcc_checking_assert (!*slot);
|
||||
*slot = XNEW (dead_debug_global_entry);
|
||||
**slot = temp_entry;
|
||||
}
|
||||
|
||||
/* If UREGNO, referenced by USE, is a pseudo marked as used in GLOBAL,
|
||||
replace it with with a USE of the debug temp recorded for it, and
|
||||
return TRUE. Otherwise, just return FALSE.
|
||||
|
||||
If PTO_RESCAN is given, instead of rescanning modified INSNs right
|
||||
away, add their UIDs to the bitmap, allocating one of *PTO_RESCAN
|
||||
is NULL. */
|
||||
|
||||
static bool
|
||||
dead_debug_global_replace_temp (struct dead_debug_global *global,
|
||||
df_ref use, unsigned int uregno,
|
||||
bitmap *pto_rescan)
|
||||
{
|
||||
if (!global || uregno < FIRST_PSEUDO_REGISTER
|
||||
|| !global->used
|
||||
|| !bitmap_bit_p (global->used, uregno))
|
||||
return false;
|
||||
|
||||
gcc_checking_assert (REGNO (*DF_REF_REAL_LOC (use)) == uregno);
|
||||
|
||||
dead_debug_global_entry *entry
|
||||
= dead_debug_global_find (global, *DF_REF_REAL_LOC (use));
|
||||
gcc_checking_assert (GET_CODE (entry->reg) == REG
|
||||
&& REGNO (entry->reg) == uregno);
|
||||
|
||||
*DF_REF_REAL_LOC (use) = entry->dtemp;
|
||||
if (!pto_rescan)
|
||||
df_insn_rescan (DF_REF_INSN (use));
|
||||
else
|
||||
{
|
||||
if (!*pto_rescan)
|
||||
*pto_rescan = BITMAP_ALLOC (NULL);
|
||||
bitmap_set_bit (*pto_rescan, INSN_UID (DF_REF_INSN (use)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Reset all debug uses in HEAD, and clear DEBUG->to_rescan bits of
|
||||
each reset insn. DEBUG is not otherwise modified. If HEAD is
|
||||
DEBUG->head, DEBUG->head will be set to NULL at the end.
|
||||
@ -199,7 +293,8 @@ dead_debug_init (struct dead_debug *debug, bitmap used)
|
||||
will be removed, and only then rescanned. */
|
||||
|
||||
static void
|
||||
dead_debug_reset_uses (struct dead_debug *debug, struct dead_debug_use *head)
|
||||
dead_debug_reset_uses (struct dead_debug_local *debug,
|
||||
struct dead_debug_use *head)
|
||||
{
|
||||
bool got_head = (debug->head == head);
|
||||
bitmap rescan;
|
||||
@ -258,15 +353,57 @@ dead_debug_reset_uses (struct dead_debug *debug, struct dead_debug_use *head)
|
||||
BITMAP_FREE (rescan);
|
||||
}
|
||||
|
||||
/* Promote pending local uses of pseudos in DEBUG to global
|
||||
substitutions. Uses of non-pseudos are left alone for
|
||||
resetting. */
|
||||
|
||||
static void
|
||||
dead_debug_promote_uses (struct dead_debug_local *debug)
|
||||
{
|
||||
for (struct dead_debug_use *head = debug->head, **headp = &debug->head;
|
||||
head; head = *headp)
|
||||
{
|
||||
rtx reg = *DF_REF_REAL_LOC (head->use);
|
||||
|
||||
if (GET_CODE (reg) != REG
|
||||
|| REGNO (reg) < FIRST_PSEUDO_REGISTER)
|
||||
{
|
||||
headp = &head->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!debug->global->used)
|
||||
debug->global->used = BITMAP_ALLOC (NULL);
|
||||
|
||||
if (bitmap_set_bit (debug->global->used, REGNO (reg)))
|
||||
dead_debug_global_insert (debug->global, reg,
|
||||
make_debug_expr_from_rtl (reg));
|
||||
|
||||
if (!dead_debug_global_replace_temp (debug->global, head->use,
|
||||
REGNO (reg), &debug->to_rescan))
|
||||
{
|
||||
headp = &head->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
*headp = head->next;
|
||||
XDELETE (head);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset all debug insns with pending uses. Release the bitmap in it,
|
||||
unless it is USED. USED must be the same bitmap passed to
|
||||
dead_debug_init. */
|
||||
dead_debug_local_init. */
|
||||
|
||||
void
|
||||
dead_debug_finish (struct dead_debug *debug, bitmap used)
|
||||
dead_debug_local_finish (struct dead_debug_local *debug, bitmap used)
|
||||
{
|
||||
if (debug->used != used)
|
||||
BITMAP_FREE (debug->used);
|
||||
|
||||
if (debug->global)
|
||||
dead_debug_promote_uses (debug);
|
||||
|
||||
dead_debug_reset_uses (debug, debug->head);
|
||||
|
||||
if (debug->to_rescan)
|
||||
@ -284,11 +421,30 @@ dead_debug_finish (struct dead_debug *debug, bitmap used)
|
||||
}
|
||||
}
|
||||
|
||||
/* Add USE to DEBUG. It must be a dead reference to UREGNO in a debug
|
||||
insn. Create a bitmap for DEBUG as needed. */
|
||||
/* Release GLOBAL->used unless it is the same as USED. Release the
|
||||
mapping hash table if it was initialized. */
|
||||
|
||||
void
|
||||
dead_debug_add (struct dead_debug *debug, df_ref use, unsigned int uregno)
|
||||
dead_debug_global_finish (struct dead_debug_global *global, bitmap used)
|
||||
{
|
||||
if (global->used != used)
|
||||
BITMAP_FREE (global->used);
|
||||
|
||||
if (global->htab.is_created ())
|
||||
global->htab.dispose ();
|
||||
}
|
||||
|
||||
/* Add USE to DEBUG, or substitute it right away if it's a pseudo in
|
||||
the global substitution list. USE must be a dead reference to
|
||||
UREGNO in a debug insn. Create a bitmap for DEBUG as needed. */
|
||||
|
||||
void
|
||||
dead_debug_add (struct dead_debug_local *debug, df_ref use, unsigned int uregno)
|
||||
{
|
||||
if (dead_debug_global_replace_temp (debug->global, use, uregno,
|
||||
&debug->to_rescan))
|
||||
return;
|
||||
|
||||
struct dead_debug_use *newddu = XNEW (struct dead_debug_use);
|
||||
|
||||
newddu->use = use;
|
||||
@ -305,26 +461,34 @@ dead_debug_add (struct dead_debug *debug, df_ref use, unsigned int uregno)
|
||||
}
|
||||
|
||||
/* If UREGNO is referenced by any entry in DEBUG, emit a debug insn
|
||||
before or after INSN (depending on WHERE), that binds a debug temp
|
||||
to the widest-mode use of UREGNO, if WHERE is *_WITH_REG, or the
|
||||
value stored in UREGNO by INSN otherwise, and replace all uses of
|
||||
UREGNO in DEBUG with uses of the debug temp. INSN must be where
|
||||
UREGNO dies, if WHERE is *_BEFORE_*, or where it is set otherwise.
|
||||
Return the number of debug insns emitted. */
|
||||
before or after INSN (depending on WHERE), that binds a (possibly
|
||||
global) debug temp to the widest-mode use of UREGNO, if WHERE is
|
||||
*_WITH_REG, or the value stored in UREGNO by INSN otherwise, and
|
||||
replace all uses of UREGNO in DEBUG with uses of the debug temp.
|
||||
INSN must be where UREGNO dies, if WHERE is *_BEFORE_*, or where it
|
||||
is set otherwise. Return the number of debug insns emitted. */
|
||||
|
||||
int
|
||||
dead_debug_insert_temp (struct dead_debug *debug, unsigned int uregno,
|
||||
dead_debug_insert_temp (struct dead_debug_local *debug, unsigned int uregno,
|
||||
rtx insn, enum debug_temp_where where)
|
||||
{
|
||||
struct dead_debug_use **tailp = &debug->head;
|
||||
struct dead_debug_use *cur;
|
||||
struct dead_debug_use *uses = NULL;
|
||||
struct dead_debug_use **usesp = &uses;
|
||||
rtx reg = NULL;
|
||||
rtx reg = NULL_RTX;
|
||||
rtx breg;
|
||||
rtx dval;
|
||||
rtx dval = NULL_RTX;
|
||||
rtx bind;
|
||||
bool global;
|
||||
|
||||
if (!debug->used || !bitmap_clear_bit (debug->used, uregno))
|
||||
if (!debug->used)
|
||||
return 0;
|
||||
|
||||
global = (debug->global && debug->global->used
|
||||
&& bitmap_bit_p (debug->global->used, uregno));
|
||||
|
||||
if (!global && !bitmap_clear_bit (debug->used, uregno))
|
||||
return 0;
|
||||
|
||||
/* Move all uses of uregno from debug->head to uses, setting mode to
|
||||
@ -359,10 +523,21 @@ dead_debug_insert_temp (struct dead_debug *debug, unsigned int uregno,
|
||||
if (reg == NULL)
|
||||
{
|
||||
gcc_checking_assert (!uses);
|
||||
return 0;
|
||||
if (!global)
|
||||
return 0;
|
||||
}
|
||||
|
||||
gcc_checking_assert (uses);
|
||||
if (global)
|
||||
{
|
||||
if (!reg)
|
||||
reg = regno_reg_rtx[uregno];
|
||||
dead_debug_global_entry *entry
|
||||
= dead_debug_global_find (debug->global, reg);
|
||||
gcc_checking_assert (entry->reg == reg);
|
||||
dval = entry->dtemp;
|
||||
}
|
||||
|
||||
gcc_checking_assert (uses || global);
|
||||
|
||||
breg = reg;
|
||||
/* Recover the expression INSN stores in REG. */
|
||||
@ -464,8 +639,9 @@ dead_debug_insert_temp (struct dead_debug *debug, unsigned int uregno,
|
||||
}
|
||||
}
|
||||
|
||||
/* Create DEBUG_EXPR (and DEBUG_EXPR_DECL). */
|
||||
dval = make_debug_expr_from_rtl (reg);
|
||||
if (!global)
|
||||
/* Create DEBUG_EXPR (and DEBUG_EXPR_DECL). */
|
||||
dval = make_debug_expr_from_rtl (reg);
|
||||
|
||||
/* Emit a debug bind insn before the insn in which reg dies. */
|
||||
bind = gen_rtx_VAR_LOCATION (GET_MODE (reg),
|
||||
|
@ -26,10 +26,71 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "df.h"
|
||||
#include "rtl.h"
|
||||
#include "basic-block.h"
|
||||
#include "hash-table.h"
|
||||
|
||||
/* Debug uses of dead regs. */
|
||||
|
||||
/* Entry that maps a dead pseudo (REG) used in a debug insns that dies
|
||||
at different blocks to the debug temp (DTEMP) it was replaced
|
||||
with. */
|
||||
|
||||
struct dead_debug_global_entry
|
||||
{
|
||||
rtx reg;
|
||||
rtx dtemp;
|
||||
};
|
||||
|
||||
/* Descriptor for hash_table to hash by dead_debug_global_entry's REG
|
||||
and map to DTEMP. */
|
||||
|
||||
struct dead_debug_hash_descr
|
||||
{
|
||||
/* The hash table contains pointers to entries of this type. */
|
||||
typedef struct dead_debug_global_entry T;
|
||||
/* Hash on the pseudo number. */
|
||||
static inline hashval_t hash (T const *my);
|
||||
/* Entries are identical if they refer to the same pseudo. */
|
||||
static inline bool equal (T const *my, T const *other);
|
||||
/* Release entries when they're removed. */
|
||||
static inline void remove (T *p);
|
||||
};
|
||||
|
||||
/* Hash on the pseudo number. */
|
||||
inline hashval_t
|
||||
dead_debug_hash_descr::hash (T const *my)
|
||||
{
|
||||
return REGNO (my->reg);
|
||||
}
|
||||
|
||||
/* Entries are identical if they refer to the same pseudo. */
|
||||
inline bool
|
||||
dead_debug_hash_descr::equal (T const *my, T const *other)
|
||||
{
|
||||
return my->reg == other->reg;
|
||||
}
|
||||
|
||||
/* Release entries when they're removed. */
|
||||
inline void
|
||||
dead_debug_hash_descr::remove (T *p)
|
||||
{
|
||||
XDELETE (p);
|
||||
}
|
||||
|
||||
/* Maintain a global table of pseudos used in debug insns after their
|
||||
deaths in other blocks, and debug temps their deathpoint values are
|
||||
to be bound to. */
|
||||
|
||||
struct dead_debug_global
|
||||
{
|
||||
/* This hash table that maps pseudos to debug temps. */
|
||||
hash_table <dead_debug_hash_descr> htab;
|
||||
/* For each entry in htab, the bit corresponding to its REGNO will
|
||||
be set. */
|
||||
bitmap used;
|
||||
};
|
||||
|
||||
/* Node of a linked list of uses of dead REGs in debug insns. */
|
||||
|
||||
struct dead_debug_use
|
||||
{
|
||||
df_ref use;
|
||||
@ -38,15 +99,25 @@ struct dead_debug_use
|
||||
|
||||
/* Linked list of the above, with a bitmap of the REGs in the
|
||||
list. */
|
||||
struct dead_debug
|
||||
|
||||
struct dead_debug_local
|
||||
{
|
||||
/* The first dead_debug_use entry in the list. */
|
||||
struct dead_debug_use *head;
|
||||
/* A pointer to the global tracking data structure. */
|
||||
struct dead_debug_global *global;
|
||||
/* A bitmap that has bits set for each REG used in the
|
||||
dead_debug_use list, and for each entry in the global hash
|
||||
table. */
|
||||
bitmap used;
|
||||
/* A bitmap that has bits set for each INSN that is to be
|
||||
rescanned. */
|
||||
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
|
||||
@ -62,10 +133,13 @@ enum debug_temp_where
|
||||
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 *,
|
||||
extern void dead_debug_global_init (struct dead_debug_global *, bitmap);
|
||||
extern void dead_debug_global_finish (struct dead_debug_global *, bitmap);
|
||||
extern void dead_debug_local_init (struct dead_debug_local *, bitmap,
|
||||
struct dead_debug_global *);
|
||||
extern void dead_debug_local_finish (struct dead_debug_local *, bitmap);
|
||||
extern void dead_debug_add (struct dead_debug_local *, df_ref, unsigned int);
|
||||
extern int dead_debug_insert_temp (struct dead_debug_local *,
|
||||
unsigned int uregno, rtx insn,
|
||||
enum debug_temp_where);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user