OSDN Git Service

* c-common.c (shadow_warning): Delete.
[pf3gnuchains/gcc-fork.git] / gcc / flow.c
index 0d31076..a12f0ed 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, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -136,20 +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"
 
-/* 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.
-   No definition is equivalent to always zero.  */
-#ifndef EXIT_IGNORE_STACK
-#define EXIT_IGNORE_STACK 0
-#endif
-
 #ifndef HAVE_epilogue
 #define HAVE_epilogue 0
 #endif
@@ -160,9 +151,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define HAVE_sibcall_epilogue 0
 #endif
 
-#ifndef LOCAL_REGNO
-#define LOCAL_REGNO(REGNO)  0
-#endif
 #ifndef EPILOGUE_USES
 #define EPILOGUE_USES(REGNO)  0
 #endif
@@ -206,7 +194,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.  */
@@ -274,77 +262,81 @@ struct propagate_block_info
   /* 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;
+  /* Index of instruction being processed.  */
+  int insn_num;
 };
 
 /* Number of dead insns removed.  */
 static int ndead;
 
+/* When PROP_REG_INFO set, array contains pbi->insn_num of instruction
+   where given register died.  When the register is marked alive, we use the
+   information to compute amount of instructions life range cross.
+   (remember, we are walking backward).  This can be computed as current
+   pbi->insn_num - reg_deaths[regno].
+   At the end of processing each basic block, the remaining live registers
+   are inspected and liferanges are increased same way so liverange of global
+   registers are computed correctly.
+  
+   The array is maintained clear for dead registers, so it can be safely reused
+   for next basic block without expensive memset of the whole array after
+   reseting pbi->insn_num to 0.  */
+
+static int *reg_deaths;
+
 /* Maximum length of pbi->mem_set_list before we start dropping
    new elements on the floor.  */
 #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);
+static int count_or_remove_death_notes_bb (basic_block, int);
 \f
 
 void
-check_function_return_warnings ()
+check_function_return_warnings (void)
 {
   if (warn_missing_noreturn
       && !TREE_THIS_VOLATILE (cfun->decl)
@@ -388,13 +380,12 @@ 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;
 
   /* Get the first instruction in the block.  */
-  insn = block->head;
+  insn = BB_HEAD (block);
 
   if (insn == NULL_RTX)
     return NULL_RTX;
@@ -411,13 +402,10 @@ 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)
 {
-  int i;
 #ifdef ELIMINABLE_REGS
+  int i;
   static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
 #endif
 
@@ -436,8 +424,7 @@ life_analysis (f, file, flags)
 
 #ifdef CANNOT_CHANGE_MODE_CLASS
   if (flags & PROP_REG_INFO)
-    for (i=0; i < NUM_MACHINE_MODES; ++i)
-      INIT_REG_SET (&subregs_of_mode[i]);
+    bitmap_initialize (&subregs_of_mode, 1);
 #endif
 
   if (! optimize)
@@ -483,8 +470,16 @@ life_analysis (f, file, flags)
      is not immediately handy.  */
 
   if (flags & PROP_REG_INFO)
-    memset (regs_ever_live, 0, sizeof (regs_ever_live));
+    {
+      memset (regs_ever_live, 0, sizeof (regs_ever_live));
+      memset (regs_asm_clobbered, 0, sizeof (regs_asm_clobbered));
+    }
   update_life_info (NULL, UPDATE_LIFE_GLOBAL, flags);
+  if (reg_deaths)
+    {
+      free (reg_deaths);
+      reg_deaths = NULL;
+    }
 
   /* Clean up.  */
   if (optimize && (flags & PROP_SCAN_DEAD_STORES))
@@ -495,7 +490,7 @@ life_analysis (f, file, flags)
 
   free_basic_block_vars (1);
 
-  /* Removing dead insns should've made jumptables really dead.  */
+  /* Removing dead insns should have made jumptables really dead.  */
   delete_dead_jumptables ();
 }
 
@@ -504,9 +499,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;
@@ -524,11 +517,9 @@ 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;
+  rtx head = BB_HEAD (bb), end = BB_END (bb);
 
   while (1)
     {
@@ -548,7 +539,7 @@ verify_wide_reg (regno, bb)
   if (rtl_dump_file)
     {
       fprintf (rtl_dump_file, "Register %d died unexpectedly.\n", regno);
-      dump_bb (bb, rtl_dump_file);
+      dump_bb (bb, rtl_dump_file, 0);
     }
   abort ();
 }
@@ -557,9 +548,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)
     {
@@ -574,7 +563,7 @@ verify_local_live_at_start (new_live_at_start, bb)
                       bb->index);
              debug_bitmap_file (rtl_dump_file, new_live_at_start);
              fputs ("Old:\n", rtl_dump_file);
-             dump_bb (bb, rtl_dump_file);
+             dump_bb (bb, rtl_dump_file, 0);
            }
          abort ();
        }
@@ -595,7 +584,7 @@ verify_local_live_at_start (new_live_at_start, bb)
                {
                  fprintf (rtl_dump_file,
                           "Register %d died unexpectedly.\n", i);
-                 dump_bb (bb, rtl_dump_file);
+                 dump_bb (bb, rtl_dump_file, 0);
                }
              abort ();
            }
@@ -609,7 +598,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.
@@ -620,14 +609,14 @@ 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;
@@ -638,6 +627,9 @@ update_life_info (blocks, extent, prop_flags)
   tmp = INITIALIZE_REG_SET (tmp_head);
   ndead = 0;
 
+  if ((prop_flags & PROP_REG_INFO) && !reg_deaths)
+    reg_deaths = xcalloc (sizeof (*reg_deaths), max_regno);
+
   timevar_push ((extent == UPDATE_LIFE_LOCAL || blocks)
                ? TV_LIFE_UPDATE : TV_LIFE);
 
@@ -690,6 +682,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.  */
@@ -757,6 +759,11 @@ update_life_info (blocks, extent, prop_flags)
                                     }
                                 });
     }
+  if (reg_deaths)
+    {
+      free (reg_deaths);
+      reg_deaths = NULL;
+    }
   timevar_pop ((extent == UPDATE_LIFE_LOCAL || blocks)
               ? TV_LIFE_UPDATE : TV_LIFE);
   if (ndead && rtl_dump_file)
@@ -767,9 +774,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;
@@ -809,8 +814,7 @@ update_life_info_in_dirty_blocks (extent, prop_flags)
    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)
     {
@@ -832,8 +836,7 @@ 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;
@@ -841,7 +844,7 @@ delete_noop_moves (f)
 
   FOR_EACH_BB (bb)
     {
-      for (insn = bb->head; insn != NEXT_INSN (bb->end); insn = next)
+      for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb)); insn = next)
        {
          next = NEXT_INSN (insn);
          if (INSN_P (insn) && noop_move_p (insn))
@@ -878,7 +881,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)
@@ -903,10 +906,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
@@ -919,8 +920,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;
 
@@ -947,9 +947,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);
@@ -960,7 +958,7 @@ mark_reg (reg, xset)
   SET_REGNO_REG_SET (set, regno);
   if (regno < FIRST_PSEUDO_REGISTER)
     {
-      int n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
+      int n = hard_regno_nregs[regno][GET_MODE (reg)];
       while (--n > 0)
        SET_REGNO_REG_SET (set, regno + n);
     }
@@ -970,14 +968,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
@@ -1005,7 +1002,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
@@ -1017,7 +1014,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++)
@@ -1038,7 +1035,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;
@@ -1047,7 +1044,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;
@@ -1060,22 +1057,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.
@@ -1083,9 +1064,7 @@ 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, invalidated_by_call;
@@ -1113,7 +1092,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
   /* 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;
 
@@ -1234,19 +1213,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);
@@ -1397,9 +1368,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;
@@ -1444,7 +1413,7 @@ find_regno_partial (ptr, data)
    bits we don't want.  */
 
 int
-initialize_uninitialized_subregs ()
+initialize_uninitialized_subregs (void)
 {
   rtx insn;
   edge e;
@@ -1475,8 +1444,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;
                }
@@ -1496,7 +1468,7 @@ 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;
 
@@ -1510,11 +1482,14 @@ allocate_bb_life_data ()
 }
 
 void
-allocate_reg_life_data ()
+allocate_reg_life_data (void)
 {
   int i;
 
   max_regno = max_reg_num ();
+  if (reg_deaths)
+    abort ();
+  reg_deaths = xcalloc (sizeof (*reg_deaths), max_regno);
 
   /* Recalculate the register space, in case it has grown.  Old style
      vector oriented regsets would set regset_{size,bytes} here also.  */
@@ -1537,8 +1512,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);
 
@@ -1587,8 +1561,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);
@@ -1601,9 +1574,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;
@@ -1661,23 +1632,23 @@ propagate_one_insn (pbi, insn)
           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     
+          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. 
+          REG_RETVAL note, but it hardly seems worth the effort.
 
           NOTE at this point will be the RETVAL note if it exists.  */
          if (note)
            {
              rtx libcall_note;
-        
+
              libcall_note
                = find_reg_note (XEXP (note, 0), REG_LIBCALL, NULL_RTX);
              remove_note (XEXP (note, 0), libcall_note);
            }
 
          /* Similarly if INSN contains a LIBCALL note, remove the
-            dnagling REG_RETVAL note.  */
+            dangling REG_RETVAL note.  */
          note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
          if (note)
            {
@@ -1759,8 +1730,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)
@@ -1785,9 +1758,19 @@ 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, regno_reg_rtx[i], cond, insn,
@@ -1823,15 +1806,19 @@ 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.  */
+         if ((flags & PROP_REG_INFO)
+             && !REGNO_REG_SET_P (pbi->reg_live, STACK_POINTER_REGNUM))
+           reg_deaths[STACK_POINTER_REGNUM] = pbi->insn_num;
          SET_REGNO_REG_SET (pbi->reg_live, STACK_POINTER_REGNUM);
 
          /* Calls may also reference any of the global registers,
@@ -1842,11 +1829,7 @@ propagate_one_insn (pbi, insn)
        }
     }
 
-  /* On final pass, update counts of how many insns in which each reg
-     is live.  */
-  if (flags & PROP_REG_INFO)
-    EXECUTE_IF_SET_IN_REG_SET (pbi->reg_live, 0, i,
-                              { REG_LIVE_LENGTH (i)++; });
+  pbi->insn_num++;
 
   return prev;
 }
@@ -1856,10 +1839,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));
 
@@ -1871,9 +1852,10 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
   pbi->cond_local_set = cond_local_set;
   pbi->cc0_live = 0;
   pbi->flags = flags;
+  pbi->insn_num = 0;
 
   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;
 
@@ -1884,16 +1866,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 (GET_CODE (bb->end) == JUMP_INSN
-      && any_condjump_p (bb->end))
+  /* 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 (bb)) == JUMP_INSN
+      && any_condjump_p (BB_END (bb)))
     {
       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.  */
@@ -1914,60 +1895,66 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
       else
        {
          /* This can happen with a conditional jump to the next insn.  */
-         if (JUMP_LABEL (bb->end) != bb_true->head)
+         if (JUMP_LABEL (BB_END (bb)) != BB_HEAD (bb_true))
            abort ();
 
          /* Simplest way to do nothing.  */
          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 (bb)));
+         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);
@@ -1989,7 +1976,7 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
              && ! current_function_calls_eh_return)))
     {
       rtx insn, set;
-      for (insn = bb->end; insn != bb->head; insn = PREV_INSN (insn))
+      for (insn = BB_END (bb); insn != BB_HEAD (bb); insn = PREV_INSN (insn))
        if (GET_CODE (insn) == INSN
            && (set = single_set (insn))
            && GET_CODE (SET_DEST (set)) == MEM)
@@ -1997,13 +1984,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
@@ -2018,8 +1998,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);
 
@@ -2030,6 +2009,16 @@ free_propagate_block_info (pbi)
   BITMAP_XFREE (pbi->reg_cond_reg);
 #endif
 
+  if (pbi->flags & PROP_REG_INFO)
+    {
+      int num = pbi->insn_num;
+      int i;
+
+      EXECUTE_IF_SET_IN_REG_SET (pbi->reg_live, 0, i,
+        { REG_LIVE_LENGTH (i) += num - reg_deaths[i];
+          reg_deaths[i] = 0;
+         });
+    }
   if (pbi->reg_next_use)
     free (pbi->reg_next_use);
 
@@ -2055,12 +2044,8 @@ free_propagate_block_info (pbi)
    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;
@@ -2081,7 +2066,7 @@ propagate_block (bb, live, local_set, cond_local_set, flags)
   /* Scan the block an insn at a time from end to beginning.  */
 
   changed = 0;
-  for (insn = bb->end;; insn = prev)
+  for (insn = BB_END (bb); ; insn = prev)
     {
       /* If this is a call to `setjmp' et al, warn if any
         non-volatile datum is live.  */
@@ -2091,9 +2076,12 @@ 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)
+      if (insn == BB_HEAD (bb))
        break;
     }
 
@@ -2112,11 +2100,8 @@ propagate_block (bb, live, local_set, cond_local_set, flags)
    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);
 
@@ -2180,7 +2165,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);
 
@@ -2221,7 +2206,7 @@ insn_dead_p (pbi, x, call_ok, notes)
                 words are not needed.  */
              if (regno < FIRST_PSEUDO_REGISTER)
                {
-                 int n = HARD_REGNO_NREGS (regno, GET_MODE (r));
+                 int n = hard_regno_nregs[regno][GET_MODE (r)];
 
                  while (--n > 0)
                    if (REGNO_REG_SET_P (pbi->reg_live, regno+n))
@@ -2309,10 +2294,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);
 
@@ -2366,8 +2348,7 @@ libcall_dead_p (pbi, note, insn)
    fixed hard registers.  */
 
 int
-regno_uninitialized (regno)
-     unsigned int regno;
+regno_uninitialized (unsigned int regno)
 {
   if (n_basic_blocks == 0
       || (regno < FIRST_PSEUDO_REGISTER
@@ -2376,7 +2357,7 @@ regno_uninitialized (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
@@ -2384,23 +2365,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 (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;
 
@@ -2447,9 +2425,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;
@@ -2466,9 +2442,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;
@@ -2501,13 +2475,12 @@ 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;
   enum rtx_code code;
+  int flags = pbi->flags;
 
   if (insn)
     for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
@@ -2516,14 +2489,17 @@ mark_set_regs (pbi, x, insn)
          mark_set_1 (pbi, SET, XEXP (link, 0),
                      (GET_CODE (x) == COND_EXEC
                       ? COND_EXEC_TEST (x) : NULL_RTX),
-                     insn, pbi->flags);
+                     insn, flags);
       }
  retry:
   switch (code = GET_CODE (x))
     {
     case SET:
+      if (GET_CODE (XEXP (x, 1)) == ASM_OPERANDS)
+       flags |= PROP_ASM_SCAN;
+      /* Fall through */
     case CLOBBER:
-      mark_set_1 (pbi, code, SET_DEST (x), cond, insn, pbi->flags);
+      mark_set_1 (pbi, code, SET_DEST (x), cond, insn, flags);
       return;
 
     case COND_EXEC:
@@ -2535,7 +2511,9 @@ mark_set_regs (pbi, x, insn)
       {
        int i;
 
-       for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
+       /* We must scan forwards.  If we have an asm, we need to set
+          the PROP_ASM_SCAN flag before scanning the clobbers.  */
+       for (i = 0; i < XVECLEN (x, 0); i++)
          {
            rtx sub = XVECEXP (x, 0, i);
            switch (code = GET_CODE (sub))
@@ -2546,13 +2524,24 @@ mark_set_regs (pbi, x, insn)
 
                cond = COND_EXEC_TEST (sub);
                sub = COND_EXEC_CODE (sub);
-               if (GET_CODE (sub) != SET && GET_CODE (sub) != CLOBBER)
-                 break;
-               /* Fall through.  */
+               if (GET_CODE (sub) == SET)
+                 goto mark_set;
+               if (GET_CODE (sub) == CLOBBER)
+                 goto mark_clob;
+               break;
 
              case SET:
+             mark_set:
+               if (GET_CODE (XEXP (sub, 1)) == ASM_OPERANDS)
+                 flags |= PROP_ASM_SCAN;
+               /* Fall through */
              case CLOBBER:
-               mark_set_1 (pbi, code, SET_DEST (sub), cond, insn, pbi->flags);
+             mark_clob:
+               mark_set_1 (pbi, code, SET_DEST (sub), cond, insn, flags);
+               break;
+
+             case ASM_OPERANDS:
+               flags |= PROP_ASM_SCAN;
                break;
 
              default:
@@ -2574,11 +2563,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;
@@ -2618,7 +2603,7 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
     case REG:
       regno_last = regno_first = REGNO (reg);
       if (regno_first < FIRST_PSEUDO_REGISTER)
-       regno_last += HARD_REGNO_NREGS (regno_first, GET_MODE (reg)) - 1;
+       regno_last += hard_regno_nregs[regno_first][GET_MODE (reg)] - 1;
       break;
 
     case SUBREG:
@@ -2637,7 +2622,7 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
                                                  SUBREG_BYTE (reg),
                                                  outer_mode);
              regno_last = (regno_first
-                           + HARD_REGNO_NREGS (regno_first, outer_mode) - 1);
+                           + hard_regno_nregs[regno_first][outer_mode] - 1);
 
              /* Since we've just adjusted the register number ranges, make
                 sure REG matches.  Otherwise some_was_live will be clear
@@ -2780,6 +2765,9 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
                {
                  for (i = regno_first; i <= regno_last; i++)
                    regs_ever_live[i] = 1;
+                 if (flags & PROP_ASM_SCAN)
+                   for (i = regno_first; i <= regno_last; i++)
+                     regs_asm_clobbered[i] = 1;
                }
              else
                {
@@ -2858,13 +2846,29 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
        {
          for (i = regno_first; i <= regno_last; ++i)
            if (!(not_dead & (((unsigned long) 1) << (i - regno_first))))
-             CLEAR_REGNO_REG_SET (pbi->reg_live, i);
+             {
+               if ((pbi->flags & PROP_REG_INFO)
+                   && REGNO_REG_SET_P (pbi->reg_live, i))
+                 {
+                   REG_LIVE_LENGTH (i) += pbi->insn_num - reg_deaths[i];
+                   reg_deaths[i] = 0;
+                 }
+               CLEAR_REGNO_REG_SET (pbi->reg_live, i);
+             }
        }
     }
   else if (GET_CODE (reg) == REG)
     {
       if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
        pbi->reg_next_use[regno_first] = 0;
+
+      if ((flags & PROP_REG_INFO) != 0
+         && (flags & PROP_ASM_SCAN) != 0
+         &&  regno_first < FIRST_PSEUDO_REGISTER)
+       {
+         for (i = regno_first; i <= regno_last; i++)
+           regs_asm_clobbered[i] = 1;
+       }
     }
 
   /* If this is the last pass and this is a SCRATCH, show it will be dying
@@ -2882,10 +2886,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
@@ -2915,7 +2916,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;
@@ -2968,8 +2969,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);
@@ -2978,9 +2978,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;
@@ -3012,9 +3010,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];
 
@@ -3037,9 +3033,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;
 
@@ -3127,8 +3121,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;
 
@@ -3152,9 +3145,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;
 
@@ -3247,9 +3238,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;
 
@@ -3313,9 +3302,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);
@@ -3374,8 +3362,8 @@ attempt_auto_inc (pbi, inc, insn, mem, incr, incr_reg)
         new insn(s) and do the updates.  */
       emit_insn_before (insns, insn);
 
-      if (pbi->bb->head == insn)
-       pbi->bb->head = insns;
+      if (BB_HEAD (pbi->bb) == insn)
+       BB_HEAD (pbi->bb) = insns;
 
       /* INCR will become a NOTE and INSN won't contain a
         use of INCR_REG.  If a use of INCR_REG was just placed in
@@ -3391,6 +3379,10 @@ attempt_auto_inc (pbi, inc, insn, mem, incr, incr_reg)
       incr_reg = q;
       regno = REGNO (q);
 
+      if ((pbi->flags & PROP_REG_INFO)
+         && !REGNO_REG_SET_P (pbi->reg_live, regno))
+       reg_deaths[regno] = pbi->insn_num;
+
       /* REGNO is now used in INCR which is below INSN, but
         it previously wasn't live here.  If we don't mark
         it as live, we'll put a REG_DEAD note for it
@@ -3432,7 +3424,17 @@ attempt_auto_inc (pbi, inc, insn, mem, incr, incr_reg)
        {
          remove_note (incr, note);
          if (XEXP (note, 0) != incr_reg)
-           CLEAR_REGNO_REG_SET (pbi->reg_live, REGNO (XEXP (note, 0)));
+           {
+             unsigned int regno = REGNO (XEXP (note, 0));
+
+             if ((pbi->flags & PROP_REG_INFO)
+                 && REGNO_REG_SET_P (pbi->reg_live, regno))
+               {
+                 REG_LIVE_LENGTH (regno) += pbi->insn_num - reg_deaths[regno];
+                 reg_deaths[regno] = 0;
+               }
+             CLEAR_REGNO_REG_SET (pbi->reg_live, REGNO (XEXP (note, 0)));
+           }
        }
 
       PUT_CODE (incr, NOTE);
@@ -3457,10 +3459,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;
@@ -3549,18 +3548,15 @@ 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;
 
   regno_last = regno_first = REGNO (reg);
   if (regno_first < FIRST_PSEUDO_REGISTER)
-    regno_last += HARD_REGNO_NREGS (regno_first, GET_MODE (reg)) - 1;
+    regno_last += hard_regno_nregs[regno_first][GET_MODE (reg)] - 1;
 
   /* Find out if any of this register is live after this instruction.  */
   some_was_live = some_was_dead = 0;
@@ -3619,6 +3615,15 @@ mark_used_reg (pbi, reg, cond, insn)
          REG_FREQ (regno_first) += REG_FREQ_FROM_BB (pbi->bb);
          REG_N_REFS (regno_first)++;
        }
+      for (i = regno_first; i <= regno_last; ++i)
+       if (! REGNO_REG_SET_P (pbi->reg_live, i))
+         {
+#ifdef ENABLE_CHECKING
+           if (reg_deaths[i])
+             abort ();
+#endif
+           reg_deaths[i] = pbi->insn_num;
+         }
     }
 
   /* Record and count the insns in which a reg dies.  If it is used in
@@ -3711,7 +3716,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;
@@ -3741,9 +3746,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;
@@ -3799,7 +3802,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)
@@ -3830,10 +3833,12 @@ mark_used_regs (pbi, x, cond, insn)
 
     case SUBREG:
 #ifdef CANNOT_CHANGE_MODE_CLASS
-      if (GET_CODE (SUBREG_REG (x)) == REG
+      if ((flags & PROP_REG_INFO)
+         && GET_CODE (SUBREG_REG (x)) == REG
          && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER)
-       SET_REGNO_REG_SET (&subregs_of_mode[GET_MODE (x)],
-                          REGNO (SUBREG_REG (x)));
+       bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (x))
+                                         * MAX_MACHINE_MODE
+                                         + GET_MODE (x));
 #endif
 
       /* While we're here, optimize this case.  */
@@ -3878,11 +3883,13 @@ mark_used_regs (pbi, x, cond, insn)
               || GET_CODE (testreg) == SUBREG)
          {
 #ifdef CANNOT_CHANGE_MODE_CLASS
-           if (GET_CODE (testreg) == SUBREG
+           if ((flags & PROP_REG_INFO)
+               && GET_CODE (testreg) == SUBREG
                && GET_CODE (SUBREG_REG (testreg)) == REG
                && REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER)
-             SET_REGNO_REG_SET (&subregs_of_mode[GET_MODE (testreg)],
-                                REGNO (SUBREG_REG (testreg)));
+             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
@@ -3975,14 +3982,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;
     }
@@ -4018,9 +4017,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.  */
@@ -4066,9 +4063,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;
 
@@ -4146,10 +4141,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);
@@ -4208,9 +4200,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)
@@ -4228,13 +4218,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);
@@ -4260,9 +4249,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);
@@ -4273,76 +4260,103 @@ 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;
+  int i;
   basic_block bb;
 
-  FOR_EACH_BB_REVERSE (bb)
+  
+  /* This used to be a loop over all the blocks with a membership test
+     inside the loop.  That can be amazingly expensive on a large CFG
+     when only a small number of bits are set in BLOCKs (for example,
+     the calls from the scheduler typically have very few bits set).
+
+     For extra credit, someone should convert BLOCKS to a bitmap rather
+     than an sbitmap.  */
+  if (blocks)
     {
-      rtx insn;
+      EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i,
+       {
+         count += count_or_remove_death_notes_bb (BASIC_BLOCK (i), kill);
+       });
+    }
+  else
+    {
+      FOR_EACH_BB (bb)
+       {
+         count += count_or_remove_death_notes_bb (bb, kill);
+       }
+    }
 
-      if (blocks && ! TEST_BIT (blocks, bb->index))
-       continue;
+  return count;
+}
+  
+/* Optionally removes all the REG_DEAD and REG_UNUSED notes from basic
+   block BB.  Returns a count of the number of registers that died.  */
+
+static int
+count_or_remove_death_notes_bb (basic_block bb, int kill)
+{
+  int count = 0;
+  rtx insn;
 
-      for (insn = bb->head;; insn = NEXT_INSN (insn))
+  for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
+    {
+      if (INSN_P (insn))
        {
-         if (INSN_P (insn))
-           {
-             rtx *pprev = &REG_NOTES (insn);
-             rtx link = *pprev;
+         rtx *pprev = &REG_NOTES (insn);
+         rtx link = *pprev;
 
-             while (link)
+         while (link)
+           {
+             switch (REG_NOTE_KIND (link))
                {
-                 switch (REG_NOTE_KIND (link))
+               case REG_DEAD:
+                 if (GET_CODE (XEXP (link, 0)) == REG)
                    {
-                   case REG_DEAD:
-                     if (GET_CODE (XEXP (link, 0)) == REG)
-                       {
-                         rtx reg = XEXP (link, 0);
-                         int n;
-
-                         if (REGNO (reg) >= FIRST_PSEUDO_REGISTER)
-                           n = 1;
-                         else
-                           n = HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg));
-                         count += n;
-                       }
-                     /* Fall through.  */
-
-                   case REG_UNUSED:
-                     if (kill)
-                       {
-                         rtx next = XEXP (link, 1);
-                         free_EXPR_LIST_node (link);
-                         *pprev = link = next;
-                         break;
-                       }
-                     /* Fall through.  */
-
-                   default:
-                     pprev = &XEXP (link, 1);
-                     link = *pprev;
+                     rtx reg = XEXP (link, 0);
+                     int n;
+
+                     if (REGNO (reg) >= FIRST_PSEUDO_REGISTER)
+                       n = 1;
+                     else
+                       n = hard_regno_nregs[REGNO (reg)][GET_MODE (reg)];
+                     count += n;
+                   }
+
+                 /* Fall through.  */
+
+               case REG_UNUSED:
+                 if (kill)
+                   {
+                     rtx next = XEXP (link, 1);
+                     free_EXPR_LIST_node (link);
+                     *pprev = link = next;
                      break;
                    }
+                 /* Fall through.  */
+
+               default:
+                 pprev = &XEXP (link, 1);
+                 link = *pprev;
+                 break;
                }
            }
-
-         if (insn == bb->end)
-           break;
        }
+
+      if (insn == BB_END (bb))
+       break;
     }
 
   return count;
 }
+
 /* Clear LOG_LINKS fields of insns in a selected blocks or whole chain
    if blocks is NULL.  */
 
 static void
-clear_log_links (blocks)
-     sbitmap blocks;
+clear_log_links (sbitmap blocks)
 {
   rtx insn;
   int i;
@@ -4358,7 +4372,7 @@ clear_log_links (blocks)
       {
        basic_block bb = BASIC_BLOCK (i);
 
-       for (insn = bb->head; insn != NEXT_INSN (bb->end);
+       for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
             insn = NEXT_INSN (insn))
          if (INSN_P (insn))
            free_INSN_LIST_list (&LOG_LINKS (insn));
@@ -4371,9 +4385,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;