OSDN Git Service

2005-06-14 Doug Rupp <rupp@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / flow.c
index c58fd49..b73ac4d 100644 (file)
@@ -273,7 +273,7 @@ static int ndead;
    (remember, we are walking backward).  This can be computed as current
    pbi->insn_num - reg_deaths[regno].
    At the end of processing each basic block, the remaining live registers
-   are inspected and liferanges are increased same way so liverange of global
+   are inspected and live ranges are increased same way so liverange of global
    registers are computed correctly.
   
    The array is maintained clear for dead registers, so it can be safely reused
@@ -653,7 +653,9 @@ update_life_info (sbitmap blocks, enum update_life_extent extent,
 
   if (blocks)
     {
-      EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i,
+      sbitmap_iterator sbi;
+
+      EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i, sbi)
        {
          bb = BASIC_BLOCK (i);
 
@@ -662,7 +664,7 @@ update_life_info (sbitmap blocks, enum update_life_extent extent,
 
          if (extent == UPDATE_LIFE_LOCAL)
            verify_local_live_at_start (tmp, bb);
-       });
+       };
     }
   else
     {
@@ -760,6 +762,9 @@ free_basic_block_vars (void)
     }
   n_basic_blocks = 0;
   last_basic_block = 0;
+  n_edges = 0;
+
+  label_to_block_map = NULL;
 
   ENTRY_BLOCK_PTR->aux = NULL;
   ENTRY_BLOCK_PTR->global_live_at_end = NULL;
@@ -1029,7 +1034,7 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
      In other words, regs that are set only as part of a COND_EXEC.  */
   regset *cond_local_sets;
 
-  int i;
+  unsigned int i;
 
   /* Some passes used to forget clear aux field of basic block causing
      sick behavior here.  */
@@ -1403,12 +1408,14 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
 
   if (blocks_out)
     {
-      EXECUTE_IF_SET_IN_SBITMAP (blocks_out, 0, i,
+      sbitmap_iterator sbi;
+
+      EXECUTE_IF_SET_IN_SBITMAP (blocks_out, 0, i, sbi)
        {
          basic_block bb = BASIC_BLOCK (i);
          FREE_REG_SET (local_sets[bb->index - (INVALID_BLOCK + 1)]);
          FREE_REG_SET (cond_local_sets[bb->index - (INVALID_BLOCK + 1)]);
-       });
+       };
     }
   else
     {
@@ -1689,8 +1696,12 @@ propagate_one_insn (struct propagate_block_info *pbi, rtx insn)
        fatal_insn ("Attempt to delete prologue/epilogue insn:", insn);
 
       /* Record sets.  Do this even for dead instructions, since they
-        would have killed the values if they hadn't been deleted.  */
+        would have killed the values if they hadn't been deleted.  To
+        be consistent, we also have to emit a clobber when we delete
+        an insn that clobbers a live register.  */
+      pbi->flags |= PROP_DEAD_INSN;
       mark_set_regs (pbi, PATTERN (insn), insn);
+      pbi->flags &= ~PROP_DEAD_INSN;
 
       /* CC0 is now known to be dead.  Either this insn used it,
         in which case it doesn't anymore, or clobbered it,
@@ -1795,7 +1806,6 @@ propagate_one_insn (struct propagate_block_info *pbi, rtx insn)
     }
   else
     {
-      rtx note;
       /* Any regs live at the time of a call instruction must not go
         in a register clobbered by calls.  Find all regs now live and
         record this for them.  */
@@ -1870,10 +1880,6 @@ propagate_one_insn (struct propagate_block_info *pbi, rtx insn)
       /* Record uses.  */
       if (! insn_is_dead)
        mark_used_regs (pbi, PATTERN (insn), NULL_RTX, insn);
-      if ((flags & PROP_EQUAL_NOTES)
-         && ((note = find_reg_note (insn, REG_EQUAL, NULL_RTX))
-             || (note = find_reg_note (insn, REG_EQUIV, NULL_RTX))))
-       mark_used_regs (pbi, XEXP (note, 0), NULL_RTX, insn);
 
       /* Sometimes we may have inserted something before INSN (such as a move)
         when we make an auto-inc.  So ensure we will scan those insns.  */
@@ -2530,7 +2536,8 @@ invalidate_mems_from_autoinc (rtx *px, void *data)
   return 0;
 }
 
-/* EXP is a REG.  Remove any dependent entries from pbi->mem_set_list.  */
+/* EXP is a REG or MEM.  Remove any dependent entries from
+   pbi->mem_set_list.  */
 
 static void
 invalidate_mems_from_set (struct propagate_block_info *pbi, rtx exp)
@@ -2542,7 +2549,12 @@ invalidate_mems_from_set (struct propagate_block_info *pbi, rtx exp)
   while (temp)
     {
       next = XEXP (temp, 1);
-      if (reg_overlap_mentioned_p (exp, XEXP (temp, 0)))
+      if ((REG_P (exp) && reg_overlap_mentioned_p (exp, XEXP (temp, 0)))
+         /* When we get an EXP that is a mem here, we want to check if EXP
+            overlaps the *address* of any of the mems in the list (i.e. not
+            whether the mems actually overlap; that's done elsewhere).  */
+         || (MEM_P (exp)
+             && reg_overlap_mentioned_p (exp, XEXP (XEXP (temp, 0), 0))))
        {
          /* Splice this entry out of the list.  */
          if (prev)
@@ -2748,11 +2760,12 @@ mark_set_1 (struct propagate_block_info *pbi, enum rtx_code code, rtx reg, rtx c
       break;
     }
 
-  /* If this set is a MEM, then it kills any aliased writes.
+  /* If this set is a MEM, then it kills any aliased writes and any
+     other MEMs which use it.
      If this set is a REG, then it kills any MEMs which use the reg.  */
   if (optimize && (flags & PROP_SCAN_DEAD_STORES))
     {
-      if (REG_P (reg))
+      if (REG_P (reg) || MEM_P (reg))
        invalidate_mems_from_set (pbi, reg);
 
       /* If the memory reference had embedded side effects (autoincrement
@@ -2955,6 +2968,8 @@ mark_set_1 (struct propagate_block_info *pbi, enum rtx_code code, rtx reg, rtx c
                  }
                CLEAR_REGNO_REG_SET (pbi->reg_live, i);
              }
+         if (flags & PROP_DEAD_INSN)
+           emit_insn_after (gen_rtx_CLOBBER (VOIDmode, reg), insn);
        }
     }
   else if (REG_P (reg))
@@ -4329,9 +4344,10 @@ void
 recompute_reg_usage (void)
 {
   allocate_reg_life_data ();
-  /* distribute_notes in combiner fails to convert some of the REG_UNUSED notes
-   to REG_DEAD notes.  This causes CHECK_DEAD_NOTES in sched1 to abort.  To 
-   solve this update the DEATH_NOTES here.  */
+  /* distribute_notes in combiner fails to convert some of the
+     REG_UNUSED notes to REG_DEAD notes.  This causes CHECK_DEAD_NOTES
+     in sched1 to die.  To solve this update the DEATH_NOTES
+     here.  */
   update_life_info (NULL, UPDATE_LIFE_LOCAL, PROP_REG_INFO | PROP_DEATH_NOTES);
 }
 
@@ -4343,7 +4359,7 @@ int
 count_or_remove_death_notes (sbitmap blocks, int kill)
 {
   int count = 0;
-  int i;
+  unsigned int i;
   basic_block bb;
 
   /* This used to be a loop over all the blocks with a membership test
@@ -4355,10 +4371,12 @@ count_or_remove_death_notes (sbitmap blocks, int kill)
      than an sbitmap.  */
   if (blocks)
     {
-      EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i,
+      sbitmap_iterator sbi;
+
+      EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i, sbi)
        {
          count += count_or_remove_death_notes_bb (BASIC_BLOCK (i), kill);
-       });
+       };
     }
   else
     {
@@ -4438,7 +4456,6 @@ static void
 clear_log_links (sbitmap blocks)
 {
   rtx insn;
-  int i;
 
   if (!blocks)
     {
@@ -4447,15 +4464,20 @@ clear_log_links (sbitmap blocks)
          free_INSN_LIST_list (&LOG_LINKS (insn));
     }
   else
-    EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i,
-      {
-       basic_block bb = BASIC_BLOCK (i);
+    {
+      unsigned int i;
+      sbitmap_iterator sbi;
 
-       for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
-            insn = NEXT_INSN (insn))
-         if (INSN_P (insn))
-           free_INSN_LIST_list (&LOG_LINKS (insn));
-      });
+      EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i, sbi)
+       {
+         basic_block bb = BASIC_BLOCK (i);
+
+         for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
+              insn = NEXT_INSN (insn))
+           if (INSN_P (insn))
+             free_INSN_LIST_list (&LOG_LINKS (insn));
+       }
+    }
 }
 
 /* Given a register bitmap, turn on the bits in a HARD_REG_SET that