OSDN Git Service

* combine.c (simplify_shift_const): Calculate rotate count
[pf3gnuchains/gcc-fork.git] / gcc / flow.c
index fdf4df2..3a7326a 100644 (file)
@@ -1,6 +1,6 @@
 /* Data flow analysis for GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -140,9 +140,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "obstack.h"
 #include "splay-tree.h"
 
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
 /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
    the stack pointer does not matter.  The value is tested only in
    functions that have frame pointers.
@@ -167,6 +164,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #ifndef EPILOGUE_USES
 #define EPILOGUE_USES(REGNO)  0
 #endif
+#ifndef EH_USES
+#define EH_USES(REGNO)  0
+#endif
 
 #ifdef HAVE_conditional_execution
 #ifndef REVERSE_CONDEXEC_PREDICATES_P
@@ -276,18 +276,16 @@ struct propagate_block_info
   int flags;
 };
 
+/* Number of dead insns removed.  */
+static int ndead;
+
 /* Maximum length of pbi->mem_set_list before we start dropping
    new elements on the floor.  */
 #define MAX_MEM_SET_LIST_LEN   100
 
-/* Have print_rtl_and_abort give the same information that fancy_abort
-   does.  */
-#define print_rtl_and_abort() \
-  print_rtl_and_abort_fcn (__FILE__, __LINE__, __FUNCTION__)
-
 /* Forward declarations */
 static int verify_wide_reg_1           PARAMS ((rtx *, void *));
-static void verify_wide_reg            PARAMS ((int, rtx, rtx));
+static void verify_wide_reg            PARAMS ((int, basic_block));
 static void verify_local_live_at_start PARAMS ((regset, basic_block));
 static void notice_stack_pointer_modification_1 PARAMS ((rtx, rtx, void *));
 static void notice_stack_pointer_modification PARAMS ((rtx));
@@ -295,7 +293,7 @@ static void mark_reg                        PARAMS ((rtx, void *));
 static void mark_regs_live_at_end      PARAMS ((regset));
 static int set_phi_alternative_reg      PARAMS ((rtx, int, int, void *));
 static void calculate_global_regs_live PARAMS ((sbitmap, sbitmap, int));
-static void propagate_block_delete_insn PARAMS ((basic_block, rtx));
+static void propagate_block_delete_insn PARAMS ((rtx));
 static rtx propagate_block_delete_libcall PARAMS ((rtx, rtx));
 static int insn_dead_p                 PARAMS ((struct propagate_block_info *,
                                                 rtx, int, rtx));
@@ -306,6 +304,8 @@ static void mark_set_regs           PARAMS ((struct propagate_block_info *,
 static void mark_set_1                 PARAMS ((struct propagate_block_info *,
                                                 enum rtx_code, rtx, rtx,
                                                 rtx, int));
+static int find_regno_partial          PARAMS ((rtx *, void *));
+
 #ifdef HAVE_conditional_execution
 static int mark_regno_cond_dead                PARAMS ((struct propagate_block_info *,
                                                 int, rtx));
@@ -333,17 +333,11 @@ static void mark_used_regs                PARAMS ((struct propagate_block_info *,
                                                 rtx, rtx, rtx));
 void dump_flow_info                    PARAMS ((FILE *));
 void debug_flow_info                   PARAMS ((void));
-static void print_rtl_and_abort_fcn    PARAMS ((const char *, int,
-                                                const char *))
-                                       ATTRIBUTE_NORETURN;
-
 static void add_to_mem_set_list                PARAMS ((struct propagate_block_info *,
                                                 rtx));
-static void invalidate_mems_from_autoinc PARAMS ((struct propagate_block_info *,
-                                                 rtx));
+static int invalidate_mems_from_autoinc PARAMS ((rtx *, void *));
 static void invalidate_mems_from_set   PARAMS ((struct propagate_block_info *,
                                                 rtx));
-static void delete_dead_jumptables     PARAMS ((void));
 static void clear_log_links            PARAMS ((sbitmap));
 \f
 
@@ -376,10 +370,14 @@ check_function_return_warnings ()
         is no longer in the chain.  */
       if (INSN_UID (cfun->x_clobber_return_insn) < max_uid)
        {
-         /* Recompute insn->block mapping, since the initial mapping is
-            set before we delete unreachable blocks.  */
-         if (BLOCK_FOR_INSN (cfun->x_clobber_return_insn) != NULL)
-           warning ("control reaches end of non-void function");
+         rtx insn;
+
+         for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+           if (insn == cfun->x_clobber_return_insn)
+             {
+               warning ("control reaches end of non-void function");
+               break;
+             }
        }
     }
 }
@@ -450,13 +448,12 @@ life_analysis (f, file, flags)
     flags &= ~(PROP_REG_INFO | PROP_AUTOINC);
 
   /* We want alias analysis information for local dead store elimination.  */
-  if (optimize && (flags & PROP_SCAN_DEAD_CODE))
+  if (optimize && (flags & PROP_SCAN_DEAD_STORES))
     init_alias_analysis ();
 
   /* Always remove no-op moves.  Do this before other processing so
      that we don't have to keep re-scanning them.  */
   delete_noop_moves (f);
-  purge_all_dead_edges (false);
 
   /* Some targets can emit simpler epilogues if they know that sp was
      not ever modified during the function.  After reload, of course,
@@ -481,7 +478,7 @@ life_analysis (f, file, flags)
   update_life_info (NULL, UPDATE_LIFE_GLOBAL, flags);
 
   /* Clean up.  */
-  if (optimize && (flags & PROP_SCAN_DEAD_CODE))
+  if (optimize && (flags & PROP_SCAN_DEAD_STORES))
     end_alias_analysis ();
 
   if (file)
@@ -489,26 +486,13 @@ life_analysis (f, file, flags)
 
   free_basic_block_vars (1);
 
-#ifdef ENABLE_CHECKING
-  {
-    rtx insn;
-
-    /* Search for any REG_LABEL notes which reference deleted labels.  */
-    for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
-      {
-       rtx inote = find_reg_note (insn, REG_LABEL, NULL_RTX);
-
-       if (inote && GET_CODE (inote) == NOTE_INSN_DELETED_LABEL)
-         abort ();
-      }
-  }
-#endif
   /* Removing dead insns should've made jumptables really dead.  */
   delete_dead_jumptables ();
 }
 
 /* A subroutine of verify_wide_reg, called through for_each_rtx.
-   Search for REGNO.  If found, abort if it is not wider than word_mode.  */
+   Search for REGNO.  If found, return 2 if it is not wider than
+   word_mode.  */
 
 static int
 verify_wide_reg_1 (px, pregno)
@@ -521,34 +505,43 @@ verify_wide_reg_1 (px, pregno)
   if (GET_CODE (x) == REG && REGNO (x) == regno)
     {
       if (GET_MODE_BITSIZE (GET_MODE (x)) <= BITS_PER_WORD)
-       abort ();
+       return 2;
       return 1;
     }
   return 0;
 }
 
 /* A subroutine of verify_local_live_at_start.  Search through insns
-   between HEAD and END looking for register REGNO.  */
+   of BB looking for register REGNO.  */
 
 static void
-verify_wide_reg (regno, head, end)
+verify_wide_reg (regno, bb)
      int regno;
-     rtx head, end;
+     basic_block bb;
 {
+  rtx head = bb->head, end = bb->end;
+
   while (1)
     {
-      if (INSN_P (head)
-         && for_each_rtx (&PATTERN (head), verify_wide_reg_1, &regno))
-       return;
+      if (INSN_P (head))
+       {
+         int r = for_each_rtx (&PATTERN (head), verify_wide_reg_1, &regno);
+         if (r == 1)
+           return;
+         if (r == 2)
+           break;
+       }
       if (head == end)
        break;
       head = NEXT_INSN (head);
     }
 
-  /* We didn't find the register at all.  Something's way screwy.  */
   if (rtl_dump_file)
-    fprintf (rtl_dump_file, "Aborting in verify_wide_reg; reg %d\n", regno);
-  print_rtl_and_abort ();
+    {
+      fprintf (rtl_dump_file, "Register %d died unexpectedly.\n", regno);
+      dump_bb (bb, rtl_dump_file);
+    }
+  abort ();
 }
 
 /* A subroutine of update_life_info.  Verify that there are no untoward
@@ -568,12 +561,13 @@ verify_local_live_at_start (new_live_at_start, bb)
          if (rtl_dump_file)
            {
              fprintf (rtl_dump_file,
-                      "live_at_start mismatch in bb %d, aborting\n",
+                      "live_at_start mismatch in bb %d, aborting\nNew:\n",
                       bb->index);
-             debug_bitmap_file (rtl_dump_file, bb->global_live_at_start);
              debug_bitmap_file (rtl_dump_file, new_live_at_start);
+             fputs ("Old:\n", rtl_dump_file);
+             dump_bb (bb, rtl_dump_file);
            }
-         print_rtl_and_abort ();
+         abort ();
        }
     }
   else
@@ -585,18 +579,20 @@ verify_local_live_at_start (new_live_at_start, bb)
 
       EXECUTE_IF_SET_IN_REG_SET (new_live_at_start, 0, i,
        {
-          /* No registers should die.  */
+         /* No registers should die.  */
          if (REGNO_REG_SET_P (bb->global_live_at_start, i))
            {
              if (rtl_dump_file)
-               fprintf (rtl_dump_file,
-                        "Register %d died unexpectedly in block %d\n", i,
-                        bb->index);
-             print_rtl_and_abort ();
+               {
+                 fprintf (rtl_dump_file,
+                          "Register %d died unexpectedly.\n", i);
+                 dump_bb (bb, rtl_dump_file);
+               }
+             abort ();
            }
 
-          /* Verify that the now-live register is wider than word_mode.  */
-         verify_wide_reg (i, bb->head, bb->end);
+         /* Verify that the now-live register is wider than word_mode.  */
+         verify_wide_reg (i, bb);
        });
     }
 }
@@ -618,7 +614,7 @@ verify_local_live_at_start (new_live_at_start, bb)
    Including PROP_REG_INFO does not properly refresh regs_ever_live
    unless the caller resets it to zero.  */
 
-void
+int
 update_life_info (blocks, extent, prop_flags)
      sbitmap blocks;
      enum update_life_extent extent;
@@ -627,8 +623,11 @@ update_life_info (blocks, extent, prop_flags)
   regset tmp;
   regset_head tmp_head;
   int i;
+  int stabilized_prop_flags = prop_flags;
+  basic_block bb;
 
   tmp = INITIALIZE_REG_SET (tmp_head);
+  ndead = 0;
 
   timevar_push ((extent == UPDATE_LIFE_LOCAL || blocks)
                ? TV_LIFE_UPDATE : TV_LIFE);
@@ -639,10 +638,6 @@ update_life_info (blocks, extent, prop_flags)
       && (extent == UPDATE_LIFE_LOCAL || blocks))
     abort ();
 
-  /* Clear log links in case we are asked to (re)compute them.  */
-  if (prop_flags & PROP_LOG_LINKS)
-    clear_log_links (blocks);
-
   /* For a global update, we go through the relaxation process again.  */
   if (extent != UPDATE_LIFE_LOCAL)
     {
@@ -652,6 +647,7 @@ update_life_info (blocks, extent, prop_flags)
 
          calculate_global_regs_live (blocks, blocks,
                                prop_flags & (PROP_SCAN_DEAD_CODE
+                                             | PROP_SCAN_DEAD_STORES
                                              | PROP_ALLOW_CFG_CHANGES));
 
          if ((prop_flags & (PROP_KILL_DEAD_CODE | PROP_ALLOW_CFG_CHANGES))
@@ -660,18 +656,31 @@ update_life_info (blocks, extent, prop_flags)
 
          /* Removing dead code may allow the CFG to be simplified which
             in turn may allow for further dead code detection / removal.  */
-         for (i = n_basic_blocks - 1; i >= 0; --i)
+         FOR_EACH_BB_REVERSE (bb)
            {
-             basic_block bb = BASIC_BLOCK (i);
-
              COPY_REG_SET (tmp, bb->global_live_at_end);
              changed |= propagate_block (bb, tmp, NULL, NULL,
                                prop_flags & (PROP_SCAN_DEAD_CODE
+                                             | PROP_SCAN_DEAD_STORES
                                              | PROP_KILL_DEAD_CODE));
            }
 
-         if (! changed || ! cleanup_cfg (CLEANUP_EXPENSIVE))
+         /* Don't pass PROP_SCAN_DEAD_CODE or PROP_KILL_DEAD_CODE to
+            subsequent propagate_block calls, since removing or acting as
+            removing dead code can affect global register liveness, which
+            is supposed to be finalized for this call after this loop.  */
+         stabilized_prop_flags
+           &= ~(PROP_SCAN_DEAD_CODE | PROP_SCAN_DEAD_STORES
+                | PROP_KILL_DEAD_CODE);
+
+         if (! changed)
            break;
+
+         /* We repeat regardless of what cleanup_cfg says.  If there were
+            instructions deleted above, that might have been only a
+            partial improvement (see MAX_MEM_SET_LIST_LEN usage).
+            Further improvement may be possible.  */
+         cleanup_cfg (CLEANUP_EXPENSIVE);
        }
 
       /* If asked, remove notes from the blocks we'll update.  */
@@ -679,14 +688,18 @@ update_life_info (blocks, extent, prop_flags)
        count_or_remove_death_notes (blocks, 1);
     }
 
+  /* Clear log links in case we are asked to (re)compute them.  */
+  if (prop_flags & PROP_LOG_LINKS)
+    clear_log_links (blocks);
+
   if (blocks)
     {
       EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i,
        {
-         basic_block bb = BASIC_BLOCK (i);
+         bb = BASIC_BLOCK (i);
 
          COPY_REG_SET (tmp, bb->global_live_at_end);
-         propagate_block (bb, tmp, NULL, NULL, prop_flags);
+         propagate_block (bb, tmp, NULL, NULL, stabilized_prop_flags);
 
          if (extent == UPDATE_LIFE_LOCAL)
            verify_local_live_at_start (tmp, bb);
@@ -694,12 +707,11 @@ update_life_info (blocks, extent, prop_flags)
     }
   else
     {
-      for (i = n_basic_blocks - 1; i >= 0; --i)
+      FOR_EACH_BB_REVERSE (bb)
        {
-         basic_block bb = BASIC_BLOCK (i);
-
          COPY_REG_SET (tmp, bb->global_live_at_end);
-         propagate_block (bb, tmp, NULL, NULL, prop_flags);
+
+         propagate_block (bb, tmp, NULL, NULL, stabilized_prop_flags);
 
          if (extent == UPDATE_LIFE_LOCAL)
            verify_local_live_at_start (tmp, bb);
@@ -738,6 +750,49 @@ update_life_info (blocks, extent, prop_flags)
     }
   timevar_pop ((extent == UPDATE_LIFE_LOCAL || blocks)
               ? TV_LIFE_UPDATE : TV_LIFE);
+  if (ndead && rtl_dump_file)
+    fprintf (rtl_dump_file, "deleted %i dead insns\n", ndead);
+  return ndead;
+}
+
+/* Update life information in all blocks where BB_DIRTY is set.  */
+
+int
+update_life_info_in_dirty_blocks (extent, prop_flags)
+     enum update_life_extent extent;
+     int prop_flags;
+{
+  sbitmap update_life_blocks = sbitmap_alloc (last_basic_block);
+  int n = 0;
+  basic_block bb;
+  int retval = 0;
+
+  sbitmap_zero (update_life_blocks);
+  FOR_EACH_BB (bb)
+    {
+      if (extent == UPDATE_LIFE_LOCAL)
+       {
+         if (bb->flags & BB_DIRTY)
+           {
+             SET_BIT (update_life_blocks, bb->index);
+             n++;
+           }
+       }
+      else
+       {
+         /* ??? Bootstrap with -march=pentium4 fails to terminate
+            with only a partial life update.  */
+         SET_BIT (update_life_blocks, bb->index);
+         if (bb->flags & BB_DIRTY)
+           n++;
+       }
+    }
+
+  if (n)
+    retval = update_life_info (update_life_blocks, extent, prop_flags);
+
+  sbitmap_free (update_life_blocks);
+  return retval;
 }
 
 /* Free the variables allocated by find_basic_blocks.
@@ -756,6 +811,7 @@ free_basic_block_vars (keep_head_end_p)
          VARRAY_FREE (basic_block_info);
        }
       n_basic_blocks = 0;
+      last_basic_block = 0;
 
       ENTRY_BLOCK_PTR->aux = NULL;
       ENTRY_BLOCK_PTR->global_live_at_end = NULL;
@@ -766,17 +822,16 @@ free_basic_block_vars (keep_head_end_p)
 
 /* Delete any insns that copy a register to itself.  */
 
-void
+int
 delete_noop_moves (f)
      rtx f ATTRIBUTE_UNUSED;
 {
-  int i;
   rtx insn, next;
   basic_block bb;
+  int nnoops = 0;
 
-  for (i = 0; i < n_basic_blocks; i++)
+  FOR_EACH_BB (bb)
     {
-      bb = BASIC_BLOCK (i);
       for (insn = bb->head; insn != NEXT_INSN (bb->end); insn = next)
        {
          next = NEXT_INSN (insn);
@@ -799,21 +854,21 @@ delete_noop_moves (f)
                  XEXP (retval_note, 0) = new_libcall_insn;
                }
 
-             /* Do not call delete_insn here since that may change
-                the basic block boundaries which upsets some callers.  */
-             PUT_CODE (insn, NOTE);
-             NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-             NOTE_SOURCE_FILE (insn) = 0;
+             delete_insn_and_edges (insn);
+             nnoops++;
            }
        }
     }
+  if (nnoops && rtl_dump_file)
+    fprintf (rtl_dump_file, "deleted %i noop moves", nnoops);
+  return nnoops;
 }
 
 /* Delete any jump tables never referenced.  We can't delete them at the
    time of removing tablejump insn as they are referenced by the preceding
    insns computing the destination, so we delay deleting and garbagecollect
    them once life information is computed.  */
-static void
+void
 delete_dead_jumptables ()
 {
   rtx insn, next;
@@ -933,7 +988,7 @@ mark_regs_live_at_end (set)
 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
       /* If they are different, also mark the hard frame pointer as live.  */
       if (! LOCAL_REGNO (HARD_FRAME_POINTER_REGNUM))
-        SET_REGNO_REG_SET (set, HARD_FRAME_POINTER_REGNUM);
+       SET_REGNO_REG_SET (set, HARD_FRAME_POINTER_REGNUM);
 #endif
     }
 
@@ -1023,20 +1078,28 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
      sbitmap blocks_in, blocks_out;
      int flags;
 {
-  basic_block *queue, *qhead, *qtail, *qend;
-  regset tmp, new_live_at_end, call_used;
-  regset_head tmp_head, call_used_head;
+  basic_block *queue, *qhead, *qtail, *qend, bb;
+  regset tmp, new_live_at_end, invalidated_by_call;
+  regset_head tmp_head, invalidated_by_call_head;
   regset_head new_live_at_end_head;
   int i;
 
+  /* Some passes used to forget clear aux field of basic block causing
+     sick behaviour here.  */
+#ifdef ENABLE_CHECKING
+  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+    if (bb->aux)
+      abort ();
+#endif
+
   tmp = INITIALIZE_REG_SET (tmp_head);
   new_live_at_end = INITIALIZE_REG_SET (new_live_at_end_head);
-  call_used = INITIALIZE_REG_SET (call_used_head);
+  invalidated_by_call = INITIALIZE_REG_SET (invalidated_by_call_head);
 
-  /* Inconveniently, this is only redily available in hard reg set form.  */
+  /* Inconveniently, this is only readily available in hard reg set form.  */
   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
-    if (call_used_regs[i])
-      SET_REGNO_REG_SET (call_used, i);
+    if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
+      SET_REGNO_REG_SET (invalidated_by_call, i);
 
   /* Create a worklist.  Allocate an extra slot for ENTRY_BLOCK, and one
      because the `head == tail' style test for an empty queue doesn't
@@ -1050,27 +1113,27 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
      useful work.  We use AUX non-null to flag that the block is queued.  */
   if (blocks_in)
     {
-      /* Clear out the garbage that might be hanging out in bb->aux.  */
-      for (i = n_basic_blocks - 1; i >= 0; --i)
-       BASIC_BLOCK (i)->aux = NULL;
-
-      EXECUTE_IF_SET_IN_SBITMAP (blocks_in, 0, i,
-       {
-         basic_block bb = BASIC_BLOCK (i);
-         *--qhead = bb;
-         bb->aux = bb;
-       });
+      FOR_EACH_BB (bb)
+       if (TEST_BIT (blocks_in, bb->index))
+         {
+           *--qhead = bb;
+           bb->aux = bb;
+         }
     }
   else
     {
-      for (i = 0; i < n_basic_blocks; ++i)
+      FOR_EACH_BB (bb)
        {
-         basic_block bb = BASIC_BLOCK (i);
          *--qhead = bb;
          bb->aux = bb;
        }
     }
 
+  /* We clean aux when we remove the initially-enqueued bbs, but we
+     don't enqueue ENTRY and EXIT initially, so clean them upfront and
+     unconditionally.  */
+  ENTRY_BLOCK_PTR->aux = EXIT_BLOCK_PTR->aux = NULL;
+
   if (blocks_out)
     sbitmap_zero (blocks_out);
 
@@ -1105,21 +1168,40 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
 
       /* Begin by propagating live_at_start from the successor blocks.  */
       CLEAR_REG_SET (new_live_at_end);
-      for (e = bb->succ; e; e = e->succ_next)
-       {
-         basic_block sb = e->dest;
 
-         /* Call-clobbered registers die across exception and call edges.  */
-         /* ??? Abnormal call edges ignored for the moment, as this gets
-            confused by sibling call edges, which crashes reg-stack.  */
-         if (e->flags & EDGE_EH)
-           {
-             bitmap_operation (tmp, sb->global_live_at_start,
-                               call_used, BITMAP_AND_COMPL);
-             IOR_REG_SET (new_live_at_end, tmp);
-           }
-         else
-           IOR_REG_SET (new_live_at_end, sb->global_live_at_start);
+      if (bb->succ)
+       for (e = bb->succ; e; e = e->succ_next)
+         {
+           basic_block sb = e->dest;
+
+           /* Call-clobbered registers die across exception and
+              call edges.  */
+           /* ??? Abnormal call edges ignored for the moment, as this gets
+              confused by sibling call edges, which crashes reg-stack.  */
+           if (e->flags & EDGE_EH)
+             {
+               bitmap_operation (tmp, sb->global_live_at_start,
+                                 invalidated_by_call, BITMAP_AND_COMPL);
+               IOR_REG_SET (new_live_at_end, tmp);
+             }
+           else
+             IOR_REG_SET (new_live_at_end, sb->global_live_at_start);
+
+           /* If a target saves one register in another (instead of on
+              the stack) the save register will need to be live for EH.  */
+           if (e->flags & EDGE_EH)
+             for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+               if (EH_USES (i))
+                 SET_REGNO_REG_SET (new_live_at_end, i);
+         }
+      else
+       {
+         /* This might be a noreturn function that throws.  And
+            even if it isn't, getting the unwind info right helps
+            debugging.  */
+         for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+           if (EH_USES (i))
+             SET_REGNO_REG_SET (new_live_at_end, i);
        }
 
       /* The all-important stack pointer must always be live.  */
@@ -1267,7 +1349,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
 
   FREE_REG_SET (tmp);
   FREE_REG_SET (new_live_at_end);
-  FREE_REG_SET (call_used);
+  FREE_REG_SET (invalidated_by_call);
 
   if (blocks_out)
     {
@@ -1280,9 +1362,8 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
     }
   else
     {
-      for (i = n_basic_blocks - 1; i >= 0; --i)
+      FOR_EACH_BB (bb)
        {
-         basic_block bb = BASIC_BLOCK (i);
          FREE_REG_SET (bb->local_set);
          FREE_REG_SET (bb->cond_local_set);
        }
@@ -1290,6 +1371,115 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
 
   free (queue);
 }
+
+\f
+/* This structure is used to pass parameters to an from the
+   the function find_regno_partial(). It is used to pass in the
+   register number we are looking, as well as to return any rtx
+   we find.  */
+
+typedef struct {
+  unsigned regno_to_find;
+  rtx retval;
+} find_regno_partial_param;
+
+
+/* Find the rtx for the reg numbers specified in 'data' if it is
+   part of an expression which only uses part of the register.  Return
+   it in the structure passed in.  */
+static int
+find_regno_partial (ptr, data)
+     rtx *ptr;
+     void *data;
+{
+  find_regno_partial_param *param = (find_regno_partial_param *)data;
+  unsigned reg = param->regno_to_find;
+  param->retval = NULL_RTX;
+
+  if (*ptr == NULL_RTX)
+    return 0;
+
+  switch (GET_CODE (*ptr))
+    {
+    case ZERO_EXTRACT:
+    case SIGN_EXTRACT:
+    case STRICT_LOW_PART:
+      if (GET_CODE (XEXP (*ptr, 0)) == REG && REGNO (XEXP (*ptr, 0)) == reg)
+       {
+         param->retval = XEXP (*ptr, 0);
+         return 1;
+       }
+      break;
+
+    case SUBREG:
+      if (GET_CODE (SUBREG_REG (*ptr)) == REG
+         && REGNO (SUBREG_REG (*ptr)) == reg)
+       {
+         param->retval = SUBREG_REG (*ptr);
+         return 1;
+       }
+      break;
+
+    default:
+      break;
+    }
+
+  return 0;
+}
+
+/* Process all immediate successors of the entry block looking for pseudo
+   registers which are live on entry. Find all of those whose first
+   instance is a partial register reference of some kind, and initialize
+   them to 0 after the entry block.  This will prevent bit sets within
+   registers whose value is unknown, and may contain some kind of sticky
+   bits we don't want.  */
+
+int
+initialize_uninitialized_subregs ()
+{
+  rtx insn;
+  edge e;
+  int reg, did_something = 0;
+  find_regno_partial_param param;
+
+  for (e = ENTRY_BLOCK_PTR->succ; e; e = e->succ_next)
+    {
+      basic_block bb = e->dest;
+      regset map = bb->global_live_at_start;
+      EXECUTE_IF_SET_IN_REG_SET (map,
+                                FIRST_PSEUDO_REGISTER, reg,
+       {
+         int uid = REGNO_FIRST_UID (reg);
+         rtx i;
+
+         /* Find an insn which mentions the register we are looking for.
+            Its preferable to have an instance of the register's rtl since
+            there may be various flags set which we need to duplicate.
+            If we can't find it, its probably an automatic whose initial
+            value doesn't matter, or hopefully something we don't care about.  */
+         for (i = get_insns (); i && INSN_UID (i) != uid; i = NEXT_INSN (i))
+           ;
+         if (i != NULL_RTX)
+           {
+             /* Found the insn, now get the REG rtx, if we can.  */
+             param.regno_to_find = reg;
+             for_each_rtx (&i, find_regno_partial, &param);
+             if (param.retval != NULL_RTX)
+               {
+                 insn = gen_move_insn (param.retval,
+                                       CONST0_RTX (GET_MODE (param.retval)));
+                 insert_insn_on_edge (insn, e);
+                 did_something = 1;
+               }
+           }
+       });
+    }
+
+  if (did_something)
+    commit_edge_insertions ();
+  return did_something;
+}
+
 \f
 /* Subroutines of life analysis.  */
 
@@ -1299,21 +1489,14 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
 void
 allocate_bb_life_data ()
 {
-  int i;
+  basic_block bb;
 
-  for (i = 0; i < n_basic_blocks; i++)
+  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
     {
-      basic_block bb = BASIC_BLOCK (i);
-
       bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
       bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
     }
 
-  ENTRY_BLOCK_PTR->global_live_at_end
-    = OBSTACK_ALLOC_REG_SET (&flow_obstack);
-  EXIT_BLOCK_PTR->global_live_at_start
-    = OBSTACK_ALLOC_REG_SET (&flow_obstack);
-
   regs_live_at_setjmp = OBSTACK_ALLOC_REG_SET (&flow_obstack);
 }
 
@@ -1344,12 +1527,10 @@ allocate_reg_life_data ()
 /* Delete dead instructions for propagate_block.  */
 
 static void
-propagate_block_delete_insn (bb, insn)
-     basic_block bb;
+propagate_block_delete_insn (insn)
      rtx insn;
 {
   rtx inote = find_reg_note (insn, REG_LABEL, NULL_RTX);
-  bool purge = false;
 
   /* If the insn referred to a label, and that label was attached to
      an ADDR_VEC, it's safe to delete the ADDR_VEC.  In fact, it's
@@ -1359,11 +1540,7 @@ propagate_block_delete_insn (bb, insn)
      INSN may reference a deleted label, particularly when a jump
      table has been optimized into a direct jump.  There's no
      real good way to fix up the reference to the deleted label
-     when the label is deleted, so we just allow it here.
-
-     After dead code elimination is complete, we do search for
-     any REG_LABEL notes which reference deleted labels as a
-     sanity check.  */
+     when the label is deleted, so we just allow it here.  */
 
   if (inote && GET_CODE (inote) == CODE_LABEL)
     {
@@ -1387,15 +1564,13 @@ propagate_block_delete_insn (bb, insn)
          for (i = 0; i < len; i++)
            LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0))--;
 
-         delete_insn (next);
+         delete_insn_and_edges (next);
+         ndead++;
        }
     }
 
-  if (bb->end == insn)
-    purge = true;
-  delete_insn (insn);
-  if (purge)
-    purge_dead_edges (bb);
+  delete_insn_and_edges (insn);
+  ndead++;
 }
 
 /* Delete dead libcalls for propagate_block.  Return the insn
@@ -1408,7 +1583,8 @@ propagate_block_delete_libcall ( insn, note)
   rtx first = XEXP (note, 0);
   rtx before = PREV_INSN (first);
 
-  delete_insn_chain (first, insn);
+  delete_insn_chain_and_edges (first, insn);
+  ndead++;
   return before;
 }
 
@@ -1455,7 +1631,7 @@ propagate_one_insn (pbi, insn)
              || (HAVE_sibcall_epilogue
                  && sibcall_epilogue_contains (insn)))
          && find_reg_note (insn, REG_MAYBE_DEAD, NULL_RTX) == 0)
-       abort ();
+       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.  */
@@ -1469,7 +1645,42 @@ propagate_one_insn (pbi, insn)
       if (libcall_is_dead)
        prev = propagate_block_delete_libcall ( insn, note);
       else
-       propagate_block_delete_insn (pbi->bb, insn);
+       {
+
+       /* If INSN contains a RETVAL note and is dead, but the libcall
+          as a whole is not dead, then we want to remove INSN, but
+          not the whole libcall sequence.
+
+          However, we need to also remove the dangling REG_LIBCALL     
+          note so that we do not have mis-matched LIBCALL/RETVAL
+          notes.  In theory we could find a new location for the
+          REG_RETVAL note, but it hardly seems worth the effort. 
+
+          NOTE at this point will be the RETVAL note if it exists.  */
+         if (note)
+           {
+             rtx libcall_note;
+        
+             libcall_note
+               = find_reg_note (XEXP (note, 0), REG_LIBCALL, NULL_RTX);
+             remove_note (XEXP (note, 0), libcall_note);
+           }
+
+         /* Similarly if INSN contains a LIBCALL note, remove the
+            dnagling REG_RETVAL note.  */
+         note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
+         if (note)
+           {
+             rtx retval_note;
+
+             retval_note
+               = find_reg_note (XEXP (note, 0), REG_RETVAL, NULL_RTX);
+             remove_note (XEXP (note, 0), retval_note);
+           }
+
+         /* Now delete INSN.  */
+         propagate_block_delete_insn (insn);
+       }
 
       return prev;
     }
@@ -1518,10 +1729,12 @@ propagate_one_insn (pbi, insn)
     /* We have an insn to pop a constant amount off the stack.
        (Such insns use PLUS regardless of the direction of the stack,
        and any insn to adjust the stack by a constant is always a pop.)
-       These insns, if not dead stores, have no effect on life.  */
-    ;
+       These insns, if not dead stores, have no effect on life, though
+       they do have an effect on the memory stores we are tracking.  */
+    invalidate_mems_from_set (pbi, stack_pointer_rtx);
   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.  */
@@ -1543,12 +1756,16 @@ propagate_one_insn (pbi, insn)
          if (GET_CODE (PATTERN (insn)) == COND_EXEC)
            cond = COND_EXEC_TEST (PATTERN (insn));
 
-         /* Non-constant calls clobber memory.  */
+         /* Non-constant calls clobber memory, constant calls do not
+            clobber memory, though they may clobber outgoing arguments
+            on the stack.  */
          if (! CONST_OR_PURE_CALL_P (insn))
            {
              free_EXPR_LIST_list (&pbi->mem_set_list);
              pbi->mem_set_list_len = 0;
            }
+         else
+           invalidate_mems_from_set (pbi, stack_pointer_rtx);
 
          /* There may be extra registers to be clobbered.  */
          for (note = CALL_INSN_FUNCTION_USAGE (insn);
@@ -1563,8 +1780,7 @@ propagate_one_insn (pbi, insn)
            if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
              {
                /* We do not want REG_UNUSED notes for these registers.  */
-               mark_set_1 (pbi, CLOBBER, gen_rtx_REG (reg_raw_mode[i], i),
-                           cond, insn,
+               mark_set_1 (pbi, CLOBBER, regno_reg_rtx[i], cond, insn,
                            pbi->flags & ~(PROP_DEATH_NOTES | PROP_REG_INFO));
              }
        }
@@ -1577,6 +1793,10 @@ propagate_one_insn (pbi, 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.  */
@@ -1608,8 +1828,7 @@ propagate_one_insn (pbi, insn)
             so they are made live.  */
          for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
            if (global_regs[i])
-             mark_used_reg (pbi, gen_rtx_REG (reg_raw_mode[i], i),
-                            cond, insn);
+             mark_used_reg (pbi, regno_reg_rtx[i], cond, insn);
        }
     }
 
@@ -1753,7 +1972,7 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
       && ! (TREE_CODE (TREE_TYPE (current_function_decl)) == FUNCTION_TYPE
            && (TYPE_RETURNS_STACK_DEPRESSED
                (TREE_TYPE (current_function_decl))))
-      && (flags & PROP_SCAN_DEAD_CODE)
+      && (flags & PROP_SCAN_DEAD_STORES)
       && (bb->succ == NULL
          || (bb->succ->succ_next == NULL
              && bb->succ->dest == EXIT_BLOCK_PTR
@@ -1899,7 +2118,7 @@ insn_dead_p (pbi, x, call_ok, notes)
       if (REG_NOTE_KIND (notes) == REG_INC)
        {
          int regno = REGNO (XEXP (notes, 0));
-         
+
          /* Don't delete insns to set global regs.  */
          if ((regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
              || REGNO_REG_SET_P (pbi->reg_live, regno))
@@ -2134,7 +2353,7 @@ libcall_dead_p (pbi, note, insn)
 
 int
 regno_uninitialized (regno)
-     int regno;
+     unsigned int regno;
 {
   if (n_basic_blocks == 0
       || (regno < FIRST_PSEUDO_REGISTER
@@ -2143,7 +2362,7 @@ regno_uninitialized (regno)
              || FUNCTION_ARG_REGNO_P (regno))))
     return 0;
 
-  return REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start, regno);
+  return REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, regno);
 }
 
 /* 1 if register REGNO was alive at a place where `setjmp' was called
@@ -2158,7 +2377,7 @@ regno_clobbered_at_setjmp (regno)
     return 0;
 
   return ((REG_N_SETS (regno) > 1
-          || REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start, regno))
+          || REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, regno))
          && REGNO_REG_SET_P (regs_live_at_setjmp, regno));
 }
 \f
@@ -2213,15 +2432,21 @@ add_to_mem_set_list (pbi, mem)
    Find any entries on the mem_set_list that need to be invalidated due
    to an address change.  */
 
-static void
-invalidate_mems_from_autoinc (pbi, insn)
-     struct propagate_block_info *pbi;
-     rtx insn;
+static int
+invalidate_mems_from_autoinc (px, data)
+     rtx *px;
+     void *data;
 {
-  rtx note = REG_NOTES (insn);
-  for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
-    if (REG_NOTE_KIND (note) == REG_INC)
-      invalidate_mems_from_set (pbi, XEXP (note, 0));
+  rtx x = *px;
+  struct propagate_block_info *pbi = data;
+
+  if (GET_RTX_CLASS (GET_CODE (x)) == 'a')
+    {
+      invalidate_mems_from_set (pbi, XEXP (x, 0));
+      return -1;
+    }
+
+  return 0;
 }
 
 /* EXP is a REG.  Remove any dependent entries from pbi->mem_set_list.  */
@@ -2434,7 +2659,7 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
 
   /* If this set is a MEM, then it kills any aliased writes.
      If this set is a REG, then it kills any MEMs which use the reg.  */
-  if (optimize && (flags & PROP_SCAN_DEAD_CODE))
+  if (optimize && (flags & PROP_SCAN_DEAD_STORES))
     {
       if (GET_CODE (reg) == REG)
        invalidate_mems_from_set (pbi, reg);
@@ -2443,16 +2668,12 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
         address modes.  Then we may need to kill some entries on the
         memory set list.  */
       if (insn && GET_CODE (reg) == MEM)
-       invalidate_mems_from_autoinc (pbi, insn);
+       for_each_rtx (&PATTERN (insn), invalidate_mems_from_autoinc, pbi);
 
       if (GET_CODE (reg) == MEM && ! side_effects_p (reg)
          /* ??? With more effort we could track conditional memory life.  */
-         && ! cond
-         /* There are no REG_INC notes for SP, so we can't assume we'll see
-            everything that invalidates it.  To be safe, don't eliminate any
-            stores though SP; none of them should be redundant anyway.  */
-         && ! reg_mentioned_p (stack_pointer_rtx, reg))
-        add_to_mem_set_list (pbi, canon_rtx (reg));
+         && ! cond)
+       add_to_mem_set_list (pbi, canon_rtx (reg));
     }
 
   if (GET_CODE (reg) == REG
@@ -2607,7 +2828,7 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
                    if (! REGNO_REG_SET_P (pbi->reg_live, i))
                      REG_NOTES (insn)
                        = alloc_EXPR_LIST (REG_UNUSED,
-                                          gen_rtx_REG (reg_raw_mode[i], i),
+                                          regno_reg_rtx[i],
                                           REG_NOTES (insn));
                }
            }
@@ -2689,7 +2910,7 @@ mark_regno_cond_dead (pbi, regno, cond)
 
          SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (XEXP (cond, 0)));
 
-         /* Not unconditionaly dead.  */
+         /* Not unconditionally dead.  */
          return 0;
        }
       else
@@ -2721,7 +2942,7 @@ mark_regno_cond_dead (pbi, regno, cond)
 
              SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (XEXP (cond, 0)));
 
-             /* Not unconditionaly dead.  */
+             /* Not unconditionally dead.  */
              return 0;
            }
        }
@@ -3137,7 +3358,7 @@ attempt_auto_inc (pbi, inc, insn, mem, incr, incr_reg)
 
       /* We now know we'll be doing this change, so emit the
         new insn(s) and do the updates.  */
-      emit_insns_before (insns, insn);
+      emit_insn_before (insns, insn);
 
       if (pbi->bb->head == insn)
        pbi->bb->head = insns;
@@ -3415,7 +3636,7 @@ mark_used_reg (pbi, reg, cond, insn)
                && ! dead_or_set_regno_p (insn, i))
              REG_NOTES (insn)
                = alloc_EXPR_LIST (REG_DEAD,
-                                  gen_rtx_REG (reg_raw_mode[i], i),
+                                  regno_reg_rtx[i],
                                   REG_NOTES (insn));
        }
     }
@@ -3423,6 +3644,10 @@ mark_used_reg (pbi, reg, cond, insn)
   /* Mark the register as being live.  */
   for (i = regno_first; i <= regno_last; ++i)
     {
+#ifdef HAVE_conditional_execution
+      int this_was_live = REGNO_REG_SET_P (pbi->reg_live, i);
+#endif
+
       SET_REGNO_REG_SET (pbi->reg_live, i);
 
 #ifdef HAVE_conditional_execution
@@ -3434,7 +3659,7 @@ mark_used_reg (pbi, reg, cond, insn)
          struct reg_cond_life_info *rcli;
          rtx ncond;
 
-         if (some_was_live)
+         if (this_was_live)
            {
              node = splay_tree_lookup (pbi->reg_cond_dead, i);
              if (node == NULL)
@@ -3476,7 +3701,7 @@ mark_used_reg (pbi, reg, cond, insn)
              SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (XEXP (cond, 0)));
            }
        }
-      else if (some_was_live)
+      else if (this_was_live)
        {
          /* The register may have been conditionally live previously, but
             is now unconditionally live.  Remove it from the conditionally
@@ -3505,6 +3730,8 @@ mark_used_regs (pbi, x, cond, insn)
   int flags = pbi->flags;
 
  retry:
+  if (!x)
+    return;
   code = GET_CODE (x);
   switch (code)
     {
@@ -3513,6 +3740,7 @@ mark_used_regs (pbi, x, cond, insn)
     case CONST_INT:
     case CONST:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case PC:
     case ADDR_VEC:
     case ADDR_DIFF_VEC:
@@ -3534,7 +3762,7 @@ mark_used_regs (pbi, x, cond, insn)
     case MEM:
       /* Don't bother watching stores to mems if this is not the
         final pass.  We'll not be deleting dead stores this round.  */
-      if (optimize && (flags & PROP_SCAN_DEAD_CODE))
+      if (optimize && (flags & PROP_SCAN_DEAD_STORES))
        {
          /* Invalidate the data for the last MEM stored, but only if MEM is
             something that can be stored into.  */
@@ -3571,12 +3799,12 @@ mark_used_regs (pbi, x, cond, insn)
             address modes.  Then we may need to kill some entries on the
             memory set list.  */
          if (insn)
-           invalidate_mems_from_autoinc (pbi, insn);
+           for_each_rtx (&PATTERN (insn), invalidate_mems_from_autoinc, pbi);
        }
 
 #ifdef AUTO_INC_DEC
       if (flags & PROP_AUTOINC)
-        find_auto_inc (pbi, x, insn);
+       find_auto_inc (pbi, x, insn);
 #endif
       break;
 
@@ -3793,7 +4021,7 @@ try_pre_increment_1 (pbi, insn)
     {
       /* We have found a suitable auto-increment and already changed
         insn Y to do it.  So flush this increment instruction.  */
-      propagate_block_delete_insn (pbi->bb, insn);
+      propagate_block_delete_insn (insn);
 
       /* Count a reference to this reg for the increment insn we are
         deleting.  When a reg is incremented, spilling it is worse,
@@ -3863,13 +4091,13 @@ try_pre_increment (insn, reg, amount)
   use = 0;
   if (pre_ok)
     use = find_use_as_address (PATTERN (insn), reg, 0);
-  if (post_ok && (use == 0 || use == (rtx) 1))
+  if (post_ok && (use == 0 || use == (rtx) (size_t) 1))
     {
       use = find_use_as_address (PATTERN (insn), reg, -amount);
       do_post = 1;
     }
 
-  if (use == 0 || use == (rtx) 1)
+  if (use == 0 || use == (rtx) (size_t) 1)
     return 0;
 
   if (GET_MODE_SIZE (GET_MODE (use)) != (amount > 0 ? amount : - amount))
@@ -3897,7 +4125,7 @@ try_pre_increment (insn, reg, amount)
 
    If such an address does not appear, return 0.
    If REG appears more than once, or is used other than in such an address,
-   return (rtx)1.  */
+   return (rtx) 1.  */
 
 rtx
 find_use_as_address (x, reg, plusconst)
@@ -3925,11 +4153,11 @@ find_use_as_address (x, reg, plusconst)
       /* If REG occurs inside a MEM used in a bit-field reference,
         that is unacceptable.  */
       if (find_use_as_address (XEXP (x, 0), reg, 0) != 0)
-       return (rtx) (HOST_WIDE_INT) 1;
+       return (rtx) (size_t) 1;
     }
 
   if (x == reg)
-    return (rtx) (HOST_WIDE_INT) 1;
+    return (rtx) (size_t) 1;
 
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
@@ -3939,7 +4167,7 @@ find_use_as_address (x, reg, plusconst)
          if (value == 0)
            value = tem;
          else if (tem != 0)
-           return (rtx) (HOST_WIDE_INT) 1;
+           return (rtx) (size_t) 1;
        }
       else if (fmt[i] == 'E')
        {
@@ -3950,7 +4178,7 @@ find_use_as_address (x, reg, plusconst)
              if (value == 0)
                value = tem;
              else if (tem != 0)
-               return (rtx) (HOST_WIDE_INT) 1;
+               return (rtx) (size_t) 1;
            }
        }
     }
@@ -3994,23 +4222,6 @@ debug_regset (r)
   putc ('\n', stderr);
 }
 
-/* Dump the rtl into the current debugging dump file, then abort.  */
-
-static void
-print_rtl_and_abort_fcn (file, line, function)
-     const char *file;
-     int line;
-     const char *function;
-{
-  if (rtl_dump_file)
-    {
-      print_rtl_with_bb (rtl_dump_file, get_insns ());
-      fclose (rtl_dump_file);
-    }
-
-  fancy_abort (file, line, function);
-}
-
 /* Recompute register set/reference counts immediately prior to register
    allocation.
 
@@ -4048,18 +4259,16 @@ count_or_remove_death_notes (blocks, kill)
      sbitmap blocks;
      int kill;
 {
-  int i, count = 0;
+  int count = 0;
+  basic_block bb;
 
-  for (i = n_basic_blocks - 1; i >= 0; --i)
+  FOR_EACH_BB_REVERSE (bb)
     {
-      basic_block bb;
       rtx insn;
 
-      if (blocks && ! TEST_BIT (blocks, i))
+      if (blocks && ! TEST_BIT (blocks, bb->index))
        continue;
 
-      bb = BASIC_BLOCK (i);
-
       for (insn = bb->head;; insn = NEXT_INSN (insn))
        {
          if (INSN_P (insn))