OSDN Git Service

* gcc.texi: Fixes for makeinfo 4.0 --html.
[pf3gnuchains/gcc-fork.git] / gcc / flow.c
index ea38623..131d88b 100644 (file)
@@ -221,10 +221,6 @@ int max_regno;
 
 varray_type reg_n_info;
 
-/* Size of the reg_n_info table.  */
-
-unsigned int reg_n_max;
-
 /* Size of a regset for the current function,
    in (1) bytes and (2) elements.  */
 
@@ -268,6 +264,9 @@ struct propagate_block_info
   /* Bit N is set if register N is conditionally or unconditionally live.  */
   regset reg_live;
 
+  /* Bit N is set if register N is set this insn.  */
+  regset new_set;
+
   /* Element N is the next insn that uses (hard or pseudo) register N
      within the current basic block; or zero, if there is no such insn.  */
   rtx *reg_next_use;
@@ -304,7 +303,6 @@ static void commit_one_edge_insertion       PARAMS ((edge));
 static void delete_unreachable_blocks  PARAMS ((void));
 static void delete_eh_regions          PARAMS ((void));
 static int can_delete_note_p           PARAMS ((rtx));
-static int delete_block                        PARAMS ((basic_block));
 static void expunge_block              PARAMS ((basic_block));
 static int can_delete_label_p          PARAMS ((rtx));
 static int merge_blocks_move_predecessor_nojumps PARAMS ((basic_block,
@@ -328,19 +326,15 @@ static int set_phi_alternative_reg      PARAMS ((rtx, int, int, void *));
 static void calculate_global_regs_live PARAMS ((sbitmap, sbitmap, int));
 static void propagate_block_delete_insn PARAMS ((basic_block, rtx));
 static rtx propagate_block_delete_libcall PARAMS ((basic_block, rtx, rtx));
-static void propagate_block            PARAMS ((basic_block, regset,
-                                                regset, int));
 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, rtx));
 static void mark_set_regs              PARAMS ((struct propagate_block_info *,
-                                                regset, rtx, rtx));
+                                                rtx, rtx));
 static void mark_set_1                 PARAMS ((struct propagate_block_info *,
-                                                regset, rtx, rtx, rtx));
-static int mark_set_reg                        PARAMS ((struct propagate_block_info *,
-                                                regset, rtx, rtx,
-                                                int *, int *));
+                                                enum rtx_code, rtx, rtx,
+                                                rtx, int));
 #ifdef AUTO_INC_DEC
 static void find_auto_inc              PARAMS ((struct propagate_block_info *,
                                                 rtx, rtx));
@@ -349,16 +343,13 @@ static int try_pre_increment_1            PARAMS ((struct propagate_block_info *,
 static int try_pre_increment           PARAMS ((rtx, rtx, HOST_WIDE_INT));
 #endif
 static void mark_used_reg              PARAMS ((struct propagate_block_info *,
-                                                regset, rtx, rtx, rtx));
+                                                rtx, rtx, rtx));
 static void mark_used_regs             PARAMS ((struct propagate_block_info *,
-                                                regset, rtx, rtx, rtx));
+                                                rtx, rtx, rtx));
 void dump_flow_info                    PARAMS ((FILE *));
 void debug_flow_info                   PARAMS ((void));
 static void dump_edge_info             PARAMS ((FILE *, edge, int));
 
-static void count_reg_sets_1           PARAMS ((rtx, int));
-static void count_reg_sets             PARAMS ((rtx, int));
-static void count_reg_references       PARAMS ((rtx, int));
 static void invalidate_mems_from_autoinc PARAMS ((struct propagate_block_info *,
                                                  rtx));
 static void remove_fake_successors     PARAMS ((basic_block));
@@ -457,7 +448,6 @@ count_basic_blocks (f)
   register int count = 0;
   int eh_region = 0;
   int call_had_abnormal_edge = 0;
-  rtx prev_call = NULL_RTX;
 
   prev_code = JUMP_INSN;
   for (insn = f; insn; insn = NEXT_INSN (insn))
@@ -469,33 +459,26 @@ count_basic_blocks (f)
              && (prev_code == JUMP_INSN
                  || prev_code == BARRIER
                  || (prev_code == CALL_INSN && call_had_abnormal_edge))))
-       {
-         count++;
-       }
+       count++;
 
       /* Record whether this call created an edge.  */
       if (code == CALL_INSN)
        {
          rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
          int region = (note ? INTVAL (XEXP (note, 0)) : 1);
-         prev_call = insn;
+
          call_had_abnormal_edge = 0;
 
          /* If there is an EH region or rethrow, we have an edge.  */
          if ((eh_region && region > 0)
              || find_reg_note (insn, REG_EH_RETHROW, NULL_RTX))
            call_had_abnormal_edge = 1;
-         else
-           {
-             /* If there is a nonlocal goto label and the specified
-                region number isn't -1, we have an edge. (0 means
-                no throw, but might have a nonlocal goto).  */
-             if (nonlocal_goto_handler_labels && region >= 0)
-               call_had_abnormal_edge = 1;
-           }
+         else if (nonlocal_goto_handler_labels && region >= 0)
+           /* If there is a nonlocal goto label and the specified
+              region number isn't -1, we have an edge. (0 means
+              no throw, but might have a nonlocal goto).  */
+           call_had_abnormal_edge = 1;
        }
-      else if (code != NOTE)
-       prev_call = NULL_RTX;
 
       if (code != NOTE)
        prev_code = code;
@@ -503,7 +486,6 @@ count_basic_blocks (f)
        ++eh_region;
       else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
        --eh_region;
-
     }
 
   /* The rest of the compiler works a bit smoother when we don't have to
@@ -527,7 +509,6 @@ find_basic_blocks_1 (f)
      rtx f;
 {
   register rtx insn, next;
-  int call_has_abnormal_edge = 0;
   int i = 0;
   rtx bb_note = NULL_RTX;
   rtx eh_list = NULL_RTX;
@@ -547,27 +528,6 @@ find_basic_blocks_1 (f)
 
       next = NEXT_INSN (insn);
 
-      if (code == CALL_INSN)
-       {
-         /* Record whether this call created an edge.  */
-         rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
-         int region = (note ? INTVAL (XEXP (note, 0)) : 1);
-         call_has_abnormal_edge = 0;
-
-         /* If there is an EH region or rethrow, we have an edge.  */
-         if ((eh_list && region > 0)
-             || find_reg_note (insn, REG_EH_RETHROW, NULL_RTX))
-           call_has_abnormal_edge = 1;
-         else
-           {
-             /* If there is a nonlocal goto label and the specified
-                region number isn't -1, we have an edge. (0 means
-                no throw, but might have a nonlocal goto).  */
-             if (nonlocal_goto_handler_labels && region >= 0)
-               call_has_abnormal_edge = 1;
-           }
-       }
-
       switch (code)
        {
        case NOTE:
@@ -580,6 +540,7 @@ find_basic_blocks_1 (f)
            else if (kind == NOTE_INSN_EH_REGION_END)
              {
                rtx t = eh_list;
+
                eh_list = XEXP (eh_list, 1);
                free_INSN_LIST_node (t);
              }
@@ -592,9 +553,9 @@ find_basic_blocks_1 (f)
              {
                if (bb_note == NULL_RTX)
                  bb_note = insn;
+
                next = flow_delete_insn (insn);
              }
-
            break;
          }
 
@@ -608,8 +569,7 @@ find_basic_blocks_1 (f)
                 does not imply an abnormal edge, it will be a bit before
                 everything can be updated.  So continue to emit a noop at
                 the end of such a block.  */
-             if (GET_CODE (end) == CALL_INSN
-                 && ! SIBLING_CALL_P (end))
+             if (GET_CODE (end) == CALL_INSN && ! SIBLING_CALL_P (end))
                {
                  rtx nop = gen_rtx_USE (VOIDmode, const0_rtx);
                  end = emit_insn_after (nop, end);
@@ -618,6 +578,7 @@ find_basic_blocks_1 (f)
              create_basic_block (i++, head, end, bb_note);
              bb_note = NULL_RTX;
            }
+
          head = end = insn;
          break;
 
@@ -661,8 +622,7 @@ find_basic_blocks_1 (f)
             imply an abnormal edge, it will be a bit before everything can
             be updated.  So continue to emit a noop at the end of such a
             block.  */
-         if (GET_CODE (end) == CALL_INSN
-             && ! SIBLING_CALL_P (end))
+         if (GET_CODE (end) == CALL_INSN && ! SIBLING_CALL_P (end))
            {
              rtx nop = gen_rtx_USE (VOIDmode, const0_rtx);
              end = emit_insn_after (nop, end);
@@ -670,20 +630,37 @@ find_basic_blocks_1 (f)
          goto new_bb_exclusive;
 
        case CALL_INSN:
-         /* A basic block ends at a call that can either throw or
-            do a non-local goto.  */
-         if (call_has_abnormal_edge)
-           {
-           new_bb_inclusive:
-             if (head == NULL_RTX)
-               head = insn;
-             end = insn;
+         {
+           /* Record whether this call created an edge.  */
+           rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+           int region = (note ? INTVAL (XEXP (note, 0)) : 1);
+           int call_has_abnormal_edge = 0;
+
+           /* If there is an EH region or rethrow, we have an edge.  */
+           if ((eh_list && region > 0)
+               || find_reg_note (insn, REG_EH_RETHROW, NULL_RTX))
+             call_has_abnormal_edge = 1;
+           else if (nonlocal_goto_handler_labels && region >= 0)
+             /* If there is a nonlocal goto label and the specified
+                region number isn't -1, we have an edge. (0 means
+                no throw, but might have a nonlocal goto).  */
+             call_has_abnormal_edge = 1;
 
-           new_bb_exclusive:
-             create_basic_block (i++, head, end, bb_note);
-             head = end = NULL_RTX;
-             bb_note = NULL_RTX;
-             break;
+           /* A basic block ends at a call that can either throw or
+              do a non-local goto.  */
+           if (call_has_abnormal_edge)
+             {
+             new_bb_inclusive:
+               if (head == NULL_RTX)
+                 head = insn;
+               end = insn;
+
+             new_bb_exclusive:
+               create_basic_block (i++, head, end, bb_note);
+               head = end = NULL_RTX;
+               bb_note = NULL_RTX;
+               break;
+             }
            }
          /* FALLTHRU */
 
@@ -713,10 +690,10 @@ find_basic_blocks_1 (f)
          for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
            if (REG_NOTE_KIND (note) == REG_LABEL)
              {
-               rtx lab = XEXP (note, 0), next;
+               rtx lab = XEXP (note, 0), next;
 
                if (lab == eh_return_stub_label)
-                 ;
+                   ;
                else if ((next = next_nonnote_insn (lab)) != NULL
                         && GET_CODE (next) == JUMP_INSN
                         && (GET_CODE (PATTERN (next)) == ADDR_VEC
@@ -1762,7 +1739,7 @@ delete_unreachable_blocks ()
     }
 
   /* Delete all unreachable basic blocks.  Count down so that we don't
-     interfere with the block renumbering that happens in delete_block.  */
+     interfere with the block renumbering that happens in flow_delete_block. */
 
   deleted_handler = 0;
 
@@ -1774,7 +1751,7 @@ delete_unreachable_blocks ()
        /* This block was found.  Tidy up the mark.  */
        b->aux = NULL;
       else
-       deleted_handler |= delete_block (b);
+       deleted_handler |= flow_delete_block (b);
     }
 
   tidy_fallthru_edges ();
@@ -1862,8 +1839,8 @@ flow_delete_insn_chain (start, finish)
 /* ??? Preserving all such notes strikes me as wrong.  It would be nice
    to post-process the stream to remove empty blocks, loops, ranges, etc.  */
 
-static int
-delete_block (b)
+int
+flow_delete_block (b)
      basic_block b;
 {
   int deleted_handler = 0;
@@ -2424,7 +2401,9 @@ tidy_fallthru_edge (e, b, c)
      If block B consisted only of this single jump, turn it into a deleted
      note.  */
   q = b->end;
-  if (GET_CODE (q) == JUMP_INSN)
+  if (GET_CODE (q) == JUMP_INSN
+      && (simplejump_p (q)
+         || (b->succ == e && e->succ_next == NULL)))
     {
 #ifdef HAVE_cc0
       /* If this was a conditional jump, we need to also delete
@@ -2486,51 +2465,22 @@ tidy_fallthru_edges ()
        tidy_fallthru_edge (s, b, c);
     }
 }
-
-/* Discover and record the loop depth at the head of each basic block.  */
-
-void
-calculate_loop_depth (dump)
-     FILE *dump;
-{
-  struct loops loops;
-
-  /* The loop infrastructure does the real job for us.  */
-  flow_loops_find (&loops);
-
-  if (dump)
-    flow_loops_dump (&loops, dump, 0);
-
-  flow_loops_free (&loops);
-}
 \f
 /* Perform data flow analysis.
-   F is the first insn of the function and NREGS the number of register numbers
-   in use.  */
+   F is the first insn of the function; FLAGS is a set of PROP_* flags
+   to be used in accumulating flow info.  */
 
 void
-life_analysis (f, nregs, file, remove_dead_code)
+life_analysis (f, file, flags)
      rtx f;
-     int nregs;
      FILE *file;
-     int remove_dead_code;
+     int flags;
 {
 #ifdef ELIMINABLE_REGS
   register int i;
   static struct {int from, to; } eliminables[] = ELIMINABLE_REGS;
 #endif
-  int flags;
-  sbitmap all_blocks;
-
-  /* Dead code elimination changes basic block structure and therefore
-     breaks the SSA phi representation.  Particularly, a phi node
-     can have an alternative value for each incoming block, referenced
-     by the block number.  Removing dead code can bump entire blocks
-     and therefore cause blocks to be renumbered, invalidating the
-     numbering of phi alternatives.  */
-  if (remove_dead_code && in_ssa_form)
-    abort ();
+
   /* Record which registers will be eliminated.  We use this in
      mark_used_regs.  */
 
@@ -2543,17 +2493,8 @@ life_analysis (f, nregs, file, remove_dead_code)
   SET_HARD_REG_BIT (elim_reg_set, FRAME_POINTER_REGNUM);
 #endif
 
-  /* We want alias analysis information for local dead store elimination.  */
-  init_alias_analysis ();
-
   if (! optimize)
-    flags = PROP_DEATH_NOTES | PROP_REG_INFO;
-  else
-    {
-      flags = PROP_FINAL;
-      if (! remove_dead_code)
-       flags &= ~(PROP_SCAN_DEAD_CODE | PROP_KILL_DEAD_CODE);
-    }
+    flags &= PROP_DEATH_NOTES | PROP_REG_INFO;
 
   /* The post-reload life analysis have (on a global basis) the same
      registers live as was computed by reload itself.  elimination
@@ -2564,7 +2505,9 @@ life_analysis (f, nregs, file, remove_dead_code)
   if (reload_completed)
     flags &= ~PROP_REG_INFO;
 
-  max_regno = nregs;
+  /* We want alias analysis information for local dead store elimination.  */
+  if (flags & PROP_SCAN_DEAD_CODE)
+    init_alias_analysis ();
 
   /* Always remove no-op moves.  Do this before other processing so
      that we don't have to keep re-scanning them.  */
@@ -2580,8 +2523,6 @@ life_analysis (f, nregs, file, remove_dead_code)
      data from lifetime analysis.  */
   allocate_reg_life_data ();
   allocate_bb_life_data ();
-  all_blocks = sbitmap_alloc (n_basic_blocks);
-  sbitmap_ones (all_blocks);
 
   /* Find the set of registers live on function exit.  */
   mark_regs_live_at_end (EXIT_BLOCK_PTR->global_live_at_start);
@@ -2592,11 +2533,11 @@ life_analysis (f, nregs, file, remove_dead_code)
 
   if (flags & PROP_REG_INFO)
     memset (regs_ever_live, 0, sizeof(regs_ever_live));
-  update_life_info (all_blocks, UPDATE_LIFE_GLOBAL, flags);
+  update_life_info (NULL, UPDATE_LIFE_GLOBAL, flags);
 
   /* Clean up.  */
-  sbitmap_free (all_blocks);
-  end_alias_analysis ();
+  if (flags & PROP_SCAN_DEAD_CODE)
+    end_alias_analysis ();
 
   if (file)
     dump_flow_info (file);
@@ -2680,10 +2621,11 @@ 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 LOCAL_ONLY, such as after splitting or peepholeing, 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
+   If EXTENT is UPDATE_LIFE_LOCAL, such as after splitting or peepholeing,
+   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.
    If we find registers removed from live_at_start, that means we have
    a broken peephole that is killing a register it shouldn't.
@@ -2692,8 +2634,6 @@ 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.
 
-   BLOCK_FOR_INSN is assumed to be correct.
-
    Including PROP_REG_INFO does not properly refresh regs_ever_live
    unless the caller resets it to zero.  */
 
@@ -2720,16 +2660,32 @@ update_life_info (blocks, extent, prop_flags)
        count_or_remove_death_notes (blocks, 1);
     }
 
-  EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i,
+  if (blocks)
     {
-      basic_block bb = BASIC_BLOCK (i);
+      EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i,
+       {
+         basic_block bb = BASIC_BLOCK (i);
 
-      COPY_REG_SET (tmp, bb->global_live_at_end);
-      propagate_block (bb, tmp, (regset) NULL, prop_flags);
+         COPY_REG_SET (tmp, bb->global_live_at_end);
+         propagate_block (bb, tmp, (regset) NULL, prop_flags);
 
-      if (extent == UPDATE_LIFE_LOCAL)
-       verify_local_live_at_start (tmp, bb);
-    });
+         if (extent == UPDATE_LIFE_LOCAL)
+           verify_local_live_at_start (tmp, bb);
+       });
+    }
+  else
+    {
+      for (i = n_basic_blocks - 1; i >= 0; --i)
+       {
+         basic_block bb = BASIC_BLOCK (i);
+
+         COPY_REG_SET (tmp, bb->global_live_at_end);
+         propagate_block (bb, tmp, (regset) NULL, prop_flags);
+
+         if (extent == UPDATE_LIFE_LOCAL)
+           verify_local_live_at_start (tmp, bb);
+       }
+    }
 
   FREE_REG_SET (tmp);
 
@@ -3018,6 +2974,8 @@ set_phi_alternative_reg (insn, dest_regno, src_regno, data)
 
 /* 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.
+
    BLOCKS_OUT is set for every block that was changed.  */
 
 static void
@@ -3048,14 +3006,27 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
   /* 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.  */
-  EXECUTE_IF_SET_IN_SBITMAP (blocks_in, 0, i,
+  if (blocks_in)
     {
-      basic_block bb = BASIC_BLOCK (i);
-      *--qhead = bb;
-      bb->aux = bb;
-    });
+      EXECUTE_IF_SET_IN_SBITMAP (blocks_in, 0, i,
+       {
+         basic_block bb = BASIC_BLOCK (i);
+         *--qhead = bb;
+         bb->aux = bb;
+       });
+    }
+  else
+    {
+      for (i = 0; i < n_basic_blocks; ++i)
+       {
+         basic_block bb = BASIC_BLOCK (i);
+         *--qhead = bb;
+         bb->aux = bb;
+       }
+    }
 
-  sbitmap_zero (blocks_out);
+  if (blocks_out)
+    sbitmap_zero (blocks_out);
 
   while (qhead != qtail)
     {
@@ -3076,11 +3047,15 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
          IOR_REG_SET (new_live_at_end, sb->global_live_at_start);
        }
 
+      /* Force the stack pointer to be live -- which might not already be 
+        the case for blocks within infinite loops.  */
+      SET_REGNO_REG_SET (new_live_at_end, STACK_POINTER_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.  */
-      for_each_successor_phi (bb->index, &set_phi_alternative_reg, 
+      for_each_successor_phi (bb, &set_phi_alternative_reg, 
                              new_live_at_end);
 
       if (bb == ENTRY_BLOCK_PTR)
@@ -3128,7 +3103,8 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
 
       /* Let our caller know that BB changed enough to require its
         death notes updated.  */
-      SET_BIT (blocks_out, bb->index);
+      if (blocks_out)
+       SET_BIT (blocks_out, bb->index);
 
       if (! rescan)
        {
@@ -3178,11 +3154,22 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
   FREE_REG_SET (tmp);
   FREE_REG_SET (new_live_at_end);
 
-  EXECUTE_IF_SET_IN_SBITMAP (blocks_out, 0, i,
+  if (blocks_out)
     {
-      basic_block bb = BASIC_BLOCK (i);
-      FREE_REG_SET (bb->local_set);
-    });
+      EXECUTE_IF_SET_IN_SBITMAP (blocks_out, 0, i,
+       {
+         basic_block bb = BASIC_BLOCK (i);
+         FREE_REG_SET (bb->local_set);
+       });
+    }
+  else
+    {
+      for (i = n_basic_blocks - 1; i >= 0; --i)
+       {
+         basic_block bb = BASIC_BLOCK (i);
+         FREE_REG_SET (bb->local_set);
+       }
+    }
 
   free (queue);
 }
@@ -3218,6 +3205,8 @@ allocate_reg_life_data ()
 {
   int i;
 
+  max_regno = max_reg_num ();
+
   /* Recalculate the register space, in case it has grown.  Old style
      vector oriented regsets would set regset_{size,bytes} here also.  */
   allocate_reg_info (max_regno, FALSE, FALSE);
@@ -3295,337 +3284,348 @@ propagate_block_delete_libcall (bb, insn, note)
   return before;
 }
 
-/* Compute the registers live at the beginning of a basic block BB from
-   those live at the end.
-
-   When called, REG_LIVE contains those live at the end.  On return, it
-   contains those live at the beginning.
-
-   LOCAL_SET, if non-null, will be set with all registers killed by 
-   this basic block.  */
+/* Update the life-status of regs for one insn.  Return the previous insn.  */
 
-static void
-propagate_block (bb, live, local_set, flags)
-     basic_block bb;
-     regset live;
-     regset local_set;
-     int flags;
+rtx
+propagate_one_insn (pbi, insn)
+     struct propagate_block_info *pbi;
+     rtx insn;
 {
-  struct propagate_block_info pbi;
-  rtx insn, prev;
-  regset_head tmp_head;
-  regset tmp;
-  
-  pbi.bb = bb;
-  pbi.reg_live = live;
-  pbi.mem_set_list = NULL_RTX;
-  pbi.local_set = local_set;
-  pbi.cc0_live = 0;
-  pbi.flags = flags;
-
-  if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
-    pbi.reg_next_use = (rtx *) xcalloc (max_reg_num (), sizeof (rtx));
-  else
-    pbi.reg_next_use = NULL;
+  rtx prev = PREV_INSN (insn);
+  int flags = pbi->flags;
+  int insn_is_dead = 0;
+  int libcall_is_dead = 0;
+  rtx note;
+  int i;
 
-  tmp = INITIALIZE_REG_SET (tmp_head);
+  if (! INSN_P (insn))
+    return prev;
 
-  if (flags & PROP_REG_INFO)
+  note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
+  if (flags & PROP_SCAN_DEAD_CODE)
     {
-      register int i;
-
-      /* Process the regs live at the end of the block.
-        Mark them as not local to any one basic block. */
-      EXECUTE_IF_SET_IN_REG_SET (live, 0, i,
-                                {
-                                  REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL;
-                                });
+      insn_is_dead = insn_dead_p (pbi, PATTERN (insn), 0,
+                                 REG_NOTES (insn));
+      libcall_is_dead = (insn_is_dead && note != 0
+                        && libcall_dead_p (pbi, PATTERN (insn),
+                                           note, insn));
+    }
+
+  /* We almost certainly don't want to delete prologue or epilogue
+     instructions.  Warn about probable compiler losage.  */
+  if (insn_is_dead
+      && reload_completed
+      && (((HAVE_epilogue || HAVE_prologue)
+          && prologue_epilogue_contains (insn))
+         || (HAVE_sibcall_epilogue
+             && sibcall_epilogue_contains (insn))))
+    {
+      if (flags & PROP_KILL_DEAD_CODE)
+       { 
+         warning ("ICE: would have deleted prologue/epilogue insn");
+         if (!inhibit_warnings)
+           debug_rtx (insn);
+       }
+      libcall_is_dead = insn_is_dead = 0;
     }
 
-  /* Scan the block an insn at a time from end to beginning.  */
-
-  for (insn = bb->end; ; insn = prev)
+  /* If an instruction consists of just dead store(s) on final pass,
+     delete it.  */
+  if ((flags & PROP_KILL_DEAD_CODE) && insn_is_dead)
     {
-      prev = PREV_INSN (insn);
-
-      if (GET_CODE (insn) == NOTE)
+      if (libcall_is_dead)
        {
-         /* If this is a call to `setjmp' et al,
-            warn if any non-volatile datum is live.  */
-
-         if ((flags & PROP_REG_INFO)
-             && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
-           IOR_REG_SET (regs_live_at_setjmp, pbi.reg_live);
+         prev = propagate_block_delete_libcall (pbi->bb, insn, note);
+         insn = NEXT_INSN (prev);
        }
+      else
+       propagate_block_delete_insn (pbi->bb, insn);
 
-      /* Update the life-status of regs for this insn.
-        First DEAD gets which regs are set in this insn
-        then LIVE gets which regs are used in this insn.
-        Then the regs live before the insn
-        are those live after, with DEAD regs turned off,
-        and then LIVE regs turned on.  */
-
-      else if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
-       {
-         register int i;
-         rtx note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
-         int insn_is_dead = 0;
-         int libcall_is_dead = 0;
-
-         if (flags & PROP_SCAN_DEAD_CODE)
-           {
-             insn_is_dead = insn_dead_p (&pbi, PATTERN (insn), 0,
-                                         REG_NOTES (insn));
-             libcall_is_dead = (insn_is_dead && note != 0
-                                && libcall_dead_p (&pbi, PATTERN (insn),
-                                                   note, insn));
-           }
-
-         /* We almost certainly don't want to delete prologue or epilogue
-            instructions.  Warn about probable compiler losage.  */
-         if (insn_is_dead
-             && reload_completed
-             && (((HAVE_epilogue || HAVE_prologue)
-                  && prologue_epilogue_contains (insn))
-                 || (HAVE_sibcall_epilogue
-                     && sibcall_epilogue_contains (insn))))
-           {
-             if (flags & PROP_KILL_DEAD_CODE)
-               { 
-                 warning ("ICE: would have deleted prologue/epilogue insn");
-                 if (!inhibit_warnings)
-                   debug_rtx (insn);
-               }
-             libcall_is_dead = insn_is_dead = 0;
-           }
-
-         /* If an instruction consists of just dead store(s) on final pass,
-            delete it.  */
-         if ((flags & PROP_KILL_DEAD_CODE) && insn_is_dead)
-           {
-             if (libcall_is_dead)
-               {
-                 prev = propagate_block_delete_libcall (bb, insn, note);
-                 insn = NEXT_INSN (prev);
-               }
-             else
-               propagate_block_delete_insn (bb, insn);
-
-             /* CC0 is now known to be dead.  Either this insn used it,
-                in which case it doesn't anymore, or clobbered it,
-                so the next insn can't use it.  */
-             pbi.cc0_live = 0;
+      /* CC0 is now known to be dead.  Either this insn used it,
+        in which case it doesn't anymore, or clobbered it,
+        so the next insn can't use it.  */
+      pbi->cc0_live = 0;
 
-             goto flushed;
-           }
+      return prev;
+    }
 
-         /* See if this is an increment or decrement that can be
-            merged into a following memory address.  */
+  /* See if this is an increment or decrement that can be merged into
+     a following memory address.  */
 #ifdef AUTO_INC_DEC
-         {
-           register rtx x = single_set (insn);
-
-           /* Does this instruction increment or decrement a register?  */
-           if (!reload_completed
-               && (flags & PROP_AUTOINC)
-               && x != 0
-               && GET_CODE (SET_DEST (x)) == REG
-               && (GET_CODE (SET_SRC (x)) == PLUS
-                   || GET_CODE (SET_SRC (x)) == MINUS)
-               && XEXP (SET_SRC (x), 0) == SET_DEST (x)
-               && GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT
-               /* Ok, look for a following memory ref we can combine with.
-                  If one is found, change the memory ref to a PRE_INC
-                  or PRE_DEC, cancel this insn, and return 1.
-                  Return 0 if nothing has been done.  */
-               && try_pre_increment_1 (&pbi, insn))
-             goto flushed;
-         }
+  {
+    register rtx x = single_set (insn);
+
+    /* Does this instruction increment or decrement a register?  */
+    if (!reload_completed
+       && (flags & PROP_AUTOINC)
+       && x != 0
+       && GET_CODE (SET_DEST (x)) == REG
+       && (GET_CODE (SET_SRC (x)) == PLUS
+           || GET_CODE (SET_SRC (x)) == MINUS)
+       && XEXP (SET_SRC (x), 0) == SET_DEST (x)
+       && GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT
+       /* Ok, look for a following memory ref we can combine with.
+          If one is found, change the memory ref to a PRE_INC
+          or PRE_DEC, cancel this insn, and return 1.
+          Return 0 if nothing has been done.  */
+       && try_pre_increment_1 (pbi, insn))
+      return prev;
+  }
 #endif /* AUTO_INC_DEC */
 
-         CLEAR_REG_SET (tmp);
+  CLEAR_REG_SET (pbi->new_set);
+
+  /* If this is not the final pass, and this insn is copying the value of
+     a library call and it's dead, don't scan the insns that perform the
+     library call, so that the call's arguments are not marked live.  */
+  if (libcall_is_dead)
+    {
+      /* Record the death of the dest reg.  */
+      mark_set_regs (pbi, PATTERN (insn), insn);
+
+      insn = XEXP (note, 0);
+      return PREV_INSN (insn);
+    }
+  else if (GET_CODE (PATTERN (insn)) == SET
+          && SET_DEST (PATTERN (insn)) == stack_pointer_rtx
+          && GET_CODE (SET_SRC (PATTERN (insn))) == PLUS
+          && XEXP (SET_SRC (PATTERN (insn)), 0) == stack_pointer_rtx
+          && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == CONST_INT)
+    /* We have an insn to pop a constant amount off the stack.
+       (Such insns use PLUS regardless of the direction of the stack,
+       and any insn to adjust the stack by a constant is always a pop.)
+       These insns, if not dead stores, have no effect on life.  */
+    ;
+  else
+    {
+      /* Any regs live at the time of a call instruction must not go
+        in a register clobbered by calls.  Find all regs now live and
+        record this for them.  */
 
-         /* If this is not the final pass, and this insn is copying the
-            value of a library call and it's dead, don't scan the
-            insns that perform the library call, so that the call's
-            arguments are not marked live.  */
-         if (libcall_is_dead)
-           {
-             /* Record the death of the dest reg.  */
-             mark_set_regs (&pbi, tmp, PATTERN (insn), insn);
-             AND_COMPL_REG_SET (pbi.reg_live, tmp);
+      if (GET_CODE (insn) == CALL_INSN && (flags & PROP_REG_INFO))
+       EXECUTE_IF_SET_IN_REG_SET (pbi->reg_live, 0, i,
+                                  { REG_N_CALLS_CROSSED (i)++; });
 
-             insn = XEXP (note, 0);
-             prev = PREV_INSN (insn);
-           }
-         else if (GET_CODE (PATTERN (insn)) == SET
-                  && SET_DEST (PATTERN (insn)) == stack_pointer_rtx
-                  && GET_CODE (SET_SRC (PATTERN (insn))) == PLUS
-                  && XEXP (SET_SRC (PATTERN (insn)), 0) == stack_pointer_rtx
-                  && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == CONST_INT)
-           /* We have an insn to pop a constant amount off the stack.
-              (Such insns use PLUS regardless of the direction of the stack,
-              and any insn to adjust the stack by a constant is always a pop.)
-              These insns, if not dead stores, have no effect on life.  */
-           ;
-         else
-           {
-             /* Any regs live at the time of a call instruction
-                must not go in a register clobbered by calls.
-                Find all regs now live and record this for them.  */
-
-             if (GET_CODE (insn) == CALL_INSN
-                 && (flags & PROP_REG_INFO))
-               EXECUTE_IF_SET_IN_REG_SET (pbi.reg_live, 0, i,
-                                          { REG_N_CALLS_CROSSED (i)++; });
-
-             /* Record sets.  Do this even for dead instructions,
-                since they would have killed the values if they hadn't
-                been deleted.  */
-             mark_set_regs (&pbi, tmp, PATTERN (insn), insn);
-
-             /* Each call clobbers all call-clobbered regs that are not
-                global or fixed.  Note that the function-value reg is a
-                call-clobbered reg, and mark_set_regs has already had
-                a chance to handle it.  */
-             if (GET_CODE (insn) == CALL_INSN)
-               {
-                 register int i;
-                 rtx cond;
-
-                 cond = NULL_RTX;
-                 if (GET_CODE (PATTERN (insn)) == COND_EXEC)
-                   cond = COND_EXEC_TEST (PATTERN (insn));
-
-                 /* Non-constant calls clobber memory.  */
-                 if (! CONST_CALL_P (insn))
-                   free_EXPR_LIST_list (&pbi.mem_set_list);
-
-                 /* There may be extra registers to be clobbered.  */
-                 for (note = CALL_INSN_FUNCTION_USAGE (insn);
-                      note;
-                      note = XEXP (note, 1))
-                   if (GET_CODE (XEXP (note, 0)) == CLOBBER)
-                     mark_set_1 (&pbi, tmp, XEXP (XEXP (note, 0), 0),
-                                 cond, insn);
-
-                 /* Calls change all call-used and global registers.  */
-                 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-                   if (call_used_regs[i] && ! global_regs[i]
-                       && ! fixed_regs[i])
-                     {
-                       int dummy;
-                       mark_set_reg (&pbi, tmp,
-                                     gen_rtx_REG (reg_raw_mode[i], i),
-                                     cond, &dummy, &dummy);
-                     }
-               }
+      /* Record sets.  Do this even for dead instructions, since they
+        would have killed the values if they hadn't been deleted.  */
+      mark_set_regs (pbi, PATTERN (insn), insn);
 
-             /* Update live for the registers killed.  */
-             AND_COMPL_REG_SET (pbi.reg_live, tmp);
-             CLEAR_REG_SET (tmp);
+      if (GET_CODE (insn) == CALL_INSN)
+       {
+         register int i;
+         rtx note, cond;
+
+         cond = NULL_RTX;
+         if (GET_CODE (PATTERN (insn)) == COND_EXEC)
+           cond = COND_EXEC_TEST (PATTERN (insn));
+
+         /* Non-constant calls clobber memory.  */
+         if (! CONST_CALL_P (insn))
+           free_EXPR_LIST_list (&pbi->mem_set_list);
+
+         /* There may be extra registers to be clobbered.  */
+         for (note = CALL_INSN_FUNCTION_USAGE (insn);
+              note;
+              note = XEXP (note, 1))
+           if (GET_CODE (XEXP (note, 0)) == CLOBBER)
+             mark_set_1 (pbi, CLOBBER, XEXP (XEXP (note, 0), 0),
+                         cond, insn, pbi->flags);
+
+         /* Calls change all call-used and global registers.  */
+         for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+           if (call_used_regs[i] && ! global_regs[i]
+               && ! fixed_regs[i])
+             {
+               /* We do not want REG_UNUSED notes for these registers.  */
+               mark_set_1 (pbi, CLOBBER, gen_rtx_REG (reg_raw_mode[i], i),
+                           cond, insn, pbi->flags & ~PROP_DEATH_NOTES);
+             }
+       }
 
-             /* If an insn doesn't use CC0, it becomes dead since we 
-                assume that every insn clobbers it.  So show it dead here;
-                mark_used_regs will set it live if it is referenced.  */
-             pbi.cc0_live = 0;
+      /* If an insn doesn't use CC0, it becomes dead since we assume
+        that every insn clobbers it.  So show it dead here;
+        mark_used_regs will set it live if it is referenced.  */
+      pbi->cc0_live = 0;
 
-             /* Record uses.  */
-             if (! insn_is_dead)
-               mark_used_regs (&pbi, tmp, PATTERN (insn), NULL_RTX, insn);
+      /* Record uses.  */
+      if (! insn_is_dead)
+       mark_used_regs (pbi, PATTERN (insn), NULL_RTX, insn);
 
-             /* Sometimes we may have inserted something before INSN
-                (such as a move) when we make an auto-inc.  So ensure
-                we will scan those insns.  */
+      /* Sometimes we may have inserted something before INSN (such as a move)
+        when we make an auto-inc.  So ensure we will scan those insns.  */
 #ifdef AUTO_INC_DEC
-             prev = PREV_INSN (insn);
+      prev = PREV_INSN (insn);
 #endif
 
-             if (! insn_is_dead && GET_CODE (insn) == CALL_INSN)
-               {
-                 register int i;
-                 rtx note, cond;
-
-                 cond = NULL_RTX;
-                 if (GET_CODE (PATTERN (insn)) == COND_EXEC)
-                   cond = COND_EXEC_TEST (PATTERN (insn));
-
-                 for (note = CALL_INSN_FUNCTION_USAGE (insn);
-                      note;
-                      note = XEXP (note, 1))
-                   if (GET_CODE (XEXP (note, 0)) == USE)
-                     mark_used_regs (&pbi, tmp, XEXP (XEXP (note, 0), 0),
-                                     cond, insn);
-
-                 /* The stack ptr is used (honorarily) by a CALL insn.  */
-                 SET_REGNO_REG_SET (tmp, STACK_POINTER_REGNUM);
-
-                 /* Calls may also reference any of the global registers,
-                    so they are made live.  */
-                 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-                   if (global_regs[i])
-                     mark_used_reg (&pbi, tmp,
-                                    gen_rtx_REG (reg_raw_mode[i], i),
-                                    cond, insn);
-               }
+      if (! insn_is_dead && GET_CODE (insn) == CALL_INSN)
+       {
+         register int i;
+         rtx note, cond;
+
+         cond = NULL_RTX;
+         if (GET_CODE (PATTERN (insn)) == COND_EXEC)
+           cond = COND_EXEC_TEST (PATTERN (insn));
+
+         /* Calls use their arguments.  */
+         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);
 
-             /* Update live for the registers used.  */
-             IOR_REG_SET (pbi.reg_live, tmp);
-           }
+         /* The stack ptr is used (honorarily) by a CALL insn.  */
+         SET_REGNO_REG_SET (pbi->reg_live, STACK_POINTER_REGNUM);
 
-         /* 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)++; });
+         /* Calls may also reference any of the global registers,
+            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);
        }
-    flushed:
-      if (insn == bb->head)
-       break;
     }
 
-  FREE_REG_SET (tmp);
-  free_EXPR_LIST_list (&pbi.mem_set_list);
+  /* 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)++; });
 
-  if (pbi.reg_next_use)
-    free (pbi.reg_next_use);
+  return prev;
 }
 
-\f
-/* Return 1 if X (the body of an insn, or part of it) is just dead stores
-   (SET expressions whose destinations are registers dead after the insn).
-   NEEDED is the regset that says which regs are alive after the insn.
+/* Initialize a propagate_block_info struct for public consumption.
+   Note that the structure itself is opaque to this file, but that
+   the user can use the regsets provided here.  */
 
-   Unless CALL_OK is non-zero, an insn is needed if it contains a CALL.
+struct propagate_block_info *
+init_propagate_block_info (bb, live, local_set, flags)
+     basic_block bb;
+     regset live;
+     regset local_set;
+     int flags;
+{
+  struct propagate_block_info *pbi = xmalloc (sizeof(*pbi));
 
-   If X is the entire body of an insn, NOTES contains the reg notes
-   pertaining to the insn.  */
+  pbi->bb = bb;
+  pbi->reg_live = live;
+  pbi->mem_set_list = NULL_RTX;
+  pbi->local_set = local_set;
+  pbi->cc0_live = 0;
+  pbi->flags = flags;
 
-static int
-insn_dead_p (pbi, x, call_ok, notes)
+  if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
+    pbi->reg_next_use = (rtx *) xcalloc (max_reg_num (), sizeof (rtx));
+  else
+    pbi->reg_next_use = NULL;
+
+  pbi->new_set = BITMAP_XMALLOC ();
+
+  return pbi;
+}
+
+/* Release a propagate_block_info struct.  */
+
+void
+free_propagate_block_info (pbi)
      struct propagate_block_info *pbi;
-     rtx x;
-     int call_ok;
-     rtx notes ATTRIBUTE_UNUSED;
 {
-  enum rtx_code code = GET_CODE (x);
+  free_EXPR_LIST_list (&pbi->mem_set_list);
 
-#ifdef AUTO_INC_DEC
-  /* If flow is invoked after reload, we must take existing AUTO_INC
-     expresions into account.  */
-  if (reload_completed)
-    {
-      for ( ; notes; notes = XEXP (notes, 1))
-       {
-         if (REG_NOTE_KIND (notes) == REG_INC)
-           {
-             int regno = REGNO (XEXP (notes, 0));
+  BITMAP_XFREE (pbi->new_set);
 
-             /* Don't delete insns to set global regs.  */
-             if ((regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
-                 || REGNO_REG_SET_P (pbi->reg_live, regno))
-               return 0;
-           }
+  if (pbi->reg_next_use)
+    free (pbi->reg_next_use);
+
+  free (pbi);
+}
+
+/* Compute the registers live at the beginning of a basic block BB from
+   those live at the end.
+
+   When called, REG_LIVE contains those live at the end.  On return, it
+   contains those live at the beginning.
+
+   LOCAL_SET, if non-null, will be set with all registers killed by 
+   this basic block.  */
+
+void
+propagate_block (bb, live, local_set, flags)
+     basic_block bb;
+     regset live;
+     regset local_set;
+     int flags;
+{
+  struct propagate_block_info *pbi;
+  rtx insn, prev;
+  
+  pbi = init_propagate_block_info (bb, live, local_set, flags);
+
+  if (flags & PROP_REG_INFO)
+    {
+      register int i;
+
+      /* Process the regs live at the end of the block.
+        Mark them as not local to any one basic block. */
+      EXECUTE_IF_SET_IN_REG_SET (live, 0, i,
+                                { REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL; });
+    }
+
+  /* Scan the block an insn at a time from end to beginning.  */
+
+  for (insn = bb->end; ; insn = prev)
+    {
+      /* If this is a call to `setjmp' et al, warn if any
+        non-volatile datum is live.  */
+      if ((flags & PROP_REG_INFO)
+         && GET_CODE (insn) == NOTE
+         && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
+       IOR_REG_SET (regs_live_at_setjmp, pbi->reg_live);
+
+      prev = propagate_one_insn (pbi, insn);
+
+      if (insn == bb->head)
+       break;
+    }
+
+  free_propagate_block_info (pbi);
+}
+\f
+/* Return 1 if X (the body of an insn, or part of it) is just dead stores
+   (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.
+
+   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;
+{
+  enum rtx_code code = GET_CODE (x);
+
+#ifdef AUTO_INC_DEC
+  /* If flow is invoked after reload, we must take existing AUTO_INC
+     expresions into account.  */
+  if (reload_completed)
+    {
+      for ( ; notes; notes = XEXP (notes, 1))
+       {
+         if (REG_NOTE_KIND (notes) == REG_INC)
+           {
+             int regno = REGNO (XEXP (notes, 0));
+
+             /* Don't delete insns to set global regs.  */
+             if ((regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
+                 || REGNO_REG_SET_P (pbi->reg_live, regno))
+               return 0;
+           }
        }
     }
 #endif
@@ -3905,19 +3905,19 @@ invalidate_mems_from_autoinc (pbi, insn)
    FLAGS is the set of operations to perform.  */
 
 static void
-mark_set_regs (pbi, new_dead, x, insn)
+mark_set_regs (pbi, x, insn)
      struct propagate_block_info *pbi;
-     regset new_dead;
      rtx x, insn;
 {
   rtx cond = NULL_RTX;
+  enum rtx_code code;
 
  retry:
-  switch (GET_CODE (x))
+  switch (code = GET_CODE (x))
     {
     case SET:
     case CLOBBER:
-      mark_set_1 (pbi, new_dead, SET_DEST (x), cond, insn);
+      mark_set_1 (pbi, code, SET_DEST (x), cond, insn, pbi->flags);
       return;
 
     case COND_EXEC:
@@ -3931,7 +3931,7 @@ mark_set_regs (pbi, new_dead, x, insn)
        for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
          {
            rtx sub = XVECEXP (x, 0, i);
-           switch (GET_CODE (sub))
+           switch (code = GET_CODE (sub))
              {
              case COND_EXEC:
                if (cond != NULL_RTX)
@@ -3945,7 +3945,7 @@ mark_set_regs (pbi, new_dead, x, insn)
 
              case SET:
              case CLOBBER:
-               mark_set_1 (pbi, new_dead, SET_DEST (sub), cond, insn);
+               mark_set_1 (pbi, code, SET_DEST (sub), cond, insn, pbi->flags);
                break;
 
              default:
@@ -3963,13 +3963,15 @@ mark_set_regs (pbi, new_dead, x, insn)
 /* Process a single SET rtx, X.  */
 
 static void
-mark_set_1 (pbi, new_dead, reg, cond, insn)
+mark_set_1 (pbi, code, reg, cond, insn, flags)
      struct propagate_block_info *pbi;
-     regset new_dead;
+     enum rtx_code code;
      rtx reg, cond, insn;
+     int flags;
 {
-  register int regno = -1;
-  int flags = pbi->flags;
+  int regno_first = -1, regno_last = -1;
+  int not_dead = 0;
+  int i;
 
   /* Some targets place small structures in registers for
      return values of functions.  We have to detect this
@@ -3977,29 +3979,89 @@ mark_set_1 (pbi, new_dead, reg, cond, insn)
   if (GET_CODE (reg) == PARALLEL
       && GET_MODE (reg) == BLKmode)
     {
-      register int i;
-
       for (i = XVECLEN (reg, 0) - 1; i >= 0; i--)
-       mark_set_1 (pbi, new_dead, XVECEXP (reg, 0, i), cond, insn);
+       mark_set_1 (pbi, code, XVECEXP (reg, 0, i), cond, insn, flags);
       return;
     }
 
-  /* Modifying just one hardware register of a multi-reg value
-     or just a byte field of a register
-     does not mean the value from before this insn is now dead.
-     But it does mean liveness of that register at the end of the block
-     is significant.
+  /* Modifying just one hardware register of a multi-reg value or just a
+     byte field of a register does not mean the value from before this insn
+     is now dead.  Of course, if it was dead after it's unused now.  */
+
+  switch (GET_CODE (reg))
+    {
+    case ZERO_EXTRACT:
+    case SIGN_EXTRACT:
+    case STRICT_LOW_PART:
+      /* ??? Assumes STRICT_LOW_PART not used on multi-word registers.  */
+      do
+       reg = XEXP (reg, 0);
+      while (GET_CODE (reg) == SUBREG
+            || GET_CODE (reg) == ZERO_EXTRACT
+            || GET_CODE (reg) == SIGN_EXTRACT
+            || GET_CODE (reg) == STRICT_LOW_PART);
+      if (GET_CODE (reg) == MEM)
+       break;
+      not_dead = REGNO_REG_SET_P (pbi->reg_live, REGNO (reg));
+      /* FALLTHRU */
+
+    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;
+      break;
 
-     Within mark_set_1, however, we treat it as if the register is
-     indeed modified.  mark_used_regs will, however, also treat this
-     register as being used.  Thus, we treat these insns as setting a
-     new value for the register as a function of its old value.  This
-     cases LOG_LINKS to be made appropriately and this will help combine.  */
+    case SUBREG:
+      if (GET_CODE (SUBREG_REG (reg)) == REG)
+       {
+         enum machine_mode outer_mode = GET_MODE (reg);
+         enum machine_mode inner_mode = GET_MODE (SUBREG_REG (reg));
+
+         /* Identify the range of registers affected.  This is moderately
+            tricky for hard registers.  See alter_subreg.  */
+
+         regno_last = regno_first = REGNO (SUBREG_REG (reg));
+         if (regno_first < FIRST_PSEUDO_REGISTER)
+           {
+#ifdef ALTER_HARD_SUBREG
+             regno_first = ALTER_HARD_SUBREG (outer_mode, SUBREG_WORD (reg),
+                                              inner_mode, regno_first);
+#else
+             regno_first += SUBREG_WORD (reg);
+#endif
+             regno_last = (regno_first
+                           + 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
+                when it shouldn't have been, and we'll create incorrect
+                REG_UNUSED notes.  */
+             reg = gen_rtx_REG (outer_mode, regno_first);
+           }
+         else
+           {
+             /* If the number of words in the subreg is less than the number
+                of words in the full register, we have a well-defined partial
+                set.  Otherwise the high bits are undefined.
+
+                This is only really applicable to pseudos, since we just took
+                care of multi-word hard registers.  */
+             if (((GET_MODE_SIZE (outer_mode)
+                   + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+                 < ((GET_MODE_SIZE (inner_mode)
+                     + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+               not_dead = REGNO_REG_SET_P (pbi->reg_live, regno_first);
+
+             reg = SUBREG_REG (reg);
+           }
+       }
+      else
+       reg = SUBREG_REG (reg);
+      break;
 
-  while (GET_CODE (reg) == SUBREG || GET_CODE (reg) == ZERO_EXTRACT
-        || GET_CODE (reg) == SIGN_EXTRACT
-        || GET_CODE (reg) == STRICT_LOW_PART)
-    reg = XEXP (reg, 0);
+    default:
+      break;
+    }
 
   /* 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.  */
@@ -4050,24 +4112,30 @@ mark_set_1 (pbi, new_dead, reg, cond, insn)
     }
 
   if (GET_CODE (reg) == REG
-      && (regno = REGNO (reg),
-         ! (regno == FRAME_POINTER_REGNUM
-            && (! reload_completed || frame_pointer_needed)))
+      && ! (regno_first == FRAME_POINTER_REGNUM
+           && (! reload_completed || frame_pointer_needed))
 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
-      && ! (regno == HARD_FRAME_POINTER_REGNUM
+      && ! (regno_first == HARD_FRAME_POINTER_REGNUM
            && (! reload_completed || frame_pointer_needed))
 #endif
 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
-      && ! (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
+      && ! (regno_first == ARG_POINTER_REGNUM && fixed_regs[regno_first])
 #endif
       )
     {
-      int some_was_live, some_was_dead;
+      int some_was_live = 0, some_was_dead = 0;
 
-      /* Perform the pbi datastructure update.  */
-      if (! mark_set_reg (pbi, new_dead, reg, cond,
-                         &some_was_live, &some_was_dead))
-       return;
+      for (i = regno_first; i <= regno_last; ++i)
+       {
+         int needed_regno = REGNO_REG_SET_P (pbi->reg_live, i);
+         if (pbi->local_set)
+           SET_REGNO_REG_SET (pbi->local_set, i);
+         if (code != CLOBBER)
+           SET_REGNO_REG_SET (pbi->new_set, i);
+
+         some_was_live |= needed_regno;
+         some_was_dead |= ! needed_regno;
+       }
 
       /* Additional data to record if this is the final pass.  */
       if (flags & (PROP_LOG_LINKS | PROP_REG_INFO
@@ -4078,56 +4146,44 @@ mark_set_1 (pbi, new_dead, reg, cond, insn)
 
          y = NULL_RTX;
          if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
-           y = pbi->reg_next_use[regno];
-
-         /* If this is a hard reg, record this function uses the reg.  */
-
-         if (regno < FIRST_PSEUDO_REGISTER)
            {
-             register int i;
-             int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
-
-             if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
-               for (i = regno; i < endregno; i++)
-                 {
-                   /* The next use is no longer "next", since a store
-                      intervenes.  */
-                   pbi->reg_next_use[i] = 0;
-                 }
+             y = pbi->reg_next_use[regno_first];
 
-             if (flags & PROP_REG_INFO)
-               for (i = regno; i < endregno; i++)
-                 {
-                   regs_ever_live[i] = 1;
-                   REG_N_SETS (i)++;
-                 }
+             /* The next use is no longer next, since a store intervenes.  */
+             for (i = regno_first; i <= regno_last; ++i)
+               pbi->reg_next_use[i] = 0;
            }
-         else
-           {
-             /* The next use is no longer "next", since a store
-                intervenes.  */
-             if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
-               pbi->reg_next_use[regno] = 0;
 
-             /* Keep track of which basic blocks each reg appears in.  */
-
-             if (flags & PROP_REG_INFO)
+         if (flags & PROP_REG_INFO)
+           {
+             for (i = regno_first; i <= regno_last; ++i)
                {
-                 if (REG_BASIC_BLOCK (regno) == REG_BLOCK_UNKNOWN)
-                   REG_BASIC_BLOCK (regno) = blocknum;
-                 else if (REG_BASIC_BLOCK (regno) != blocknum)
-                   REG_BASIC_BLOCK (regno) = REG_BLOCK_GLOBAL;
-
-                 /* Count (weighted) references, stores, etc.  This counts a
+                 /* Count (weighted) references, stores, etc.  This counts a
                     register twice if it is modified, but that is correct.  */
-                 REG_N_SETS (regno)++;
-                 REG_N_REFS (regno) += pbi->bb->loop_depth + 1;
-                 
+                 REG_N_SETS (i) += 1;
+                 REG_N_REFS (i) += (optimize_size ? 1
+                                    : pbi->bb->loop_depth + 1);
+
                  /* The insns where a reg is live are normally counted
                     elsewhere, but we want the count to include the insn
                     where the reg is set, and the normal counting mechanism
                     would not count it.  */
-                 REG_LIVE_LENGTH (regno)++;
+                 REG_LIVE_LENGTH (i) += 1;
+               }
+
+             /* If this is a hard reg, record this function uses the reg.  */
+             if (regno_first < FIRST_PSEUDO_REGISTER)
+               {
+                 for (i = regno_first; i <= regno_last; i++)
+                   regs_ever_live[i] = 1;
+               }
+             else
+               {
+                 /* Keep track of which basic blocks each reg appears in.  */
+                 if (REG_BASIC_BLOCK (regno_first) == REG_BLOCK_UNKNOWN)
+                   REG_BASIC_BLOCK (regno_first) = blocknum;
+                 else if (REG_BASIC_BLOCK (regno_first) != blocknum)
+                   REG_BASIC_BLOCK (regno_first) = REG_BLOCK_GLOBAL;
                }
            }
 
@@ -4145,15 +4201,17 @@ mark_set_1 (pbi, new_dead, reg, cond, insn)
                     even if reload can make what appear to be valid
                     assignments later.  */
                  if (y && (BLOCK_NUM (y) == blocknum)
-                     && (regno >= FIRST_PSEUDO_REGISTER
+                     && (regno_first >= FIRST_PSEUDO_REGISTER
                          || asm_noperands (PATTERN (y)) < 0))
                    LOG_LINKS (y) = alloc_INSN_LIST (insn, LOG_LINKS (y));
                }
            }
+         else if (not_dead)
+           ;
          else if (! some_was_live)
            {
              if (flags & PROP_REG_INFO)
-               REG_N_DEATHS (REGNO (reg))++;
+               REG_N_DEATHS (regno_first) += 1;
 
              if (flags & PROP_DEATH_NOTES)
                {
@@ -4176,24 +4234,32 @@ mark_set_1 (pbi, new_dead, reg, cond, insn)
                     for those parts that were not needed.  This case should
                     be rare.  */
 
-                 int i;
-
-                 for (i = HARD_REGNO_NREGS (regno, GET_MODE (reg)) - 1;
-                      i >= 0; i--)
-                   if (! REGNO_REG_SET_P (pbi->reg_live, regno + i))
+                 for (i = regno_first; i <= regno_last; ++i)
+                   if (! REGNO_REG_SET_P (pbi->reg_live, i))
                      REG_NOTES (insn)
-                       = (alloc_EXPR_LIST
-                          (REG_UNUSED,
-                           gen_rtx_REG (reg_raw_mode[regno + i], regno + i),
-                           REG_NOTES (insn)));
+                       = alloc_EXPR_LIST (REG_UNUSED,
+                                          gen_rtx_REG (reg_raw_mode[i], i),
+                                          REG_NOTES (insn));
                }
            }
        }
+
+      /* Mark the register as being dead.  */
+      if (some_was_live
+         /* The stack pointer is never dead.  Well, not strictly true,
+            but it's very difficult to tell from here.  Hopefully
+            combine_stack_adjustments will fix up the most egregious
+            errors.  */
+         && regno_first != STACK_POINTER_REGNUM)
+       {
+         for (i = regno_first; i <= regno_last; ++i)
+           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] = 0;
+       pbi->reg_next_use[regno_first] = 0;
     }
 
   /* If this is the last pass and this is a SCRATCH, show it will be dying
@@ -4205,64 +4271,6 @@ mark_set_1 (pbi, new_dead, reg, cond, insn)
          = alloc_EXPR_LIST (REG_UNUSED, reg, REG_NOTES (insn));
     }
 }
-
-/* Update data structures for a (possibly conditional) store into REG.
-   Return true if REG is now unconditionally dead.  */
-
-static int
-mark_set_reg (pbi, new_dead, reg, cond, p_some_was_live, p_some_was_dead)
-     struct propagate_block_info *pbi;
-     regset new_dead;
-     rtx reg;
-     rtx cond ATTRIBUTE_UNUSED;
-     int *p_some_was_live, *p_some_was_dead;
-{
-  int regno = REGNO (reg);
-  int some_was_live = REGNO_REG_SET_P (pbi->reg_live, regno);
-  int some_was_dead = ! some_was_live;
-
-  /* Mark it as a significant register for this basic block.  */
-  if (pbi->local_set)
-    SET_REGNO_REG_SET (pbi->local_set, regno);
-
-  /* A hard reg in a wide mode may really be multiple registers.
-     If so, mark all of them just like the first.  */
-  if (regno < FIRST_PSEUDO_REGISTER)
-    {
-      int n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
-      while (--n > 0)
-       {
-         int regno_n = regno + n;
-         int needed_regno = REGNO_REG_SET_P (pbi->reg_live, regno_n);
-         if (pbi->local_set)
-           SET_REGNO_REG_SET (pbi->local_set, regno_n);
-
-         some_was_live |= needed_regno;
-         some_was_dead |= ! needed_regno;
-       }
-    }
-
-  *p_some_was_live = some_was_live;
-  *p_some_was_dead = some_was_dead;
-
-  /* The stack pointer is never dead.  Well, not strictly true, but it's
-     very difficult to tell from here.  Hopefully combine_stack_adjustments
-     will fix up the most egregious errors.  */
-  if (regno == STACK_POINTER_REGNUM)
-    return 0;
-
-  /* Mark it as dead before this insn.  */
-  SET_REGNO_REG_SET (new_dead, regno);
-  if (regno < FIRST_PSEUDO_REGISTER)
-    {
-      int n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
-      while (--n > 0)
-       SET_REGNO_REG_SET (new_dead, regno + n);
-    }
-
-  /* Unconditionally dead.  */
-  return 1;
-}
 \f
 #ifdef AUTO_INC_DEC
 
@@ -4321,7 +4329,10 @@ find_auto_inc (pbi, x, insn)
                                    ? (offset ? PRE_INC : POST_INC)
                                    : (offset ? PRE_DEC : POST_DEC));
 
-         if (dead_or_set_p (incr, addr))
+         if (dead_or_set_p (incr, addr)
+             /* Mustn't autoinc an eliminable register.  */
+             && (regno >= FIRST_PSEUDO_REGISTER
+                 || ! TEST_HARD_REG_BIT (elim_reg_set, regno)))
            {
              /* This is the simple case.  Try to make the auto-inc.  If
                 we can't, we are done.  Otherwise, we will do any
@@ -4346,16 +4357,15 @@ find_auto_inc (pbi, x, insn)
                 Change it to q = p, ...*q..., q = q+size.
                 Then fall into the usual case.  */
              rtx insns, temp;
-             basic_block bb;
 
              start_sequence ();
              emit_move_insn (q, addr);
              insns = get_insns ();
              end_sequence ();
 
-             bb = BLOCK_FOR_INSN (insn);
-             for (temp = insns; temp; temp = NEXT_INSN (temp))
-               set_block_for_insn (temp, bb);
+             if (basic_block_for_insn)
+               for (temp = insns; temp; temp = NEXT_INSN (temp))
+                 set_block_for_insn (temp, pbi->bb);
 
              /* If we can't make the auto-inc, or can't make the
                 replacement into Y, exit.  There's no point in making
@@ -4373,8 +4383,8 @@ find_auto_inc (pbi, x, insn)
                 new insn(s) and do the updates.  */
              emit_insns_before (insns, insn);
 
-             if (BLOCK_FOR_INSN (insn)->head == insn)
-               BLOCK_FOR_INSN (insn)->head = insns;
+             if (pbi->bb->head == insn)
+               pbi->bb->head = insns;
 
              /* INCR will become a NOTE and INSN won't contain a
                 use of ADDR.  If a use of ADDR was just placed in
@@ -4422,6 +4432,11 @@ find_auto_inc (pbi, x, insn)
             register.  */
          if (SET_DEST (set) == addr)
            {
+             /* If the original source was dead, it's dead now.  */
+             rtx note = find_reg_note (incr, REG_DEAD, NULL_RTX);
+             if (note && XEXP (note, 0) != addr)
+               CLEAR_REGNO_REG_SET (pbi->reg_live, REGNO (XEXP (note, 0)));
+             
              PUT_CODE (incr, NOTE);
              NOTE_LINE_NUMBER (incr) = NOTE_INSN_DELETED;
              NOTE_SOURCE_FILE (incr) = 0;
@@ -4444,9 +4459,8 @@ find_auto_inc (pbi, x, insn)
 #endif /* AUTO_INC_DEC */
 \f
 static void
-mark_used_reg (pbi, new_live, reg, cond, insn)
+mark_used_reg (pbi, reg, cond, insn)
      struct propagate_block_info *pbi;
-     regset new_live;
      rtx reg;
      rtx cond ATTRIBUTE_UNUSED;
      rtx insn;
@@ -4454,20 +4468,17 @@ mark_used_reg (pbi, new_live, reg, cond, insn)
   int regno = REGNO (reg);
   int some_was_live = REGNO_REG_SET_P (pbi->reg_live, regno);
   int some_was_dead = ! some_was_live;
-
-  SET_REGNO_REG_SET (new_live, regno);
+  int some_not_set;
+  int n;
 
   /* A hard reg in a wide mode may really be multiple registers.
      If so, mark all of them just like the first.  */
   if (regno < FIRST_PSEUDO_REGISTER)
     {
-      int n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
+      n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
       while (--n > 0)
        {
-         int regno_n = regno + n;
-         int needed_regno = REGNO_REG_SET_P (pbi->reg_live, regno_n);
-
-         SET_REGNO_REG_SET (new_live, regno_n);
+         int needed_regno = REGNO_REG_SET_P (pbi->reg_live, regno + n);
          some_was_live |= needed_regno;
          some_was_dead |= ! needed_regno;
        }
@@ -4492,12 +4503,15 @@ mark_used_reg (pbi, new_live, reg, cond, insn)
             be eliminated, reload will set it live at that point.
 
             Otherwise, record that this function uses this register.  */
+         /* ??? The PPC backend tries to "eliminate" on the pic
+            register to itself.  This should be fixed.  In the mean
+            time, hack around it.  */
 
-         if (! TEST_HARD_REG_BIT (elim_reg_set, regno))
+         if (! (TEST_HARD_REG_BIT (elim_reg_set, regno)
+                && (regno == FRAME_POINTER_REGNUM
+                    || regno == ARG_POINTER_REGNUM)))
            {
              int n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
-             if (n == 0)
-               n = 1;
              do
                regs_ever_live[regno + --n] = 1;
              while (n > 0);
@@ -4518,17 +4532,23 @@ mark_used_reg (pbi, new_live, reg, cond, insn)
        }
     }
 
+  /* Find out if any of the register was set this insn.  */
+  some_not_set = ! REGNO_REG_SET_P (pbi->new_set, regno);
+  if (regno < FIRST_PSEUDO_REGISTER)
+    {
+      n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
+      while (--n > 0)
+       some_not_set |= ! REGNO_REG_SET_P (pbi->new_set, regno + n);
+    }
+
   /* Record and count the insns in which a reg dies.  If it is used in
      this insn and was dead below the insn then it dies in this insn.
      If it was set in this insn, we do not make a REG_DEAD note;
      likewise if we already made such a note.  */
-
-  if ((pbi->flags & PROP_DEATH_NOTES)
+  if ((pbi->flags & (PROP_DEATH_NOTES | PROP_REG_INFO))
       && some_was_dead
-      && ! dead_or_set_p (insn, reg))
+      && some_not_set)
     {
-      int n;
-
       /* Check for the case where the register dying partially
         overlaps the register set by this insn.  */
       if (regno < FIRST_PSEUDO_REGISTER
@@ -4536,16 +4556,20 @@ mark_used_reg (pbi, new_live, reg, cond, insn)
        {
          n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
          while (--n >= 0)
-           some_was_live |= dead_or_set_regno_p (insn, regno + n);
+           some_was_live |= REGNO_REG_SET_P (pbi->new_set, regno + n);
        }
 
       /* If none of the words in X is needed, make a REG_DEAD note.
         Otherwise, we must make partial REG_DEAD notes.  */
       if (! some_was_live)
        {
-         REG_NOTES (insn)
-           = alloc_EXPR_LIST (REG_DEAD, reg, REG_NOTES (insn));
-         REG_N_DEATHS (regno)++;
+         if ((pbi->flags & PROP_DEATH_NOTES)
+             && ! find_regno_note (insn, REG_DEAD, regno))
+           REG_NOTES (insn)
+             = alloc_EXPR_LIST (REG_DEAD, reg, REG_NOTES (insn));
+
+         if (pbi->flags & PROP_REG_INFO)
+           REG_N_DEATHS (regno)++;
        }
       else
        {
@@ -4554,7 +4578,7 @@ mark_used_reg (pbi, new_live, reg, cond, insn)
 
          n = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg)) - 1;
          for (; n >= regno; n--)
-           if (!REGNO_REG_SET_P (pbi->reg_live, n)
+           if (! REGNO_REG_SET_P (pbi->reg_live, n)
                && ! dead_or_set_regno_p (insn, n))
              REG_NOTES (insn)
                = alloc_EXPR_LIST (REG_DEAD,
@@ -4562,6 +4586,14 @@ mark_used_reg (pbi, new_live, reg, cond, insn)
                                   REG_NOTES (insn));
        }
     }
+
+  SET_REGNO_REG_SET (pbi->reg_live, regno);
+  if (regno < FIRST_PSEUDO_REGISTER)
+    {
+      n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
+      while (--n > 0)
+       SET_REGNO_REG_SET (pbi->reg_live, regno + n);
+    }
 }
 
 /* Scan expression X and store a 1-bit in NEW_LIVE for each reg it uses.
@@ -4572,9 +4604,8 @@ mark_used_reg (pbi, new_live, reg, cond, insn)
    is not called.  */
 
 static void
-mark_used_regs (pbi, new_live, x, cond, insn)
+mark_used_regs (pbi, x, cond, insn)
      struct propagate_block_info *pbi;
-     regset new_live;
      rtx x, cond, insn;
 {
   register RTX_CODE code;
@@ -4605,7 +4636,7 @@ mark_used_regs (pbi, new_live, x, cond, insn)
       /* If we are clobbering a MEM, mark any registers inside the address
         as being used.  */
       if (GET_CODE (XEXP (x, 0)) == MEM)
-       mark_used_regs (pbi, new_live, XEXP (XEXP (x, 0), 0), cond, insn);
+       mark_used_regs (pbi, XEXP (XEXP (x, 0), 0), cond, insn);
       return;
 
     case MEM:
@@ -4670,7 +4701,7 @@ mark_used_regs (pbi, new_live, x, cond, insn)
 
     case REG:
       /* See a register other than being set => mark it as needed.  */
-      mark_used_reg (pbi, new_live, x, cond, insn);
+      mark_used_reg (pbi, x, cond, insn);
       return;
 
     case SET:
@@ -4686,8 +4717,8 @@ mark_used_regs (pbi, new_live, x, cond, insn)
            if (flags & PROP_AUTOINC)
              find_auto_inc (pbi, testreg, insn);
 #endif
-           mark_used_regs (pbi, new_live, XEXP (testreg, 0), cond, insn);
-           mark_used_regs (pbi, new_live, SET_SRC (x), cond, insn);
+           mark_used_regs (pbi, XEXP (testreg, 0), cond, insn);
+           mark_used_regs (pbi, SET_SRC (x), cond, insn);
            return;
          }
            
@@ -4739,12 +4770,10 @@ mark_used_regs (pbi, new_live, x, cond, insn)
                && ! (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
 #endif
                ))
-         /* We used to exclude global_regs here, but that seems wrong.
-            Storing in them is like storing in mem.  */
          {
-           mark_used_regs (pbi, new_live, SET_SRC (x), cond, insn);
            if (mark_dest)
-             mark_used_regs (pbi, new_live, SET_DEST (x), cond, insn);
+             mark_used_regs (pbi, SET_DEST (x), cond, insn);
+           mark_used_regs (pbi, SET_SRC (x), cond, insn);
            return;
          }
       }
@@ -4781,8 +4810,7 @@ mark_used_regs (pbi, new_live, x, cond, insn)
            int j;
 
            for (j = 0; j < ASM_OPERANDS_INPUT_LENGTH (x); j++)
-             mark_used_regs (pbi, new_live, ASM_OPERANDS_INPUT (x, j),
-                             cond, insn);
+             mark_used_regs (pbi, ASM_OPERANDS_INPUT (x, j), cond, insn);
          }
        break;
       }
@@ -4791,7 +4819,7 @@ mark_used_regs (pbi, new_live, x, cond, insn)
       if (cond != NULL_RTX)
        abort ();
 
-      mark_used_regs (pbi, new_live, COND_EXEC_TEST (x), NULL_RTX, insn);
+      mark_used_regs (pbi, COND_EXEC_TEST (x), NULL_RTX, insn);
 
       cond = COND_EXEC_TEST (x);
       x = COND_EXEC_CODE (x);
@@ -4825,13 +4853,13 @@ mark_used_regs (pbi, new_live, x, cond, insn)
                x = XEXP (x, 0);
                goto retry;
              }
-           mark_used_regs (pbi, new_live, XEXP (x, i), cond, insn);
+           mark_used_regs (pbi, XEXP (x, i), cond, insn);
          }
        else if (fmt[i] == 'E')
          {
            register int j;
            for (j = 0; j < XVECLEN (x, i); j++)
-             mark_used_regs (pbi, new_live, XVECEXP (x, i, j), cond, insn);
+             mark_used_regs (pbi, XVECEXP (x, i, j), cond, insn);
          }
       }
   }
@@ -5555,208 +5583,6 @@ compute_immediate_dominators (idom, dominators)
   sbitmap_vector_free (tmp);
 }
 
-/* Count for a single SET rtx, X.  */
-
-static void
-count_reg_sets_1 (x, loop_depth)
-     rtx x;
-     int loop_depth;
-{
-  register int regno;
-  register rtx reg = SET_DEST (x);
-
-  /* Find the register that's set/clobbered.  */
-  while (GET_CODE (reg) == SUBREG || GET_CODE (reg) == ZERO_EXTRACT
-        || GET_CODE (reg) == SIGN_EXTRACT
-        || GET_CODE (reg) == STRICT_LOW_PART)
-    reg = XEXP (reg, 0);
-
-  if (GET_CODE (reg) == PARALLEL
-      && GET_MODE (reg) == BLKmode)
-    {
-      register int i;
-      for (i = XVECLEN (reg, 0) - 1; i >= 0; i--)
-       count_reg_sets_1 (XVECEXP (reg, 0, i), loop_depth);
-      return;
-    }
-
-  if (GET_CODE (reg) == REG)
-    {
-      regno = REGNO (reg);
-      if (regno >= FIRST_PSEUDO_REGISTER)
-       {
-         /* Count (weighted) references, stores, etc.  This counts a
-            register twice if it is modified, but that is correct.  */
-         REG_N_SETS (regno)++;
-         REG_N_REFS (regno) += loop_depth + 1;
-       }
-    }
-}
-
-/* Increment REG_N_SETS for each SET or CLOBBER found in X; also increment
-   REG_N_REFS by the current loop depth for each SET or CLOBBER found.  */
-
-static void
-count_reg_sets  (x, loop_depth)
-     rtx x;
-     int loop_depth;
-{
-  register RTX_CODE code = GET_CODE (x);
-
-  if (code == SET || code == CLOBBER)
-    count_reg_sets_1 (x, loop_depth);
-  else if (code == PARALLEL)
-    {
-      register int i;
-      for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
-       {
-         code = GET_CODE (XVECEXP (x, 0, i));
-         if (code == SET || code == CLOBBER)
-           count_reg_sets_1 (XVECEXP (x, 0, i), loop_depth);
-       }
-    }
-}
-
-/* Increment REG_N_REFS by the current loop depth each register reference
-   found in X.  */
-
-static void
-count_reg_references (x, loop_depth)
-     rtx x;
-     int loop_depth;
-{
-  register RTX_CODE code;
-
- retry:
-  code = GET_CODE (x);
-  switch (code)
-    {
-    case LABEL_REF:
-    case SYMBOL_REF:
-    case CONST_INT:
-    case CONST:
-    case CONST_DOUBLE:
-    case PC:
-    case ADDR_VEC:
-    case ADDR_DIFF_VEC:
-    case ASM_INPUT:
-      return;
-
-#ifdef HAVE_cc0
-    case CC0:
-      return;
-#endif
-
-    case CLOBBER:
-      /* If we are clobbering a MEM, mark any registers inside the address
-        as being used.  */
-      if (GET_CODE (XEXP (x, 0)) == MEM)
-       count_reg_references (XEXP (XEXP (x, 0), 0), loop_depth);
-      return;
-
-    case SUBREG:
-      /* While we're here, optimize this case.  */
-      x = SUBREG_REG (x);
-
-      /* In case the SUBREG is not of a register, don't optimize */
-      if (GET_CODE (x) != REG)
-       {
-         count_reg_references (x, loop_depth);
-         return;
-       }
-
-      /* ... fall through ...  */
-
-    case REG:
-      if (REGNO (x) >= FIRST_PSEUDO_REGISTER)
-       REG_N_REFS (REGNO (x)) += loop_depth + 1;
-      return;
-
-    case SET:
-      {
-       register rtx testreg = SET_DEST (x);
-       int mark_dest = 0;
-
-       /* If storing into MEM, don't show it as being used.  But do
-          show the address as being used.  */
-       if (GET_CODE (testreg) == MEM)
-         {
-           count_reg_references (XEXP (testreg, 0), loop_depth);
-           count_reg_references (SET_SRC (x), loop_depth);
-           return;
-         }
-           
-       /* Storing in STRICT_LOW_PART is like storing in a reg
-          in that this SET might be dead, so ignore it in TESTREG.
-          but in some other ways it is like using the reg.
-
-          Storing in a SUBREG or a bit field is like storing the entire
-          register in that if the register's value is not used
-          then this SET is not needed.  */
-       while (GET_CODE (testreg) == STRICT_LOW_PART
-              || GET_CODE (testreg) == ZERO_EXTRACT
-              || GET_CODE (testreg) == SIGN_EXTRACT
-              || GET_CODE (testreg) == SUBREG)
-         {
-           /* Modifying a single register in an alternate mode
-              does not use any of the old value.  But these other
-              ways of storing in a register do use the old value.  */
-           if (GET_CODE (testreg) == SUBREG
-               && !(REG_SIZE (SUBREG_REG (testreg)) > REG_SIZE (testreg)))
-             ;
-           else
-             mark_dest = 1;
-
-           testreg = XEXP (testreg, 0);
-         }
-
-       /* If this is a store into a register,
-          recursively scan the value being stored.  */
-
-       if ((GET_CODE (testreg) == PARALLEL
-            && GET_MODE (testreg) == BLKmode)
-           || GET_CODE (testreg) == REG)
-         {
-           count_reg_references (SET_SRC (x), loop_depth);
-           if (mark_dest)
-             count_reg_references (SET_DEST (x), loop_depth);
-           return;
-         }
-      }
-      break;
-
-    default:
-      break;
-    }
-
-  /* Recursively scan the operands of this expression.  */
-
-  {
-    register const char *fmt = GET_RTX_FORMAT (code);
-    register int i;
-    
-    for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-      {
-       if (fmt[i] == 'e')
-         {
-           /* Tail recursive case: save a function call level.  */
-           if (i == 0)
-             {
-               x = XEXP (x, 0);
-               goto retry;
-             }
-           count_reg_references (XEXP (x, i), loop_depth);
-         }
-       else if (fmt[i] == 'E')
-         {
-           register int j;
-           for (j = 0; j < XVECLEN (x, i); j++)
-             count_reg_references (XVECEXP (x, i, j), loop_depth);
-         }
-      }
-  }
-}
-
 /* Recompute register set/reference counts immediately prior to register
    allocation.
 
@@ -5781,70 +5607,8 @@ recompute_reg_usage (f, loop_step)
      rtx f ATTRIBUTE_UNUSED;
      int loop_step ATTRIBUTE_UNUSED;
 {
-  rtx insn;
-  int i, max_reg;
-  int index;
-  int loop_depth;
-
-  /* Clear out the old data.  */
-  max_reg = max_reg_num ();
-  for (i = FIRST_PSEUDO_REGISTER; i < max_reg; i++)
-    {
-      REG_N_SETS (i) = 0;
-      REG_N_REFS (i) = 0;
-    }
-
-  /* Scan each insn in the chain and count how many times each register is
-     set/used.  */
-  for (index = 0; index < n_basic_blocks; index++)
-    {
-      basic_block bb = BASIC_BLOCK (index);
-      loop_depth = bb->loop_depth;
-      for (insn = bb->head; insn; insn = NEXT_INSN (insn))
-       {
-         if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
-           {
-             rtx links;
-
-             /* This call will increment REG_N_SETS for each SET or CLOBBER
-                of a register in INSN.  It will also increment REG_N_REFS
-                by the loop depth for each set of a register in INSN.  */
-             count_reg_sets (PATTERN (insn), loop_depth);
-
-             /* count_reg_sets does not detect autoincrement address modes, so
-                detect them here by looking at the notes attached to INSN.  */
-             for (links = REG_NOTES (insn); links; links = XEXP (links, 1))
-               {
-                 if (REG_NOTE_KIND (links) == REG_INC)
-                   /* Count (weighted) references, stores, etc.  This
-                      counts a register twice if it is modified, but
-                      that is correct.  */
-                   REG_N_SETS (REGNO (XEXP (links, 0)))++;
-               }
-
-             /* This call will increment REG_N_REFS by the current loop depth
-                for each reference to a register in INSN.  */
-             count_reg_references (PATTERN (insn), loop_depth);
-
-             /* count_reg_references will not include counts for arguments to
-                function calls, so detect them here by examining the
-                CALL_INSN_FUNCTION_USAGE data.  */
-             if (GET_CODE (insn) == CALL_INSN)
-               {
-                 rtx note;
-
-                 for (note = CALL_INSN_FUNCTION_USAGE (insn);
-                      note;
-                      note = XEXP (note, 1))
-                   if (GET_CODE (XEXP (note, 0)) == USE)
-                     count_reg_references (XEXP (XEXP (note, 0), 0),
-                                           loop_depth);
-               }
-           }
-         if (insn == bb->end)
-           break;
-       }
-    }
+  allocate_reg_life_data ();
+  update_life_info (NULL, UPDATE_LIFE_LOCAL, PROP_REG_INFO);
 }
 
 /* Optionally removes all the REG_DEAD and REG_UNUSED notes from a set of