OSDN Git Service

* flow.c (update_life_info): Amend comment about when a register
[pf3gnuchains/gcc-fork.git] / gcc / flow.c
index b5a6e37..0dffb46 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, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -120,6 +120,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 \f
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "tree.h"
 #include "rtl.h"
 #include "tm_p.h"
@@ -134,15 +136,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "toplev.h"
 #include "recog.h"
 #include "expr.h"
-#include "ssa.h"
 #include "timevar.h"
 
 #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 +165,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
@@ -204,7 +205,7 @@ rtx regs_may_share;
 
 /* Callback that determines if it's ok for a function to have no
    noreturn attribute.  */
-int (*lang_missing_noreturn_ok_p) PARAMS ((tree));
+int (*lang_missing_noreturn_ok_p) (tree);
 
 /* Set of registers that may be eliminable.  These are handled specially
    in updating regs_ever_live.  */
@@ -269,85 +270,66 @@ struct propagate_block_info
   /* The length of mem_set_list.  */
   int mem_set_list_len;
 
-  /* Non-zero if the value of CC0 is live.  */
+  /* Nonzero if the value of CC0 is live.  */
   int cc0_live;
 
-  /* Flags controling the set of information propagate_block collects.  */
+  /* Flags controlling the set of information propagate_block collects.  */
   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_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));
-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 rtx propagate_block_delete_libcall PARAMS ((basic_block, rtx, rtx));
-static int insn_dead_p                 PARAMS ((struct propagate_block_info *,
-                                                rtx, int, rtx));
-static int libcall_dead_p              PARAMS ((struct propagate_block_info *,
-                                                rtx, rtx));
-static void mark_set_regs              PARAMS ((struct propagate_block_info *,
-                                                rtx, rtx));
-static void mark_set_1                 PARAMS ((struct propagate_block_info *,
-                                                enum rtx_code, rtx, rtx,
-                                                rtx, int));
+static int verify_wide_reg_1 (rtx *, void *);
+static void verify_wide_reg (int, basic_block);
+static void verify_local_live_at_start (regset, basic_block);
+static void notice_stack_pointer_modification_1 (rtx, rtx, void *);
+static void notice_stack_pointer_modification (rtx);
+static void mark_reg (rtx, void *);
+static void mark_regs_live_at_end (regset);
+static void calculate_global_regs_live (sbitmap, sbitmap, int);
+static void propagate_block_delete_insn (rtx);
+static rtx propagate_block_delete_libcall (rtx, rtx);
+static int insn_dead_p (struct propagate_block_info *, rtx, int, rtx);
+static int libcall_dead_p (struct propagate_block_info *, rtx, rtx);
+static void mark_set_regs (struct propagate_block_info *, rtx, rtx);
+static void mark_set_1 (struct propagate_block_info *, enum rtx_code, rtx,
+                       rtx, rtx, int);
+static int find_regno_partial (rtx *, void *);
+
 #ifdef HAVE_conditional_execution
-static int mark_regno_cond_dead                PARAMS ((struct propagate_block_info *,
-                                                int, rtx));
-static void free_reg_cond_life_info    PARAMS ((splay_tree_value));
-static int flush_reg_cond_reg_1                PARAMS ((splay_tree_node, void *));
-static void flush_reg_cond_reg         PARAMS ((struct propagate_block_info *,
-                                                int));
-static rtx elim_reg_cond               PARAMS ((rtx, unsigned int));
-static rtx ior_reg_cond                        PARAMS ((rtx, rtx, int));
-static rtx not_reg_cond                        PARAMS ((rtx));
-static rtx and_reg_cond                        PARAMS ((rtx, rtx, int));
+static int mark_regno_cond_dead (struct propagate_block_info *, int, rtx);
+static void free_reg_cond_life_info (splay_tree_value);
+static int flush_reg_cond_reg_1 (splay_tree_node, void *);
+static void flush_reg_cond_reg (struct propagate_block_info *, int);
+static rtx elim_reg_cond (rtx, unsigned int);
+static rtx ior_reg_cond (rtx, rtx, int);
+static rtx not_reg_cond (rtx);
+static rtx and_reg_cond (rtx, rtx, int);
 #endif
 #ifdef AUTO_INC_DEC
-static void attempt_auto_inc           PARAMS ((struct propagate_block_info *,
-                                                rtx, rtx, rtx, rtx, rtx));
-static void find_auto_inc              PARAMS ((struct propagate_block_info *,
-                                                rtx, rtx));
-static int try_pre_increment_1         PARAMS ((struct propagate_block_info *,
-                                                rtx));
-static int try_pre_increment           PARAMS ((rtx, rtx, HOST_WIDE_INT));
+static void attempt_auto_inc (struct propagate_block_info *, rtx, rtx, rtx,
+                             rtx, rtx);
+static void find_auto_inc (struct propagate_block_info *, rtx, rtx);
+static int try_pre_increment_1 (struct propagate_block_info *, rtx);
+static int try_pre_increment (rtx, rtx, HOST_WIDE_INT);
 #endif
-static void mark_used_reg              PARAMS ((struct propagate_block_info *,
-                                                rtx, rtx, rtx));
-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 void invalidate_mems_from_set   PARAMS ((struct propagate_block_info *,
-                                                rtx));
-static void delete_dead_jumptables     PARAMS ((void));
+static void mark_used_reg (struct propagate_block_info *, rtx, rtx, rtx);
+static void mark_used_regs (struct propagate_block_info *, rtx, rtx, rtx);
+void debug_flow_info (void);
+static void add_to_mem_set_list (struct propagate_block_info *, rtx);
+static int invalidate_mems_from_autoinc (rtx *, void *);
+static void invalidate_mems_from_set (struct propagate_block_info *, rtx);
+static void clear_log_links (sbitmap);
 \f
 
 void
-check_function_return_warnings ()
+check_function_return_warnings (void)
 {
   if (warn_missing_noreturn
       && !TREE_THIS_VOLATILE (cfun->decl)
@@ -375,12 +357,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.  */
-         compute_bb_for_insn (max_uid);
+         rtx insn;
 
-         if (BLOCK_FOR_INSN (cfun->x_clobber_return_insn) != NULL)
-           warning ("control reaches end of non-void function");
+         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;
+             }
        }
     }
 }
@@ -389,8 +373,7 @@ check_function_return_warnings ()
    note associated with the BLOCK.  */
 
 rtx
-first_insn_after_basic_block_note (block)
-     basic_block block;
+first_insn_after_basic_block_note (basic_block block)
 {
   rtx insn;
 
@@ -412,14 +395,11 @@ first_insn_after_basic_block_note (block)
    to be used in accumulating flow info.  */
 
 void
-life_analysis (f, file, flags)
-     rtx f;
-     FILE *file;
-     int flags;
+life_analysis (rtx f, FILE *file, int flags)
 {
 #ifdef ELIMINABLE_REGS
-  register int i;
-  static struct {int from, to; } eliminables[] = ELIMINABLE_REGS;
+  int i;
+  static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
 #endif
 
   /* Record which registers will be eliminated.  We use this in
@@ -434,6 +414,12 @@ life_analysis (f, file, flags)
   SET_HARD_REG_BIT (elim_reg_set, FRAME_POINTER_REGNUM);
 #endif
 
+
+#ifdef CANNOT_CHANGE_MODE_CLASS
+  if (flags & PROP_REG_INFO)
+    bitmap_initialize (&subregs_of_mode, 1);
+#endif
+
   if (! optimize)
     flags &= ~(PROP_LOG_LINKS | PROP_AUTOINC | PROP_ALLOW_CFG_CHANGES);
 
@@ -451,7 +437,7 @@ 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
@@ -481,7 +467,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,31 +475,16 @@ 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)
-     rtx *px;
-     void *pregno;
+verify_wide_reg_1 (rtx *px, void *pregno)
 {
   rtx x = *px;
   unsigned int regno = *(int *) pregno;
@@ -521,43 +492,48 @@ 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)
-     int regno;
-     rtx head, end;
+verify_wide_reg (int regno, 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
    changes in live_at_start during a local update.  */
 
 static void
-verify_local_live_at_start (new_live_at_start, bb)
-     regset new_live_at_start;
-     basic_block bb;
+verify_local_live_at_start (regset new_live_at_start, basic_block bb)
 {
   if (reload_completed)
     {
@@ -568,12 +544,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 +562,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);
        });
     }
 }
@@ -604,7 +583,7 @@ verify_local_live_at_start (new_live_at_start, bb)
 /* Updates life information starting with the basic blocks set in BLOCKS.
    If BLOCKS is null, consider it to be the universal set.
 
-   If EXTENT is UPDATE_LIFE_LOCAL, such as after splitting or peepholeing,
+   If EXTENT is UPDATE_LIFE_LOCAL, such as after splitting or peepholing,
    we are only expecting local modifications to basic blocks.  If we find
    extra registers live at the beginning of a block, then we either killed
    useful data, or we have a broken split that wants data not provided.
@@ -615,20 +594,26 @@ verify_local_live_at_start (new_live_at_start, bb)
    generates subregs of a multi-word pseudo, current life analysis will
    lose the kill.  So we _can_ have a pseudo go live.  How irritating.
 
+   It is also not true when a peephole decides that it doesn't need one
+   or more of the inputs.
+
    Including PROP_REG_INFO does not properly refresh regs_ever_live
    unless the caller resets it to zero.  */
 
-void
-update_life_info (blocks, extent, prop_flags)
-     sbitmap blocks;
-     enum update_life_extent extent;
-     int prop_flags;
+int
+update_life_info (sbitmap blocks, enum update_life_extent extent, int 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);
 
   /* Changes to the CFG are only allowed when
      doing a global update for the entire CFG.  */
@@ -645,6 +630,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))
@@ -653,18 +639,41 @@ 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);
+
+         /* Zap the life information from the last round.  If we don't
+            do this, we can wind up with registers that no longer appear
+            in the code being marked live at entry, which twiggs bogus
+            warnings from regno_uninitialized.  */
+         FOR_EACH_BB (bb)
+           {
+             CLEAR_REG_SET (bb->global_live_at_start);
+             CLEAR_REG_SET (bb->global_live_at_end);
+           }
        }
 
       /* If asked, remove notes from the blocks we'll update.  */
@@ -672,14 +681,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);
@@ -687,12 +700,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);
@@ -729,22 +741,58 @@ 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;
 }
 
-/* Free the variables allocated by find_basic_blocks.
-
-   KEEP_HEAD_END_P is non-zero if basic_block_info is not to be freed.  */
+/* Update life information in all blocks where BB_DIRTY is set.  */
 
-void
-free_basic_block_vars (keep_head_end_p)
-     int keep_head_end_p;
+int
+update_life_info_in_dirty_blocks (enum update_life_extent extent, int prop_flags)
 {
-  if (basic_block_for_insn)
+  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)
     {
-      VARRAY_FREE (basic_block_for_insn);
-      basic_block_for_insn = NULL;
+      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.
+
+   KEEP_HEAD_END_P is nonzero if basic_block_info is not to be freed.  */
+
+void
+free_basic_block_vars (int keep_head_end_p)
+{
   if (! keep_head_end_p)
     {
       if (basic_block_info)
@@ -753,6 +801,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;
@@ -763,55 +812,68 @@ free_basic_block_vars (keep_head_end_p)
 
 /* Delete any insns that copy a register to itself.  */
 
-void
-delete_noop_moves (f)
-     rtx f ATTRIBUTE_UNUSED;
+int
+delete_noop_moves (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);
          if (INSN_P (insn) && noop_move_p (insn))
            {
-             /* Do not call flow_delete_insn here to not confuse backward
-                pointers of LIBCALL block.  */
-             PUT_CODE (insn, NOTE);
-             NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-             NOTE_SOURCE_FILE (insn) = 0;
-             if (insn == bb->end)
-               purge_dead_edges (bb);
+             rtx note;
+
+             /* If we're about to remove the first insn of a libcall
+                then move the libcall note to the next real insn and
+                update the retval note.  */
+             if ((note = find_reg_note (insn, REG_LIBCALL, NULL_RTX))
+                      && XEXP (note, 0) != insn)
+               {
+                 rtx new_libcall_insn = next_real_insn (insn);
+                 rtx retval_note = find_reg_note (XEXP (note, 0),
+                                                  REG_RETVAL, NULL_RTX);
+                 REG_NOTES (new_libcall_insn)
+                   = gen_rtx_INSN_LIST (REG_LIBCALL, XEXP (note, 0),
+                                        REG_NOTES (new_libcall_insn));
+                 XEXP (retval_note, 0) = new_libcall_insn;
+               }
+
+             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 preceeding
+   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
-delete_dead_jumptables ()
+void
+delete_dead_jumptables (void)
 {
   rtx insn, next;
   for (insn = get_insns (); insn; insn = next)
     {
       next = NEXT_INSN (insn);
       if (GET_CODE (insn) == CODE_LABEL
-         && LABEL_NUSES (insn) == 0
+         && LABEL_NUSES (insn) == LABEL_PRESERVE_P (insn)
          && GET_CODE (next) == JUMP_INSN
          && (GET_CODE (PATTERN (next)) == ADDR_VEC
              || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
        {
          if (rtl_dump_file)
            fprintf (rtl_dump_file, "Dead jumptable %i removed\n", INSN_UID (insn));
-         flow_delete_insn (NEXT_INSN (insn));
-         flow_delete_insn (insn);
+         delete_insn (NEXT_INSN (insn));
+         delete_insn (insn);
          next = NEXT_INSN (next);
        }
     }
@@ -821,10 +883,8 @@ delete_dead_jumptables ()
    Only useful before prologues have been emitted.  */
 
 static void
-notice_stack_pointer_modification_1 (x, pat, data)
-     rtx x;
-     rtx pat ATTRIBUTE_UNUSED;
-     void *data ATTRIBUTE_UNUSED;
+notice_stack_pointer_modification_1 (rtx x, rtx pat ATTRIBUTE_UNUSED,
+                                    void *data ATTRIBUTE_UNUSED)
 {
   if (x == stack_pointer_rtx
       /* The stack pointer is only modified indirectly as the result
@@ -837,8 +897,7 @@ notice_stack_pointer_modification_1 (x, pat, data)
 }
 
 static void
-notice_stack_pointer_modification (f)
-     rtx f;
+notice_stack_pointer_modification (rtx f)
 {
   rtx insn;
 
@@ -865,9 +924,7 @@ notice_stack_pointer_modification (f)
    of their component registers set as well.  */
 
 static void
-mark_reg (reg, xset)
-     rtx reg;
-     void *xset;
+mark_reg (rtx reg, void *xset)
 {
   regset set = (regset) xset;
   int regno = REGNO (reg);
@@ -888,14 +945,13 @@ mark_reg (reg, xset)
    at the end of the last basic block.  */
 
 static void
-mark_regs_live_at_end (set)
-     regset set;
+mark_regs_live_at_end (regset set)
 {
   unsigned int i;
 
   /* If exiting needs the right stack value, consider the stack pointer
      live at the end of the function.  */
-  if ((HAVE_epilogue && reload_completed)
+  if ((HAVE_epilogue && epilogue_completed)
       || ! EXIT_IGNORE_STACK
       || (! FRAME_POINTER_REQUIRED
          && ! current_function_calls_alloca
@@ -915,7 +971,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
     }
 
@@ -923,7 +979,7 @@ mark_regs_live_at_end (set)
   /* Many architectures have a GP register even without flag_pic.
      Assume the pic register is not in use, or will be handled by
      other means, if it is not fixed.  */
-  if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
+  if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
       && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
     SET_REGNO_REG_SET (set, PIC_OFFSET_TABLE_REGNUM);
 #endif
@@ -935,7 +991,7 @@ mark_regs_live_at_end (set)
     if (global_regs[i] || EPILOGUE_USES (i))
       SET_REGNO_REG_SET (set, i);
 
-  if (HAVE_epilogue && reload_completed)
+  if (HAVE_epilogue && epilogue_completed)
     {
       /* Mark all call-saved registers that we actually used.  */
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -956,7 +1012,7 @@ mark_regs_live_at_end (set)
       }
 #endif
 #ifdef EH_RETURN_STACKADJ_RTX
-  if ((! HAVE_epilogue || ! reload_completed)
+  if ((! HAVE_epilogue || ! epilogue_completed)
       && current_function_calls_eh_return)
     {
       rtx tmp = EH_RETURN_STACKADJ_RTX;
@@ -965,7 +1021,7 @@ mark_regs_live_at_end (set)
     }
 #endif
 #ifdef EH_RETURN_HANDLER_RTX
-  if ((! HAVE_epilogue || ! reload_completed)
+  if ((! HAVE_epilogue || ! epilogue_completed)
       && current_function_calls_eh_return)
     {
       rtx tmp = EH_RETURN_HANDLER_RTX;
@@ -978,22 +1034,6 @@ mark_regs_live_at_end (set)
   diddle_return_value (mark_reg, set);
 }
 
-/* Callback function for for_each_successor_phi.  DATA is a regset.
-   Sets the SRC_REGNO, the regno of the phi alternative for phi node
-   INSN, in the regset.  */
-
-static int
-set_phi_alternative_reg (insn, dest_regno, src_regno, data)
-     rtx insn ATTRIBUTE_UNUSED;
-     int dest_regno ATTRIBUTE_UNUSED;
-     int src_regno;
-     void *data;
-{
-  regset live = (regset) data;
-  SET_REGNO_REG_SET (live, src_regno);
-  return 0;
-}
-
 /* Propagate global life info around the graph of basic blocks.  Begin
    considering blocks with their corresponding bit set in BLOCKS_IN.
    If BLOCKS_IN is null, consider it the universal set.
@@ -1001,29 +1041,35 @@ set_phi_alternative_reg (insn, dest_regno, src_regno, data)
    BLOCKS_OUT is set for every block that was changed.  */
 
 static void
-calculate_global_regs_live (blocks_in, blocks_out, flags)
-     sbitmap blocks_in, blocks_out;
-     int flags;
+calculate_global_regs_live (sbitmap blocks_in, sbitmap 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 behavior 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
      work with a full queue.  */
-  queue = (basic_block *) xmalloc ((n_basic_blocks + 2) * sizeof (*queue));
+  queue = xmalloc ((n_basic_blocks + 2) * sizeof (*queue));
   qtail = queue;
   qhead = qend = queue + n_basic_blocks + 2;
 
@@ -1032,27 +1078,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);
 
@@ -1087,21 +1133,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.  */
@@ -1125,19 +1190,11 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
 
          /* Any constant, or pseudo with constant equivalences, may
             require reloading from memory using the pic register.  */
-         if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
+         if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
              && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
            SET_REGNO_REG_SET (new_live_at_end, PIC_OFFSET_TABLE_REGNUM);
        }
 
-      /* Regs used in phi nodes are not included in
-        global_live_at_start, since they are live only along a
-        particular edge.  Set those regs that are live because of a
-        phi node alternative corresponding to this particular block.  */
-      if (in_ssa_form)
-       for_each_successor_phi (bb, &set_phi_alternative_reg,
-                               new_live_at_end);
-
       if (bb == ENTRY_BLOCK_PTR)
        {
          COPY_REG_SET (bb->global_live_at_end, new_live_at_end);
@@ -1249,7 +1306,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)
     {
@@ -1262,9 +1319,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);
        }
@@ -1272,6 +1328,116 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
 
   free (queue);
 }
+
+\f
+/* This structure is used to pass parameters to and 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 (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 (void)
+{
+  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)
+               {
+                 start_sequence ();
+                 emit_move_insn (param.retval,
+                                 CONST0_RTX (GET_MODE (param.retval)));
+                 insn = get_insns ();
+                 end_sequence ();
+                 insert_insn_on_edge (insn, e);
+                 did_something = 1;
+               }
+           }
+       });
+    }
+
+  if (did_something)
+    commit_edge_insertions ();
+  return did_something;
+}
+
 \f
 /* Subroutines of life analysis.  */
 
@@ -1279,28 +1445,21 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
    of life analysis.  Not static since used also for stupid life analysis.  */
 
 void
-allocate_bb_life_data ()
+allocate_bb_life_data (void)
 {
-  register 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);
 }
 
 void
-allocate_reg_life_data ()
+allocate_reg_life_data (void)
 {
   int i;
 
@@ -1319,6 +1478,7 @@ allocate_reg_life_data ()
       REG_N_DEATHS (i) = 0;
       REG_N_CALLS_CROSSED (i) = 0;
       REG_LIVE_LENGTH (i) = 0;
+      REG_FREQ (i) = 0;
       REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN;
     }
 }
@@ -1326,9 +1486,7 @@ allocate_reg_life_data ()
 /* Delete dead instructions for propagate_block.  */
 
 static void
-propagate_block_delete_insn (bb, insn)
-     basic_block bb;
-     rtx insn;
+propagate_block_delete_insn (rtx insn)
 {
   rtx inote = find_reg_note (insn, REG_LABEL, NULL_RTX);
 
@@ -1340,11 +1498,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)
     {
@@ -1368,42 +1522,33 @@ propagate_block_delete_insn (bb, insn)
          for (i = 0; i < len; i++)
            LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0))--;
 
-         flow_delete_insn (next);
+         delete_insn_and_edges (next);
+         ndead++;
        }
     }
 
-  if (bb->end == insn)
-    {
-      bb->end = PREV_INSN (insn);
-      purge_dead_edges (bb);
-    }
-  flow_delete_insn (insn);
+  delete_insn_and_edges (insn);
+  ndead++;
 }
 
 /* Delete dead libcalls for propagate_block.  Return the insn
    before the libcall.  */
 
 static rtx
-propagate_block_delete_libcall (bb, insn, note)
-     basic_block bb;
-     rtx insn, note;
+propagate_block_delete_libcall (rtx insn, rtx note)
 {
   rtx first = XEXP (note, 0);
   rtx before = PREV_INSN (first);
 
-  if (insn == bb->end)
-    bb->end = before;
-
-  flow_delete_insn_chain (first, insn);
+  delete_insn_chain_and_edges (first, insn);
+  ndead++;
   return before;
 }
 
 /* Update the life-status of regs for one insn.  Return the previous insn.  */
 
 rtx
-propagate_one_insn (pbi, insn)
-     struct propagate_block_info *pbi;
-     rtx insn;
+propagate_one_insn (struct propagate_block_info *pbi, rtx insn)
 {
   rtx prev = PREV_INSN (insn);
   int flags = pbi->flags;
@@ -1441,7 +1586,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.  */
@@ -1453,9 +1598,44 @@ propagate_one_insn (pbi, insn)
       pbi->cc0_live = 0;
 
       if (libcall_is_dead)
-       prev = propagate_block_delete_libcall (pbi->bb, insn, note);
+       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
+            dangling 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;
     }
@@ -1464,7 +1644,7 @@ propagate_one_insn (pbi, insn)
      a following memory address.  */
 #ifdef AUTO_INC_DEC
   {
-    register rtx x = single_set (insn);
+    rtx x = single_set (insn);
 
     /* Does this instruction increment or decrement a register?  */
     if ((flags & PROP_AUTOINC)
@@ -1504,10 +1684,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.  */
@@ -1522,19 +1704,25 @@ propagate_one_insn (pbi, insn)
 
       if (GET_CODE (insn) == CALL_INSN)
        {
-         register int i;
+         regset live_at_end;
+         bool sibcall_p;
          rtx note, cond;
+         int i;
 
          cond = NULL_RTX;
          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);
@@ -1544,13 +1732,22 @@ propagate_one_insn (pbi, insn)
              mark_set_1 (pbi, CLOBBER, XEXP (XEXP (note, 0), 0),
                          cond, insn, pbi->flags);
 
-         /* Calls change all call-used and global registers.  */
+         /* Calls change all call-used and global registers; sibcalls do not
+            clobber anything that must be preserved at end-of-function,
+            except for return values.  */
+
+         sibcall_p = SIBLING_CALL_P (insn);
+         live_at_end = EXIT_BLOCK_PTR->global_live_at_start;
          for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-           if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
+           if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i)
+               && ! (sibcall_p
+                     && REGNO_REG_SET_P (live_at_end, i)
+                     && ! refers_to_regno_p (i, i+1,
+                                             current_function_return_rtx,
+                                             (rtx *) 0)))
              {
                /* 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));
              }
        }
@@ -1563,6 +1760,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.  */
@@ -1572,20 +1773,21 @@ propagate_one_insn (pbi, insn)
 
       if (! insn_is_dead && GET_CODE (insn) == CALL_INSN)
        {
-         register int i;
+         int i;
          rtx note, cond;
 
          cond = NULL_RTX;
          if (GET_CODE (PATTERN (insn)) == COND_EXEC)
            cond = COND_EXEC_TEST (PATTERN (insn));
 
-         /* Calls use their arguments.  */
+         /* Calls use their arguments, and may clobber memory which
+            address involves some register.  */
          for (note = CALL_INSN_FUNCTION_USAGE (insn);
               note;
               note = XEXP (note, 1))
-           if (GET_CODE (XEXP (note, 0)) == USE)
-             mark_used_regs (pbi, XEXP (XEXP (note, 0), 0),
-                             cond, insn);
+           /* We find USE or CLOBBER entities in a FUNCTION_USAGE list: both
+              of which mark_used_regs knows how to handle.  */
+           mark_used_regs (pbi, XEXP (XEXP (note, 0), 0), cond, insn);
 
          /* The stack ptr is used (honorarily) by a CALL insn.  */
          SET_REGNO_REG_SET (pbi->reg_live, STACK_POINTER_REGNUM);
@@ -1594,8 +1796,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);
        }
     }
 
@@ -1613,10 +1814,8 @@ propagate_one_insn (pbi, insn)
    the user can use the regsets provided here.  */
 
 struct propagate_block_info *
-init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
-     basic_block bb;
-     regset live, local_set, cond_local_set;
-     int flags;
+init_propagate_block_info (basic_block bb, regset live, regset local_set,
+                          regset cond_local_set, int flags)
 {
   struct propagate_block_info *pbi = xmalloc (sizeof (*pbi));
 
@@ -1630,7 +1829,7 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
   pbi->flags = flags;
 
   if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
-    pbi->reg_next_use = (rtx *) xcalloc (max_reg_num (), sizeof (rtx));
+    pbi->reg_next_use = xcalloc (max_reg_num (), sizeof (rtx));
   else
     pbi->reg_next_use = NULL;
 
@@ -1641,16 +1840,15 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
                                       free_reg_cond_life_info);
   pbi->reg_cond_reg = BITMAP_XMALLOC ();
 
-  /* If this block ends in a conditional branch, for each register live
-     from one side of the branch and not the other, record the register
-     as conditionally dead.  */
+  /* If this block ends in a conditional branch, for each register
+     live from one side of the branch and not the other, record the
+     register as conditionally dead.  */
   if (GET_CODE (bb->end) == JUMP_INSN
       && any_condjump_p (bb->end))
     {
       regset_head diff_head;
       regset diff = INITIALIZE_REG_SET (diff_head);
       basic_block bb_true, bb_false;
-      rtx cond_true, cond_false, set_src;
       int i;
 
       /* Identify the successor blocks.  */
@@ -1678,53 +1876,59 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
          bb_false = bb_true;
        }
 
-      /* Extract the condition from the branch.  */
-      set_src = SET_SRC (pc_set (bb->end));
-      cond_true = XEXP (set_src, 0);
-      cond_false = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond_true)),
-                                  GET_MODE (cond_true), XEXP (cond_true, 0),
-                                  XEXP (cond_true, 1));
-      if (GET_CODE (XEXP (set_src, 1)) == PC)
-       {
-         rtx t = cond_false;
-         cond_false = cond_true;
-         cond_true = t;
-       }
-
       /* Compute which register lead different lives in the successors.  */
       if (bitmap_operation (diff, bb_true->global_live_at_start,
                            bb_false->global_live_at_start, BITMAP_XOR))
        {
+         /* Extract the condition from the branch.  */
+         rtx set_src = SET_SRC (pc_set (bb->end));
+         rtx cond_true = XEXP (set_src, 0);
          rtx reg = XEXP (cond_true, 0);
 
          if (GET_CODE (reg) == SUBREG)
            reg = SUBREG_REG (reg);
 
-         if (GET_CODE (reg) != REG)
-           abort ();
+         /* We can only track conditional lifetimes if the condition is
+            in the form of a comparison of a register against zero.  
+            If the condition is more complex than that, then it is safe
+            not to record any information.  */
+         if (GET_CODE (reg) == REG
+             && XEXP (cond_true, 1) == const0_rtx)
+           {
+             rtx cond_false
+               = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond_true)),
+                                 GET_MODE (cond_true), XEXP (cond_true, 0),
+                                 XEXP (cond_true, 1));
+             if (GET_CODE (XEXP (set_src, 1)) == PC)
+               {
+                 rtx t = cond_false;
+                 cond_false = cond_true;
+                 cond_true = t;
+               }
 
-         SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (reg));
+             SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (reg));
 
-         /* For each such register, mark it conditionally dead.  */
-         EXECUTE_IF_SET_IN_REG_SET
-           (diff, 0, i,
-            {
-              struct reg_cond_life_info *rcli;
-              rtx cond;
+             /* For each such register, mark it conditionally dead.  */
+             EXECUTE_IF_SET_IN_REG_SET
+               (diff, 0, i,
+                {
+                  struct reg_cond_life_info *rcli;
+                  rtx cond;
 
-              rcli = (struct reg_cond_life_info *) xmalloc (sizeof (*rcli));
+                  rcli = xmalloc (sizeof (*rcli));
 
-              if (REGNO_REG_SET_P (bb_true->global_live_at_start, i))
-                cond = cond_false;
-              else
-                cond = cond_true;
-              rcli->condition = cond;
-              rcli->stores = const0_rtx;
-              rcli->orig_condition = cond;
+                  if (REGNO_REG_SET_P (bb_true->global_live_at_start, i))
+                    cond = cond_false;
+                  else
+                    cond = cond_true;
+                  rcli->condition = cond;
+                  rcli->stores = const0_rtx;
+                  rcli->orig_condition = cond;
 
-              splay_tree_insert (pbi->reg_cond_dead, i,
-                                 (splay_tree_value) rcli);
-            });
+                  splay_tree_insert (pbi->reg_cond_dead, i,
+                                     (splay_tree_value) rcli);
+                });
+           }
        }
 
       FREE_REG_SET (diff);
@@ -1739,7 +1943,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
@@ -1754,13 +1958,6 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
            rtx mem = SET_DEST (set);
            rtx canon_mem = canon_rtx (mem);
 
-           /* This optimization is performed by faking a store to the
-              memory at the end of the block.  This doesn't work for
-              unchanging memories because multiple stores to unchanging
-              memory is illegal and alias analysis doesn't consider it.  */
-           if (RTX_UNCHANGING_P (canon_mem))
-             continue;
-
            if (XEXP (canon_mem, 0) == frame_pointer_rtx
                || (GET_CODE (XEXP (canon_mem, 0)) == PLUS
                    && XEXP (XEXP (canon_mem, 0), 0) == frame_pointer_rtx
@@ -1775,8 +1972,7 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
 /* Release a propagate_block_info struct.  */
 
 void
-free_propagate_block_info (pbi)
-     struct propagate_block_info *pbi;
+free_propagate_block_info (struct propagate_block_info *pbi)
 {
   free_EXPR_LIST_list (&pbi->mem_set_list);
 
@@ -1809,15 +2005,11 @@ free_propagate_block_info (pbi)
    case, the resulting set will be equal to the union of the two sets that
    would otherwise be computed.
 
-   Return non-zero if an INSN is deleted (i.e. by dead code removal).  */
+   Return nonzero if an INSN is deleted (i.e. by dead code removal).  */
 
 int
-propagate_block (bb, live, local_set, cond_local_set, flags)
-     basic_block bb;
-     regset live;
-     regset local_set;
-     regset cond_local_set;
-     int flags;
+propagate_block (basic_block bb, regset live, regset local_set,
+                regset cond_local_set, int flags)
 {
   struct propagate_block_info *pbi;
   rtx insn, prev;
@@ -1827,7 +2019,7 @@ propagate_block (bb, live, local_set, cond_local_set, flags)
 
   if (flags & PROP_REG_INFO)
     {
-      register int i;
+      int i;
 
       /* Process the regs live at the end of the block.
         Mark them as not local to any one basic block.  */
@@ -1848,7 +2040,10 @@ propagate_block (bb, live, local_set, cond_local_set, flags)
        IOR_REG_SET (regs_live_at_setjmp, pbi->reg_live);
 
       prev = propagate_one_insn (pbi, insn);
-      changed |= NEXT_INSN (prev) != insn;
+      if (!prev)
+        changed |= insn != get_insns ();
+      else
+        changed |= NEXT_INSN (prev) != insn;
 
       if (insn == bb->head)
        break;
@@ -1863,36 +2058,34 @@ propagate_block (bb, live, local_set, cond_local_set, flags)
    (SET expressions whose destinations are registers dead after the insn).
    NEEDED is the regset that says which regs are alive after the insn.
 
-   Unless CALL_OK is non-zero, an insn is needed if it contains a CALL.
+   Unless CALL_OK is nonzero, an insn is needed if it contains a CALL.
 
    If X is the entire body of an insn, NOTES contains the reg notes
    pertaining to the insn.  */
 
 static int
-insn_dead_p (pbi, x, call_ok, notes)
-     struct propagate_block_info *pbi;
-     rtx x;
-     int call_ok;
-     rtx notes ATTRIBUTE_UNUSED;
+insn_dead_p (struct propagate_block_info *pbi, rtx x, int call_ok,
+            rtx notes ATTRIBUTE_UNUSED)
 {
   enum rtx_code code = GET_CODE (x);
 
+  /* Don't eliminate insns that may trap.  */
+  if (flag_non_call_exceptions && may_trap_p (x))
+    return 0;
+
 #ifdef AUTO_INC_DEC
-  /* If flow is invoked after reload, we must take existing AUTO_INC
-     expresions into account.  */
-  if (reload_completed)
+  /* As flow is invoked after combine, we must take existing AUTO_INC
+     expressions into account.  */
+  for (; notes; notes = XEXP (notes, 1))
     {
-      for (; notes; notes = XEXP (notes, 1))
+      if (REG_NOTE_KIND (notes) == REG_INC)
        {
-         if (REG_NOTE_KIND (notes) == REG_INC)
-           {
-             int regno = REGNO (XEXP (notes, 0));
+         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))
-               return 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))
+           return 0;
        }
     }
 #endif
@@ -1936,7 +2129,7 @@ insn_dead_p (pbi, x, call_ok, notes)
             rtx_equal_p does not check the alias set or flags, we also
             must have the potential for them to conflict (anti_dependence).  */
          for (temp = pbi->mem_set_list; temp != 0; temp = XEXP (temp, 1))
-           if (anti_dependence (r, XEXP (temp, 0)))
+           if (unchanging_anti_dependence (r, XEXP (temp, 0)))
              {
                rtx mem = XEXP (temp, 0);
 
@@ -2065,22 +2258,19 @@ insn_dead_p (pbi, x, call_ok, notes)
    NOTE is the REG_RETVAL note of the insn.  */
 
 static int
-libcall_dead_p (pbi, note, insn)
-     struct propagate_block_info *pbi;
-     rtx note;
-     rtx insn;
+libcall_dead_p (struct propagate_block_info *pbi, rtx note, rtx insn)
 {
   rtx x = single_set (insn);
 
   if (x)
     {
-      register rtx r = SET_SRC (x);
+      rtx r = SET_SRC (x);
 
       if (GET_CODE (r) == REG)
        {
          rtx call = XEXP (note, 0);
          rtx call_pat;
-         register int i;
+         int i;
 
          /* Find the call insn.  */
          while (call != insn && GET_CODE (call) != CALL_INSN)
@@ -2122,8 +2312,7 @@ libcall_dead_p (pbi, note, insn)
    fixed hard registers.  */
 
 int
-regno_uninitialized (regno)
-     int regno;
+regno_uninitialized (unsigned int regno)
 {
   if (n_basic_blocks == 0
       || (regno < FIRST_PSEUDO_REGISTER
@@ -2132,7 +2321,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->global_live_at_end, regno);
 }
 
 /* 1 if register REGNO was alive at a place where `setjmp' was called
@@ -2140,23 +2329,20 @@ regno_uninitialized (regno)
    Such regs may be clobbered by `longjmp'.  */
 
 int
-regno_clobbered_at_setjmp (regno)
-     int regno;
+regno_clobbered_at_setjmp (int regno)
 {
   if (n_basic_blocks == 0)
     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->global_live_at_end, regno))
          && REGNO_REG_SET_P (regs_live_at_setjmp, regno));
 }
 \f
 /* Add MEM to PBI->MEM_SET_LIST.  MEM should be canonical.  Respect the
    maximal list size; look for overlaps in mode and select the largest.  */
 static void
-add_to_mem_set_list (pbi, mem)
-     struct propagate_block_info *pbi;
-     rtx mem;
+add_to_mem_set_list (struct propagate_block_info *pbi, rtx mem)
 {
   rtx i;
 
@@ -2202,23 +2388,25 @@ 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 (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 dependant entries from pbi->mem_set_list.  */
+/* EXP is a REG.  Remove any dependent entries from pbi->mem_set_list.  */
 
 static void
-invalidate_mems_from_set (pbi, exp)
-     struct propagate_block_info *pbi;
-     rtx exp;
+invalidate_mems_from_set (struct propagate_block_info *pbi, rtx exp)
 {
   rtx temp = pbi->mem_set_list;
   rtx prev = NULL_RTX;
@@ -2251,9 +2439,7 @@ invalidate_mems_from_set (pbi, exp)
    FLAGS is the set of operations to perform.  */
 
 static void
-mark_set_regs (pbi, x, insn)
-     struct propagate_block_info *pbi;
-     rtx x, insn;
+mark_set_regs (struct propagate_block_info *pbi, rtx x, rtx insn)
 {
   rtx cond = NULL_RTX;
   rtx link;
@@ -2283,7 +2469,8 @@ mark_set_regs (pbi, x, insn)
 
     case PARALLEL:
       {
-       register int i;
+       int i;
+
        for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
          {
            rtx sub = XVECEXP (x, 0, i);
@@ -2323,11 +2510,7 @@ mark_set_regs (pbi, x, insn)
    will be the condition.  */
 
 static void
-mark_set_1 (pbi, code, reg, cond, insn, flags)
-     struct propagate_block_info *pbi;
-     enum rtx_code code;
-     rtx reg, cond, insn;
-     int flags;
+mark_set_1 (struct propagate_block_info *pbi, enum rtx_code code, rtx reg, rtx cond, rtx insn, int flags)
 {
   int regno_first = -1, regno_last = -1;
   unsigned long not_dead = 0;
@@ -2422,7 +2605,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);
@@ -2431,16 +2614,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
@@ -2498,8 +2677,8 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
       if (flags & (PROP_LOG_LINKS | PROP_REG_INFO
                   | PROP_DEATH_NOTES | PROP_AUTOINC))
        {
-         register rtx y;
-         register int blocknum = pbi->bb->index;
+         rtx y;
+         int blocknum = pbi->bb->index;
 
          y = NULL_RTX;
          if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
@@ -2595,7 +2774,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));
                }
            }
@@ -2635,10 +2814,7 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
    Return true if the register is now unconditionally dead.  */
 
 static int
-mark_regno_cond_dead (pbi, regno, cond)
-     struct propagate_block_info *pbi;
-     int regno;
-     rtx cond;
+mark_regno_cond_dead (struct propagate_block_info *pbi, int regno, rtx cond)
 {
   /* If this is a store to a predicate register, the value of the
      predicate is changing, we don't know that the predicate as seen
@@ -2668,7 +2844,7 @@ mark_regno_cond_dead (pbi, regno, cond)
          /* The register was unconditionally live previously.
             Record the current condition as the condition under
             which it is dead.  */
-         rcli = (struct reg_cond_life_info *) xmalloc (sizeof (*rcli));
+         rcli = xmalloc (sizeof (*rcli));
          rcli->condition = cond;
          rcli->stores = cond;
          rcli->orig_condition = const0_rtx;
@@ -2677,7 +2853,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
@@ -2709,7 +2885,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;
            }
        }
@@ -2721,8 +2897,7 @@ mark_regno_cond_dead (pbi, regno, cond)
 /* Called from splay_tree_delete for pbi->reg_cond_life.  */
 
 static void
-free_reg_cond_life_info (value)
-     splay_tree_value value;
+free_reg_cond_life_info (splay_tree_value value)
 {
   struct reg_cond_life_info *rcli = (struct reg_cond_life_info *) value;
   free (rcli);
@@ -2731,9 +2906,7 @@ free_reg_cond_life_info (value)
 /* Helper function for flush_reg_cond_reg.  */
 
 static int
-flush_reg_cond_reg_1 (node, data)
-     splay_tree_node node;
-     void *data;
+flush_reg_cond_reg_1 (splay_tree_node node, void *data)
 {
   struct reg_cond_life_info *rcli;
   int *xdata = (int *) data;
@@ -2765,9 +2938,7 @@ flush_reg_cond_reg_1 (node, data)
 /* Flush all (sub) expressions referring to REGNO from REG_COND_LIVE.  */
 
 static void
-flush_reg_cond_reg (pbi, regno)
-     struct propagate_block_info *pbi;
-     int regno;
+flush_reg_cond_reg (struct propagate_block_info *pbi, int regno)
 {
   int pair[2];
 
@@ -2784,15 +2955,13 @@ flush_reg_cond_reg (pbi, regno)
    For ior/and, the ADD flag determines whether we want to add the new
    condition X to the old one unconditionally.  If it is zero, we will
    only return a new expression if X allows us to simplify part of
-   OLD, otherwise we return OLD unchanged to the caller.
+   OLD, otherwise we return NULL to the caller.
    If ADD is nonzero, we will return a new condition in all cases.  The
    toplevel caller of one of these functions should always pass 1 for
    ADD.  */
 
 static rtx
-ior_reg_cond (old, x, add)
-     rtx old, x;
-     int add;
+ior_reg_cond (rtx old, rtx x, int add)
 {
   rtx op0, op1;
 
@@ -2806,7 +2975,7 @@ ior_reg_cond (old, x, add)
          && REGNO (XEXP (x, 0)) == REGNO (XEXP (old, 0)))
        return old;
       if (! add)
-       return old;
+       return NULL;
       return gen_rtx_IOR (0, old, x);
     }
 
@@ -2815,51 +2984,63 @@ ior_reg_cond (old, x, add)
     case IOR:
       op0 = ior_reg_cond (XEXP (old, 0), x, 0);
       op1 = ior_reg_cond (XEXP (old, 1), x, 0);
-      if (op0 != XEXP (old, 0) || op1 != XEXP (old, 1))
+      if (op0 != NULL || op1 != NULL)
        {
          if (op0 == const0_rtx)
-           return op1;
+           return op1 ? op1 : gen_rtx_IOR (0, XEXP (old, 1), x);
          if (op1 == const0_rtx)
-           return op0;
+           return op0 ? op0 : gen_rtx_IOR (0, XEXP (old, 0), x);
          if (op0 == const1_rtx || op1 == const1_rtx)
            return const1_rtx;
-         if (op0 == XEXP (old, 0))
-           op0 = gen_rtx_IOR (0, op0, x);
-         else
-           op1 = gen_rtx_IOR (0, op1, x);
+         if (op0 == NULL)
+           op0 = gen_rtx_IOR (0, XEXP (old, 0), x);
+         else if (rtx_equal_p (x, op0))
+           /* (x | A) | x ~ (x | A).  */
+           return old;
+         if (op1 == NULL)
+           op1 = gen_rtx_IOR (0, XEXP (old, 1), x);
+         else if (rtx_equal_p (x, op1))
+           /* (A | x) | x ~ (A | x).  */
+           return old;
          return gen_rtx_IOR (0, op0, op1);
        }
       if (! add)
-       return old;
+       return NULL;
       return gen_rtx_IOR (0, old, x);
 
     case AND:
       op0 = ior_reg_cond (XEXP (old, 0), x, 0);
       op1 = ior_reg_cond (XEXP (old, 1), x, 0);
-      if (op0 != XEXP (old, 0) || op1 != XEXP (old, 1))
+      if (op0 != NULL || op1 != NULL)
        {
          if (op0 == const1_rtx)
-           return op1;
+           return op1 ? op1 : gen_rtx_IOR (0, XEXP (old, 1), x);
          if (op1 == const1_rtx)
-           return op0;
+           return op0 ? op0 : gen_rtx_IOR (0, XEXP (old, 0), x);
          if (op0 == const0_rtx || op1 == const0_rtx)
            return const0_rtx;
-         if (op0 == XEXP (old, 0))
-           op0 = gen_rtx_IOR (0, op0, x);
-         else
-           op1 = gen_rtx_IOR (0, op1, x);
+         if (op0 == NULL)
+           op0 = gen_rtx_IOR (0, XEXP (old, 0), x);
+         else if (rtx_equal_p (x, op0))
+           /* (x & A) | x ~ x.  */
+           return op0;
+         if (op1 == NULL)
+           op1 = gen_rtx_IOR (0, XEXP (old, 1), x);
+         else if (rtx_equal_p (x, op1))
+           /* (A & x) | x ~ x.  */
+           return op1;
          return gen_rtx_AND (0, op0, op1);
        }
       if (! add)
-       return old;
+       return NULL;
       return gen_rtx_IOR (0, old, x);
 
     case NOT:
       op0 = and_reg_cond (XEXP (old, 0), not_reg_cond (x), 0);
-      if (op0 != XEXP (old, 0))
+      if (op0 != NULL)
        return not_reg_cond (op0);
       if (! add)
-       return old;
+       return NULL;
       return gen_rtx_IOR (0, old, x);
 
     default:
@@ -2868,8 +3049,7 @@ ior_reg_cond (old, x, add)
 }
 
 static rtx
-not_reg_cond (x)
-     rtx x;
+not_reg_cond (rtx x)
 {
   enum rtx_code x_code;
 
@@ -2893,9 +3073,7 @@ not_reg_cond (x)
 }
 
 static rtx
-and_reg_cond (old, x, add)
-     rtx old, x;
-     int add;
+and_reg_cond (rtx old, rtx x, int add)
 {
   rtx op0, op1;
 
@@ -2909,7 +3087,7 @@ and_reg_cond (old, x, add)
          && REGNO (XEXP (x, 0)) == REGNO (XEXP (old, 0)))
        return old;
       if (! add)
-       return old;
+       return NULL;
       return gen_rtx_AND (0, old, x);
     }
 
@@ -2918,62 +3096,63 @@ and_reg_cond (old, x, add)
     case IOR:
       op0 = and_reg_cond (XEXP (old, 0), x, 0);
       op1 = and_reg_cond (XEXP (old, 1), x, 0);
-      if (op0 != XEXP (old, 0) || op1 != XEXP (old, 1))
+      if (op0 != NULL || op1 != NULL)
        {
          if (op0 == const0_rtx)
-           return op1;
+           return op1 ? op1 : gen_rtx_AND (0, XEXP (old, 1), x);
          if (op1 == const0_rtx)
-           return op0;
+           return op0 ? op0 : gen_rtx_AND (0, XEXP (old, 0), x);
          if (op0 == const1_rtx || op1 == const1_rtx)
            return const1_rtx;
-         if (op0 == XEXP (old, 0))
-           op0 = gen_rtx_AND (0, op0, x);
-         else
-           op1 = gen_rtx_AND (0, op1, x);
+         if (op0 == NULL)
+           op0 = gen_rtx_AND (0, XEXP (old, 0), x);
+         else if (rtx_equal_p (x, op0))
+           /* (x | A) & x ~ x.  */
+           return op0;
+         if (op1 == NULL)
+           op1 = gen_rtx_AND (0, XEXP (old, 1), x);
+         else if (rtx_equal_p (x, op1))
+           /* (A | x) & x ~ x.  */
+           return op1;
          return gen_rtx_IOR (0, op0, op1);
        }
       if (! add)
-       return old;
+       return NULL;
       return gen_rtx_AND (0, old, x);
 
     case AND:
       op0 = and_reg_cond (XEXP (old, 0), x, 0);
       op1 = and_reg_cond (XEXP (old, 1), x, 0);
-      if (op0 != XEXP (old, 0) || op1 != XEXP (old, 1))
+      if (op0 != NULL || op1 != NULL)
        {
          if (op0 == const1_rtx)
-           return op1;
+           return op1 ? op1 : gen_rtx_AND (0, XEXP (old, 1), x);
          if (op1 == const1_rtx)
-           return op0;
+           return op0 ? op0 : gen_rtx_AND (0, XEXP (old, 0), x);
          if (op0 == const0_rtx || op1 == const0_rtx)
            return const0_rtx;
-         if (op0 == XEXP (old, 0))
-           op0 = gen_rtx_AND (0, op0, x);
-         else
-           op1 = gen_rtx_AND (0, op1, x);
+         if (op0 == NULL)
+           op0 = gen_rtx_AND (0, XEXP (old, 0), x);
+         else if (rtx_equal_p (x, op0))
+           /* (x & A) & x ~ (x & A).  */
+           return old;
+         if (op1 == NULL)
+           op1 = gen_rtx_AND (0, XEXP (old, 1), x);
+         else if (rtx_equal_p (x, op1))
+           /* (A & x) & x ~ (A & x).  */
+           return old;
          return gen_rtx_AND (0, op0, op1);
        }
       if (! add)
-       return old;
-
-      /* If X is identical to one of the existing terms of the AND,
-        then just return what we already have.  */
-      /* ??? There really should be some sort of recursive check here in
-        case there are nested ANDs.  */
-      if ((GET_CODE (XEXP (old, 0)) == GET_CODE (x)
-          && REGNO (XEXP (XEXP (old, 0), 0)) == REGNO (XEXP (x, 0)))
-         || (GET_CODE (XEXP (old, 1)) == GET_CODE (x)
-             && REGNO (XEXP (XEXP (old, 1), 0)) == REGNO (XEXP (x, 0))))
-       return old;
-
+       return NULL;
       return gen_rtx_AND (0, old, x);
 
     case NOT:
       op0 = ior_reg_cond (XEXP (old, 0), not_reg_cond (x), 0);
-      if (op0 != XEXP (old, 0))
+      if (op0 != NULL)
        return not_reg_cond (op0);
       if (! add)
-       return old;
+       return NULL;
       return gen_rtx_AND (0, old, x);
 
     default:
@@ -2987,9 +3166,7 @@ and_reg_cond (old, x, add)
    is used when the value of REGNO changes.  */
 
 static rtx
-elim_reg_cond (x, regno)
-     rtx x;
-     unsigned int regno;
+elim_reg_cond (rtx x, unsigned int regno)
 {
   rtx op0, op1;
 
@@ -3053,9 +3230,8 @@ elim_reg_cond (x, regno)
    else.  */
 
 static void
-attempt_auto_inc (pbi, inc, insn, mem, incr, incr_reg)
-     struct propagate_block_info *pbi;
-     rtx inc, insn, mem, incr, incr_reg;
+attempt_auto_inc (struct propagate_block_info *pbi, rtx inc, rtx insn,
+                 rtx mem, rtx incr, rtx incr_reg)
 {
   int regno = REGNO (incr_reg);
   rtx set = single_set (incr);
@@ -3099,10 +3275,6 @@ attempt_auto_inc (pbi, inc, insn, mem, incr, incr_reg)
       insns = get_insns ();
       end_sequence ();
 
-      if (basic_block_for_insn)
-       for (temp = insns; temp; temp = NEXT_INSN (temp))
-         set_block_for_insn (temp, pbi->bb);
-
       /* If we can't make the auto-inc, or can't make the
         replacement into Y, exit.  There's no point in making
         the change below if we can't do the auto-inc and doing
@@ -3116,7 +3288,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;
@@ -3201,10 +3373,7 @@ attempt_auto_inc (pbi, inc, insn, mem, incr, incr_reg)
    reference.  */
 
 static void
-find_auto_inc (pbi, x, insn)
-     struct propagate_block_info *pbi;
-     rtx x;
-     rtx insn;
+find_auto_inc (struct propagate_block_info *pbi, rtx x, rtx insn)
 {
   rtx addr = XEXP (x, 0);
   HOST_WIDE_INT offset = 0;
@@ -3269,6 +3438,12 @@ find_auto_inc (pbi, x, insn)
                                                                  addr,
                                                                  inc_val)),
                          insn, x, incr, addr);
+      else if (HAVE_PRE_MODIFY_DISP && offset == INTVAL (inc_val))
+       attempt_auto_inc (pbi, gen_rtx_PRE_MODIFY (Pmode, addr,
+                                                   gen_rtx_PLUS (Pmode,
+                                                                 addr,
+                                                                 inc_val)),
+                         insn, x, incr, addr);
     }
   else if (GET_CODE (inc_val) == REG
           && ! reg_set_between_p (inc_val, PREV_INSN (insn),
@@ -3287,11 +3462,8 @@ find_auto_inc (pbi, x, insn)
 #endif /* AUTO_INC_DEC */
 \f
 static void
-mark_used_reg (pbi, reg, cond, insn)
-     struct propagate_block_info *pbi;
-     rtx reg;
-     rtx cond ATTRIBUTE_UNUSED;
-     rtx insn;
+mark_used_reg (struct propagate_block_info *pbi, rtx reg,
+              rtx cond ATTRIBUTE_UNUSED, rtx insn)
 {
   unsigned int regno_first, regno_last, i;
   int some_was_live, some_was_dead, some_not_set;
@@ -3347,7 +3519,7 @@ mark_used_reg (pbi, reg, cond, insn)
        {
          /* Keep track of which basic block each reg appears in.  */
 
-         register int blocknum = pbi->bb->index;
+         int blocknum = pbi->bb->index;
          if (REG_BASIC_BLOCK (regno_first) == REG_BLOCK_UNKNOWN)
            REG_BASIC_BLOCK (regno_first) = blocknum;
          else if (REG_BASIC_BLOCK (regno_first) != blocknum)
@@ -3394,7 +3566,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));
        }
     }
@@ -3402,6 +3574,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
@@ -3413,7 +3589,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)
@@ -3445,7 +3621,7 @@ mark_used_reg (pbi, reg, cond, insn)
            {
              /* The register was not previously live at all.  Record
                 the condition under which it is still dead.  */
-             rcli = (struct reg_cond_life_info *) xmalloc (sizeof (*rcli));
+             rcli = xmalloc (sizeof (*rcli));
              rcli->condition = not_reg_cond (cond);
              rcli->stores = const0_rtx;
              rcli->orig_condition = const0_rtx;
@@ -3455,7 +3631,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
@@ -3475,15 +3651,15 @@ mark_used_reg (pbi, reg, cond, insn)
    is not called.  */
 
 static void
-mark_used_regs (pbi, x, cond, insn)
-     struct propagate_block_info *pbi;
-     rtx x, cond, insn;
+mark_used_regs (struct propagate_block_info *pbi, rtx x, rtx cond, rtx insn)
 {
-  register RTX_CODE code;
-  register int regno;
+  RTX_CODE code;
+  int regno;
   int flags = pbi->flags;
 
  retry:
+  if (!x)
+    return;
   code = GET_CODE (x);
   switch (code)
     {
@@ -3492,6 +3668,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:
@@ -3513,7 +3690,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.  */
@@ -3530,7 +3707,7 @@ mark_used_regs (pbi, x, cond, insn)
              while (temp)
                {
                  next = XEXP (temp, 1);
-                 if (anti_dependence (XEXP (temp, 0), x))
+                 if (unchanging_anti_dependence (XEXP (temp, 0), x))
                    {
                      /* Splice temp out of the list.  */
                      if (prev)
@@ -3550,22 +3727,23 @@ 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;
 
     case SUBREG:
-#ifdef CLASS_CANNOT_CHANGE_MODE
-      if (GET_CODE (SUBREG_REG (x)) == REG
-         && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER
-         && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (x),
-                                        GET_MODE (SUBREG_REG (x))))
-       REG_CHANGES_MODE (REGNO (SUBREG_REG (x))) = 1;
+#ifdef CANNOT_CHANGE_MODE_CLASS
+      if ((flags & PROP_REG_INFO)
+         && GET_CODE (SUBREG_REG (x)) == REG
+         && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER)
+       bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (x))
+                                         * MAX_MACHINE_MODE
+                                         + GET_MODE (x));
 #endif
 
       /* While we're here, optimize this case.  */
@@ -3581,7 +3759,7 @@ mark_used_regs (pbi, x, cond, insn)
 
     case SET:
       {
-       register rtx testreg = SET_DEST (x);
+       rtx testreg = SET_DEST (x);
        int mark_dest = 0;
 
        /* If storing into MEM, don't show it as being used.  But do
@@ -3609,20 +3787,24 @@ mark_used_regs (pbi, x, cond, insn)
               || GET_CODE (testreg) == SIGN_EXTRACT
               || GET_CODE (testreg) == SUBREG)
          {
-#ifdef CLASS_CANNOT_CHANGE_MODE
-           if (GET_CODE (testreg) == SUBREG
+#ifdef CANNOT_CHANGE_MODE_CLASS
+           if ((flags & PROP_REG_INFO)
+               && GET_CODE (testreg) == SUBREG
                && GET_CODE (SUBREG_REG (testreg)) == REG
-               && REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER
-               && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (testreg)),
-                                              GET_MODE (testreg)))
-             REG_CHANGES_MODE (REGNO (SUBREG_REG (testreg))) = 1;
+               && REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER)
+             bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (testreg))
+                                               * MAX_MACHINE_MODE
+                                               + GET_MODE (testreg));
 #endif
 
            /* Modifying a single register in an alternate mode
               does not use any of the old value.  But these other
               ways of storing in a register do use the old value.  */
            if (GET_CODE (testreg) == SUBREG
-               && !(REG_SIZE (SUBREG_REG (testreg)) > REG_SIZE (testreg)))
+               && !((REG_BYTES (SUBREG_REG (testreg))
+                     + UNITS_PER_WORD - 1) / UNITS_PER_WORD
+                    > (REG_BYTES (testreg)
+                       + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
              ;
            else
              mark_dest = 1;
@@ -3705,14 +3887,6 @@ mark_used_regs (pbi, x, cond, insn)
       x = COND_EXEC_CODE (x);
       goto retry;
 
-    case PHI:
-      /* We _do_not_ want to scan operands of phi nodes.  Operands of
-        a phi function are evaluated only when control reaches this
-        block along a particular edge.  Therefore, regs that appear
-        as arguments to phi should not be added to the global live at
-        start.  */
-      return;
-
     default:
       break;
     }
@@ -3720,8 +3894,8 @@ mark_used_regs (pbi, x, cond, insn)
   /* Recursively scan the operands of this expression.  */
 
   {
-    register const char * const fmt = GET_RTX_FORMAT (code);
-    register int i;
+    const char * const fmt = GET_RTX_FORMAT (code);
+    int i;
 
     for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
       {
@@ -3737,7 +3911,7 @@ mark_used_regs (pbi, x, cond, insn)
          }
        else if (fmt[i] == 'E')
          {
-           register int j;
+           int j;
            for (j = 0; j < XVECLEN (x, i); j++)
              mark_used_regs (pbi, XVECEXP (x, i, j), cond, insn);
          }
@@ -3748,9 +3922,7 @@ mark_used_regs (pbi, x, cond, insn)
 #ifdef AUTO_INC_DEC
 
 static int
-try_pre_increment_1 (pbi, insn)
-     struct propagate_block_info *pbi;
-     rtx insn;
+try_pre_increment_1 (struct propagate_block_info *pbi, rtx insn)
 {
   /* Find the next use of this reg.  If in same basic block,
      make it do pre-increment or pre-decrement if appropriate.  */
@@ -3769,7 +3941,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,
@@ -3796,11 +3968,9 @@ try_pre_increment_1 (pbi, insn)
    This checks all about the validity of the result of modifying INSN.  */
 
 static int
-try_pre_increment (insn, reg, amount)
-     rtx insn, reg;
-     HOST_WIDE_INT amount;
+try_pre_increment (rtx insn, rtx reg, HOST_WIDE_INT amount)
 {
-  register rtx use;
+  rtx use;
 
   /* Nonzero if we can try to make a pre-increment or pre-decrement.
      For example, addl $4,r1; movl (r1),... can become movl +(r1),...  */
@@ -3839,13 +4009,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))
@@ -3873,19 +4043,16 @@ 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)
-     register rtx x;
-     rtx reg;
-     HOST_WIDE_INT plusconst;
+find_use_as_address (rtx x, rtx reg, HOST_WIDE_INT plusconst)
 {
   enum rtx_code code = GET_CODE (x);
   const char * const fmt = GET_RTX_FORMAT (code);
-  register int i;
-  register rtx value = 0;
-  register rtx tem;
+  int i;
+  rtx value = 0;
+  rtx tem;
 
   if (code == MEM && XEXP (x, 0) == reg && plusconst == 0)
     return x;
@@ -3901,11 +4068,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--)
     {
@@ -3915,18 +4082,18 @@ 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')
        {
-         register int j;
+         int j;
          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
            {
              tem = find_use_as_address (XVECEXP (x, i, j), reg, plusconst);
              if (value == 0)
                value = tem;
              else if (tem != 0)
-               return (rtx) (HOST_WIDE_INT) 1;
+               return (rtx) (size_t) 1;
            }
        }
     }
@@ -3938,9 +4105,7 @@ find_use_as_address (x, reg, plusconst)
    This is part of making a debugging dump.  */
 
 void
-dump_regset (r, outf)
-     regset r;
-     FILE *outf;
+dump_regset (regset r, FILE *outf)
 {
   int i;
   if (r == NULL)
@@ -3958,35 +4123,17 @@ dump_regset (r, outf)
     });
 }
 
-/* Print a human-reaable representation of R on the standard error
+/* Print a human-readable representation of R on the standard error
    stream.  This function is designed to be used from within the
    debugger.  */
 
 void
-debug_regset (r)
-     regset r;
+debug_regset (regset r)
 {
   dump_regset (r, stderr);
   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.
 
@@ -4007,9 +4154,7 @@ print_rtl_and_abort_fcn (file, line, function)
    possibly other information which is used by the register allocators.  */
 
 void
-recompute_reg_usage (f, loop_step)
-     rtx f ATTRIBUTE_UNUSED;
-     int loop_step ATTRIBUTE_UNUSED;
+recompute_reg_usage (rtx f ATTRIBUTE_UNUSED, int loop_step ATTRIBUTE_UNUSED)
 {
   allocate_reg_life_data ();
   update_life_info (NULL, UPDATE_LIFE_LOCAL, PROP_REG_INFO);
@@ -4020,22 +4165,18 @@ recompute_reg_usage (f, loop_step)
    of the number of registers that died.  */
 
 int
-count_or_remove_death_notes (blocks, kill)
-     sbitmap blocks;
-     int kill;
+count_or_remove_death_notes (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))
@@ -4086,31 +4227,31 @@ count_or_remove_death_notes (blocks, kill)
 
   return count;
 }
-/* Clear LOG_LINKS fields of insns in a chain.
-   Also clear the global_live_at_{start,end} fields of the basic block
-   structures.  */
+/* Clear LOG_LINKS fields of insns in a selected blocks or whole chain
+   if blocks is NULL.  */
 
-void
-clear_log_links (insns)
-     rtx insns;
+static void
+clear_log_links (sbitmap blocks)
 {
-  rtx i;
-  int b;
-
-  for (i = insns; i; i = NEXT_INSN (i))
-    if (INSN_P (i))
-      LOG_LINKS (i) = 0;
+  rtx insn;
+  int i;
 
-  for (b = 0; b < n_basic_blocks; b++)
+  if (!blocks)
     {
-      basic_block bb = BASIC_BLOCK (b);
-
-      bb->global_live_at_start = NULL;
-      bb->global_live_at_end = NULL;
+      for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+       if (INSN_P (insn))
+         free_INSN_LIST_list (&LOG_LINKS (insn));
     }
+  else
+    EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i,
+      {
+       basic_block bb = BASIC_BLOCK (i);
 
-  ENTRY_BLOCK_PTR->global_live_at_end = NULL;
-  EXIT_BLOCK_PTR->global_live_at_start = NULL;
+       for (insn = bb->head; insn != NEXT_INSN (bb->end);
+            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
@@ -4119,9 +4260,7 @@ clear_log_links (insns)
    with moving single words, but probably isn't worth the trouble.  */
 
 void
-reg_set_to_hard_reg_set (to, from)
-     HARD_REG_SET *to;
-     bitmap from;
+reg_set_to_hard_reg_set (HARD_REG_SET *to, bitmap from)
 {
   int i;