OSDN Git Service

* flow.c (update_life_info): Amend comment about when a register
[pf3gnuchains/gcc-fork.git] / gcc / flow.c
index cdfbee5..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, 2002 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.
@@ -207,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.  */
@@ -272,10 +270,10 @@ 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;
 };
 
@@ -287,65 +285,51 @@ static int ndead;
 #define MAX_MEM_SET_LIST_LEN   100
 
 /* Forward declarations */
-static int verify_wide_reg_1           PARAMS ((rtx *, void *));
-static void verify_wide_reg            PARAMS ((int, basic_block));
-static void verify_local_live_at_start PARAMS ((regset, basic_block));
-static void notice_stack_pointer_modification_1 PARAMS ((rtx, rtx, void *));
-static void notice_stack_pointer_modification PARAMS ((rtx));
-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 ((rtx));
-static rtx propagate_block_delete_libcall PARAMS ((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 find_regno_partial          PARAMS ((rtx *, void *));
+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 add_to_mem_set_list                PARAMS ((struct propagate_block_info *,
-                                                rtx));
-static int invalidate_mems_from_autoinc PARAMS ((rtx *, void *));
-static void invalidate_mems_from_set   PARAMS ((struct propagate_block_info *,
-                                                rtx));
-static void clear_log_links            PARAMS ((sbitmap));
+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)
@@ -373,10 +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.  */
-         if (BLOCK_FOR_INSN (cfun->x_clobber_return_insn) != NULL)
-           warning ("control reaches end of non-void function");
+         rtx insn;
+
+         for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+           if (insn == cfun->x_clobber_return_insn)
+             {
+               warning ("control reaches end of non-void function");
+               break;
+             }
        }
     }
 }
@@ -385,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;
 
@@ -408,10 +395,7 @@ 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
   int i;
@@ -430,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);
 
@@ -447,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
@@ -477,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)
@@ -485,20 +475,6 @@ 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 ();
 }
@@ -508,9 +484,7 @@ life_analysis (f, file, flags)
    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;
@@ -528,9 +502,7 @@ verify_wide_reg_1 (px, pregno)
    of BB looking for register REGNO.  */
 
 static void
-verify_wide_reg (regno, bb)
-     int regno;
-     basic_block bb;
+verify_wide_reg (int regno, basic_block bb)
 {
   rtx head = bb->head, end = bb->end;
 
@@ -561,9 +533,7 @@ verify_wide_reg (regno, bb)
    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)
     {
@@ -575,7 +545,7 @@ verify_local_live_at_start (new_live_at_start, bb)
            {
              fprintf (rtl_dump_file,
                       "live_at_start mismatch in bb %d, aborting\nNew:\n",
-                      bb->sindex);
+                      bb->index);
              debug_bitmap_file (rtl_dump_file, new_live_at_start);
              fputs ("Old:\n", rtl_dump_file);
              dump_bb (bb, rtl_dump_file);
@@ -592,7 +562,7 @@ 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)
@@ -604,7 +574,7 @@ verify_local_live_at_start (new_live_at_start, bb)
              abort ();
            }
 
-          /* Verify that the now-live register is wider than word_mode.  */
+         /* Verify that the now-live register is wider than word_mode.  */
          verify_wide_reg (i, bb);
        });
     }
@@ -613,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.
@@ -624,19 +594,20 @@ 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.  */
 
 int
-update_life_info (blocks, extent, prop_flags)
-     sbitmap blocks;
-     enum update_life_extent extent;
-     int prop_flags;
+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;
@@ -656,10 +627,10 @@ update_life_info (blocks, extent, prop_flags)
       for ( ; ; )
        {
          int changed = 0;
-         basic_block bb;
 
          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))
@@ -668,12 +639,12 @@ 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_ALL_BB_REVERSE (bb)
+         FOR_EACH_BB_REVERSE (bb)
            {
-
              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));
            }
 
@@ -682,7 +653,8 @@ update_life_info (blocks, extent, prop_flags)
             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_KILL_DEAD_CODE);
+           &= ~(PROP_SCAN_DEAD_CODE | PROP_SCAN_DEAD_STORES
+                | PROP_KILL_DEAD_CODE);
 
          if (! changed)
            break;
@@ -692,6 +664,16 @@ update_life_info (blocks, extent, prop_flags)
             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.  */
@@ -707,7 +689,7 @@ update_life_info (blocks, extent, prop_flags)
     {
       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, stabilized_prop_flags);
@@ -718,9 +700,7 @@ update_life_info (blocks, extent, prop_flags)
     }
   else
     {
-      basic_block bb;
-
-      FOR_ALL_BB_REVERSE (bb)
+      FOR_EACH_BB_REVERSE (bb)
        {
          COPY_REG_SET (tmp, bb->global_live_at_end);
 
@@ -771,9 +751,7 @@ update_life_info (blocks, extent, prop_flags)
 /* Update life information in all blocks where BB_DIRTY is set.  */
 
 int
-update_life_info_in_dirty_blocks (extent, prop_flags)
-     enum update_life_extent extent;
-     int prop_flags;
+update_life_info_in_dirty_blocks (enum update_life_extent extent, int prop_flags)
 {
   sbitmap update_life_blocks = sbitmap_alloc (last_basic_block);
   int n = 0;
@@ -781,12 +759,25 @@ update_life_info_in_dirty_blocks (extent, prop_flags)
   int retval = 0;
 
   sbitmap_zero (update_life_blocks);
-  FOR_ALL_BB (bb)
-    if (bb->flags & BB_DIRTY)
-      {
-       SET_BIT (update_life_blocks, bb->sindex);
-       n++;
-      }
+  FOR_EACH_BB (bb)
+    {
+      if (extent == UPDATE_LIFE_LOCAL)
+       {
+         if (bb->flags & BB_DIRTY)
+           {
+             SET_BIT (update_life_blocks, bb->index);
+             n++;
+           }
+       }
+      else
+       {
+         /* ??? Bootstrap with -march=pentium4 fails to terminate
+            with only a partial life update.  */
+         SET_BIT (update_life_blocks, bb->index);
+         if (bb->flags & BB_DIRTY)
+           n++;
+       }
+    }
 
   if (n)
     retval = update_life_info (update_life_blocks, extent, prop_flags);
@@ -797,11 +788,10 @@ update_life_info_in_dirty_blocks (extent, prop_flags)
 
 /* Free the variables allocated by find_basic_blocks.
 
-   KEEP_HEAD_END_P is non-zero if basic_block_info is not to be freed.  */
+   KEEP_HEAD_END_P is nonzero if basic_block_info is not to be freed.  */
 
 void
-free_basic_block_vars (keep_head_end_p)
-     int keep_head_end_p;
+free_basic_block_vars (int keep_head_end_p)
 {
   if (! keep_head_end_p)
     {
@@ -810,7 +800,7 @@ free_basic_block_vars (keep_head_end_p)
          clear_edges ();
          VARRAY_FREE (basic_block_info);
        }
-      num_basic_blocks = 0;
+      n_basic_blocks = 0;
       last_basic_block = 0;
 
       ENTRY_BLOCK_PTR->aux = NULL;
@@ -823,14 +813,13 @@ free_basic_block_vars (keep_head_end_p)
 /* Delete any insns that copy a register to itself.  */
 
 int
-delete_noop_moves (f)
-     rtx f ATTRIBUTE_UNUSED;
+delete_noop_moves (rtx f ATTRIBUTE_UNUSED)
 {
   rtx insn, next;
   basic_block bb;
   int nnoops = 0;
 
-  FOR_ALL_BB (bb)
+  FOR_EACH_BB (bb)
     {
       for (insn = bb->head; insn != NEXT_INSN (bb->end); insn = next)
        {
@@ -869,7 +858,7 @@ delete_noop_moves (f)
    insns computing the destination, so we delay deleting and garbagecollect
    them once life information is computed.  */
 void
-delete_dead_jumptables ()
+delete_dead_jumptables (void)
 {
   rtx insn, next;
   for (insn = get_insns (); insn; insn = next)
@@ -894,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
@@ -910,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;
 
@@ -938,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);
@@ -961,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
@@ -988,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
     }
 
@@ -996,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
@@ -1008,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++)
@@ -1029,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;
@@ -1038,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;
@@ -1051,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.
@@ -1074,18 +1041,16 @@ 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, bb;
-  regset tmp, new_live_at_end, call_used;
-  regset_head tmp_head, call_used_head;
+  regset tmp, new_live_at_end, invalidated_by_call;
+  regset_head tmp_head, invalidated_by_call_head;
   regset_head new_live_at_end_head;
   int i;
 
   /* Some passes used to forget clear aux field of basic block causing
-     sick behaviour here.  */
+     sick behavior here.  */
 #ifdef ENABLE_CHECKING
   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
     if (bb->aux)
@@ -1094,39 +1059,35 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
 
   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 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 ((num_basic_blocks + 2) * sizeof (*queue));
+  queue = xmalloc ((n_basic_blocks + 2) * sizeof (*queue));
   qtail = queue;
-  qhead = qend = queue + num_basic_blocks + 2;
+  qhead = qend = queue + n_basic_blocks + 2;
 
   /* Queue the blocks set in the initial mask.  Do this in reverse block
      number order so that we are more likely for the first round to do
      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_ALL_BB (bb)
-       bb->aux = NULL;
-
-      EXECUTE_IF_SET_IN_SBITMAP (blocks_in, 0, i,
-       {
-         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_ALL_BB (bb)
+      FOR_EACH_BB (bb)
        {
          *--qhead = bb;
          bb->aux = bb;
@@ -1185,7 +1146,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
            if (e->flags & EDGE_EH)
              {
                bitmap_operation (tmp, sb->global_live_at_start,
-                                 call_used, BITMAP_AND_COMPL);
+                                 invalidated_by_call, BITMAP_AND_COMPL);
                IOR_REG_SET (new_live_at_end, tmp);
              }
            else
@@ -1229,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);
@@ -1303,7 +1256,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
       /* Let our caller know that BB changed enough to require its
         death notes updated.  */
       if (blocks_out)
-       SET_BIT (blocks_out, bb->sindex);
+       SET_BIT (blocks_out, bb->index);
 
       if (! rescan)
        {
@@ -1353,20 +1306,20 @@ 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)
     {
       EXECUTE_IF_SET_IN_SBITMAP (blocks_out, 0, i,
        {
-         bb = BASIC_BLOCK (i);
+         basic_block bb = BASIC_BLOCK (i);
          FREE_REG_SET (bb->local_set);
          FREE_REG_SET (bb->cond_local_set);
        });
     }
   else
     {
-      FOR_ALL_BB (bb)
+      FOR_EACH_BB (bb)
        {
          FREE_REG_SET (bb->local_set);
          FREE_REG_SET (bb->cond_local_set);
@@ -1377,7 +1330,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
 }
 
 \f
-/* This structure is used to pass parameters to an from the
+/* 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.  */
@@ -1392,9 +1345,7 @@ typedef struct {
    part of an expression which only uses part of the register.  Return
    it in the structure passed in.  */
 static int
-find_regno_partial (ptr, data)
-     rtx *ptr;
-     void *data;
+find_regno_partial (rtx *ptr, void *data)
 {
   find_regno_partial_param *param = (find_regno_partial_param *)data;
   unsigned reg = param->regno_to_find;
@@ -1439,7 +1390,7 @@ find_regno_partial (ptr, data)
    bits we don't want.  */
 
 int
-initialize_uninitialized_subregs ()
+initialize_uninitialized_subregs (void)
 {
   rtx insn;
   edge e;
@@ -1470,8 +1421,11 @@ initialize_uninitialized_subregs ()
              for_each_rtx (&i, find_regno_partial, &param);
              if (param.retval != NULL_RTX)
                {
-                 insn = gen_move_insn (param.retval,
-                                       CONST0_RTX (GET_MODE (param.retval)));
+                 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;
                }
@@ -1491,26 +1445,21 @@ initialize_uninitialized_subregs ()
    of life analysis.  Not static since used also for stupid life analysis.  */
 
 void
-allocate_bb_life_data ()
+allocate_bb_life_data (void)
 {
   basic_block bb;
 
-  FOR_ALL_BB (bb)
+  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
     {
       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;
 
@@ -1529,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;
     }
 }
@@ -1536,8 +1486,7 @@ allocate_reg_life_data ()
 /* Delete dead instructions for propagate_block.  */
 
 static void
-propagate_block_delete_insn (insn)
-     rtx insn;
+propagate_block_delete_insn (rtx insn)
 {
   rtx inote = find_reg_note (insn, REG_LABEL, NULL_RTX);
 
@@ -1549,11 +1498,7 @@ propagate_block_delete_insn (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)
     {
@@ -1590,8 +1535,7 @@ propagate_block_delete_insn (insn)
    before the libcall.  */
 
 static rtx
-propagate_block_delete_libcall ( insn, note)
-     rtx insn, note;
+propagate_block_delete_libcall (rtx insn, rtx note)
 {
   rtx first = XEXP (note, 0);
   rtx before = PREV_INSN (first);
@@ -1604,9 +1548,7 @@ propagate_block_delete_libcall ( insn, note)
 /* 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;
@@ -1658,7 +1600,42 @@ propagate_one_insn (pbi, insn)
       if (libcall_is_dead)
        prev = propagate_block_delete_libcall ( insn, note);
       else
-       propagate_block_delete_insn (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;
     }
@@ -1727,8 +1704,10 @@ propagate_one_insn (pbi, insn)
 
       if (GET_CODE (insn) == CALL_INSN)
        {
-         int i;
+         regset live_at_end;
+         bool sibcall_p;
          rtx note, cond;
+         int i;
 
          cond = NULL_RTX;
          if (GET_CODE (PATTERN (insn)) == COND_EXEC)
@@ -1742,7 +1721,7 @@ propagate_one_insn (pbi, insn)
              free_EXPR_LIST_list (&pbi->mem_set_list);
              pbi->mem_set_list_len = 0;
            }
-          else
+         else
            invalidate_mems_from_set (pbi, stack_pointer_rtx);
 
          /* There may be extra registers to be clobbered.  */
@@ -1753,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));
              }
        }
@@ -1792,13 +1780,14 @@ propagate_one_insn (pbi, insn)
          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);
@@ -1807,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);
        }
     }
 
@@ -1826,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));
 
@@ -1843,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;
 
@@ -1854,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.  */
@@ -1891,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);
@@ -1952,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
@@ -1967,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
@@ -1988,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);
 
@@ -2022,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;
@@ -2061,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;
@@ -2076,20 +2058,21 @@ 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
   /* As flow is invoked after combine, we must take existing AUTO_INC
      expressions into account.  */
@@ -2146,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);
 
@@ -2275,10 +2258,7 @@ 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);
 
@@ -2332,17 +2312,16 @@ libcall_dead_p (pbi, note, insn)
    fixed hard registers.  */
 
 int
-regno_uninitialized (regno)
-     unsigned int regno;
+regno_uninitialized (unsigned int regno)
 {
-  if (num_basic_blocks == 0
+  if (n_basic_blocks == 0
       || (regno < FIRST_PSEUDO_REGISTER
          && (global_regs[regno]
              || fixed_regs[regno]
              || FUNCTION_ARG_REGNO_P (regno))))
     return 0;
 
-  return REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->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
@@ -2350,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 (num_basic_blocks == 0)
+  if (n_basic_blocks == 0)
     return 0;
 
   return ((REG_N_SETS (regno) > 1
-          || REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->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;
 
@@ -2413,9 +2389,7 @@ add_to_mem_set_list (pbi, mem)
    to an address change.  */
 
 static int
-invalidate_mems_from_autoinc (px, data)
-     rtx *px;
-     void *data;
+invalidate_mems_from_autoinc (rtx *px, void *data)
 {
   rtx x = *px;
   struct propagate_block_info *pbi = data;
@@ -2432,9 +2406,7 @@ invalidate_mems_from_autoinc (px, data)
 /* 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;
@@ -2467,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;
@@ -2540,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;
@@ -2639,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);
@@ -2653,7 +2619,7 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
       if (GET_CODE (reg) == MEM && ! side_effects_p (reg)
          /* ??? With more effort we could track conditional memory life.  */
          && ! cond)
-        add_to_mem_set_list (pbi, canon_rtx (reg));
+       add_to_mem_set_list (pbi, canon_rtx (reg));
     }
 
   if (GET_CODE (reg) == REG
@@ -2712,7 +2678,7 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
                   | PROP_DEATH_NOTES | PROP_AUTOINC))
        {
          rtx y;
-         int blocknum = pbi->bb->sindex;
+         int blocknum = pbi->bb->index;
 
          y = NULL_RTX;
          if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
@@ -2808,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));
                }
            }
@@ -2848,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
@@ -2881,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;
@@ -2934,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);
@@ -2944,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;
@@ -2978,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];
 
@@ -3003,9 +2961,7 @@ flush_reg_cond_reg (pbi, regno)
    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;
 
@@ -3093,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;
 
@@ -3118,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;
 
@@ -3213,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;
 
@@ -3279,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);
@@ -3338,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;
@@ -3423,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;
@@ -3491,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),
@@ -3509,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;
@@ -3569,7 +3519,7 @@ mark_used_reg (pbi, reg, cond, insn)
        {
          /* Keep track of which basic block each reg appears in.  */
 
-         int blocknum = pbi->bb->sindex;
+         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)
@@ -3616,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));
        }
     }
@@ -3671,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;
@@ -3701,9 +3651,7 @@ 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)
 {
   RTX_CODE code;
   int regno;
@@ -3742,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.  */
@@ -3759,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)
@@ -3784,17 +3732,18 @@ mark_used_regs (pbi, x, cond, insn)
 
 #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.  */
@@ -3838,13 +3787,14 @@ 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
@@ -3937,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;
     }
@@ -3980,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.  */
@@ -4028,9 +3968,7 @@ 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)
 {
   rtx use;
 
@@ -4108,10 +4046,7 @@ try_pre_increment (insn, reg, amount)
    return (rtx) 1.  */
 
 rtx
-find_use_as_address (x, reg, plusconst)
-     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);
@@ -4170,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)
@@ -4190,13 +4123,12 @@ 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);
@@ -4222,9 +4154,7 @@ debug_regset (r)
    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);
@@ -4235,18 +4165,16 @@ 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 count = 0;
   basic_block bb;
 
-  FOR_ALL_BB_REVERSE (bb)
+  FOR_EACH_BB_REVERSE (bb)
     {
       rtx insn;
 
-      if (blocks && ! TEST_BIT (blocks, bb->sindex))
+      if (blocks && ! TEST_BIT (blocks, bb->index))
        continue;
 
       for (insn = bb->head;; insn = NEXT_INSN (insn))
@@ -4303,8 +4231,7 @@ count_or_remove_death_notes (blocks, kill)
    if blocks is NULL.  */
 
 static void
-clear_log_links (blocks)
-     sbitmap blocks;
+clear_log_links (sbitmap blocks)
 {
   rtx insn;
   int i;
@@ -4333,9 +4260,7 @@ clear_log_links (blocks)
    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;