OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / df-problems.c
index 59bed8b..c9fc91b 100644 (file)
@@ -1,6 +1,6 @@
 /* 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)
@@ -2748,10 +2748,12 @@ df_ignore_stack_reg (int regno ATTRIBUTE_UNUSED)
 
 
 /* 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 = &REG_NOTES (insn);
   rtx link = *pprev;
@@ -2798,6 +2800,47 @@ df_kill_notes (rtx insn)
            }
          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;
@@ -3096,6 +3139,7 @@ static void
 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;
 
@@ -3113,9 +3157,25 @@ dead_debug_reset (struct dead_debug *debug, unsigned int dregno)
            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;
+       }
     }
 }
 
@@ -3174,7 +3234,10 @@ dead_debug_insert_before (struct dead_debug *debug, unsigned int uregno,
        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);
@@ -3279,7 +3342,7 @@ df_note_bb_compute (unsigned int bb_index,
       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))
@@ -3356,7 +3419,7 @@ df_note_bb_compute (unsigned int bb_index,
       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;