/* Standard problems for dataflow support routines.
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+ 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
Originally contributed by Michael P. Hayes
(m.hayes@elec.canterbury.ac.nz, mhayes@redhat.com)
Major rewrite contributed by Danny Berlin (dberlin@dberlin.org)
/* Remove all of the REG_DEAD or REG_UNUSED notes from INSN and add
- them to OLD_DEAD_NOTES and OLD_UNUSED_NOTES. */
+ them to OLD_DEAD_NOTES and OLD_UNUSED_NOTES. Remove also
+ REG_EQUAL/REG_EQUIV notes referring to dead pseudos using LIVE
+ as the bitmap of currently live registers. */
static void
-df_kill_notes (rtx insn)
+df_kill_notes (rtx insn, bitmap live)
{
rtx *pprev = ®_NOTES (insn);
rtx link = *pprev;
}
break;
+ case REG_EQUAL:
+ case REG_EQUIV:
+ {
+ /* Remove the notes that refer to dead registers. As we have at most
+ one REG_EQUAL/EQUIV note, all of EQ_USES will refer to this note
+ so we need to purge the complete EQ_USES vector when removing
+ the note using df_notes_rescan. */
+ df_ref *use_rec;
+ bool deleted = false;
+
+ for (use_rec = DF_INSN_EQ_USES (insn); *use_rec; use_rec++)
+ {
+ df_ref use = *use_rec;
+ if (DF_REF_REGNO (use) > FIRST_PSEUDO_REGISTER
+ && DF_REF_LOC (use)
+ && (DF_REF_FLAGS (use) & DF_REF_IN_NOTE)
+ && ! bitmap_bit_p (live, DF_REF_REGNO (use))
+ && loc_mentioned_in_p (DF_REF_LOC (use), XEXP (link, 0)))
+ {
+ deleted = true;
+ break;
+ }
+ }
+ if (deleted)
+ {
+ rtx next;
+#ifdef REG_DEAD_DEBUGGING
+ df_print_note ("deleting: ", insn, link);
+#endif
+ next = XEXP (link, 1);
+ free_EXPR_LIST_node (link);
+ *pprev = link = next;
+ df_notes_rescan (insn);
+ }
+ else
+ {
+ pprev = &XEXP (link, 1);
+ link = *pprev;
+ }
+ break;
+ }
default:
pprev = &XEXP (link, 1);
link = *pprev;
dead_debug_reset (struct dead_debug *debug, unsigned int dregno)
{
struct dead_debug_use **tailp = &debug->head;
+ struct dead_debug_use **insnp = &debug->head;
struct dead_debug_use *cur;
rtx insn;
debug->to_rescan = BITMAP_ALLOC (NULL);
bitmap_set_bit (debug->to_rescan, INSN_UID (insn));
XDELETE (cur);
+ /* If the current use isn't the first one attached to INSN, go back
+ to this first use. We assume that the uses attached to an insn
+ are adjacent. */
+ if (tailp != insnp && DF_REF_INSN ((*insnp)->use) == insn)
+ tailp = insnp;
+ /* Then remove all the other uses attached to INSN. */
+ while ((cur = *tailp) && DF_REF_INSN (cur->use) == insn)
+ {
+ *tailp = cur->next;
+ XDELETE (cur);
+ }
+ insnp = tailp;
}
else
- tailp = &(*tailp)->next;
+ {
+ if (DF_REF_INSN ((*insnp)->use) != DF_REF_INSN (cur->use))
+ insnp = tailp;
+ tailp = &(*tailp)->next;
+ }
}
}
tailp = &(*tailp)->next;
}
- gcc_assert (reg);
+ /* We may have dangling bits in debug->used for registers that were part
+ of a multi-register use, one component of which has been reset. */
+ if (reg == NULL)
+ return;
/* Create DEBUG_EXPR (and DEBUG_EXPR_DECL). */
dval = make_debug_expr_from_rtl (reg);
debug_insn = DEBUG_INSN_P (insn);
bitmap_clear (do_not_gen);
- df_kill_notes (insn);
+ df_kill_notes (insn, live);
/* Process the defs. */
if (CALL_P (insn))
while (*mws_rec)
{
struct df_mw_hardreg *mws = *mws_rec;
- if ((DF_MWS_REG_DEF_P (mws))
+ if (DF_MWS_REG_USE_P (mws)
&& !df_ignore_stack_reg (mws->start_regno))
{
bool really_add_notes = debug_insn != 0;