OSDN Git Service

* sparc/sparc.md (eligible_for_return_delay): New attribute.
[pf3gnuchains/gcc-fork.git] / gcc / reorg.c
index 9400615..4333061 100644 (file)
@@ -1,5 +1,5 @@
 /* Perform instruction reorganizations for delay slot filling.
-   Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
    Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu).
    Hacked by Michael Tiemann (tiemann@cygnus.com).
 
@@ -121,8 +121,10 @@ Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
+#include "toplev.h"
 #include "rtl.h"
 #include "expr.h"
+#include "function.h"
 #include "insn-config.h"
 #include "conditions.h"
 #include "hard-reg-set.h"
@@ -134,6 +136,7 @@ Boston, MA 02111-1307, USA.  */
 #include "output.h"
 #include "obstack.h"
 #include "insn-attr.h"
+#include "resource.h"
 
 
 #ifdef DELAY_SLOTS
@@ -163,58 +166,9 @@ static rtx *unfilled_firstobj;
 #define unfilled_slots_next    \
   ((rtx *) obstack_next_free (&unfilled_slots_obstack))
 
-/* This structure is used to indicate which hardware resources are set or
-   needed by insns so far.  */
-
-struct resources
-{
-  char memory;                 /* Insn sets or needs a memory location.  */
-  char unch_memory;            /* Insn sets of needs a "unchanging" MEM.  */
-  char volatil;                        /* Insn sets or needs a volatile memory loc.  */
-  char cc;                     /* Insn sets or needs the condition codes.  */
-  HARD_REG_SET regs;           /* Which registers are set or needed.  */
-};
-
-/* Macro to clear all resources.  */
-#define CLEAR_RESOURCE(RES)    \
- do { (RES)->memory = (RES)->unch_memory = (RES)->volatil = (RES)->cc = 0; \
-      CLEAR_HARD_REG_SET ((RES)->regs); } while (0)
-
-/* Indicates what resources are required at the beginning of the epilogue.  */
-static struct resources start_of_epilogue_needs;
-
-/* Indicates what resources are required at function end.  */
-static struct resources end_of_function_needs;
-
 /* Points to the label before the end of the function.  */
 static rtx end_of_function_label;
 
-/* This structure is used to record liveness information at the targets or
-   fallthrough insns of branches.  We will most likely need the information
-   at targets again, so save them in a hash table rather than recomputing them
-   each time.  */
-
-struct target_info
-{
-  int uid;                     /* INSN_UID of target.  */
-  struct target_info *next;    /* Next info for same hash bucket.  */
-  HARD_REG_SET live_regs;      /* Registers live at target.  */
-  int block;                   /* Basic block number containing target.  */
-  int bb_tick;                 /* Generation count of basic block info.  */
-};
-
-#define TARGET_HASH_PRIME 257
-
-/* Define the hash table itself.  */
-static struct target_info **target_hash_table;
-
-/* For each basic block, we maintain a generation number of its basic
-   block info, which is updated each time we move an insn from the
-   target of a jump.  This is the generation number indexed by block
-   number.  */
-
-static int *bb_ticks;
-
 /* Mapping between INSN_UID's and position in the code since INSN_UID's do
    not always monotonically increase.  */
 static int *uid_to_ruid;
@@ -222,25 +176,26 @@ static int *uid_to_ruid;
 /* Highest valid index in `uid_to_ruid'.  */
 static int max_uid;
 
-static void mark_referenced_resources PROTO((rtx, struct resources *, int));
-static void mark_set_resources PROTO((rtx, struct resources *, int, int));
-static int stop_search_p       PROTO((rtx, int));
-static int resource_conflicts_p        PROTO((struct resources *,
-                                      struct resources *));
-static int insn_references_resource_p PROTO((rtx, struct resources *, int));
-static int insn_sets_resource_p PROTO((rtx, struct resources *, int));
-static rtx find_end_label      PROTO((void));
-static rtx emit_delay_sequence PROTO((rtx, rtx, int));
-static rtx add_to_delay_list   PROTO((rtx, rtx));
-static rtx delete_from_delay_slot PROTO((rtx));
-static void delete_scheduled_jump PROTO((rtx));
-static void note_delay_statistics PROTO((int, int));
-static rtx optimize_skip       PROTO((rtx));
-static int get_jump_flags PROTO((rtx, rtx));
-static int rare_destination PROTO((rtx));
-static int mostly_true_jump    PROTO((rtx, rtx));
-static rtx get_branch_condition        PROTO((rtx, rtx));
-static int condition_dominates_p PROTO((rtx, rtx));
+static int stop_search_p               PROTO((rtx, int));
+static int resource_conflicts_p                PROTO((struct resources *,
+                                              struct resources *));
+static int insn_references_resource_p  PROTO((rtx, struct resources *, int));
+static int insn_sets_resource_p                PROTO((rtx, struct resources *, int));
+static rtx find_end_label              PROTO((void));
+static rtx emit_delay_sequence         PROTO((rtx, rtx, int));
+static rtx add_to_delay_list           PROTO((rtx, rtx));
+static rtx delete_from_delay_slot      PROTO((rtx));
+static void delete_scheduled_jump      PROTO((rtx));
+static void note_delay_statistics      PROTO((int, int));
+static rtx optimize_skip               PROTO((rtx));
+static int get_jump_flags              PROTO((rtx, rtx));
+static int rare_destination            PROTO((rtx));
+static int mostly_true_jump            PROTO((rtx, rtx));
+static rtx get_branch_condition                PROTO((rtx, rtx));
+static int condition_dominates_p       PROTO((rtx, rtx));
+static int redirect_with_delay_slots_safe_p PROTO ((rtx, rtx, rtx));
+static int redirect_with_delay_list_safe_p PROTO ((rtx, rtx, rtx));
+static int check_annul_list_true_false PROTO ((int, rtx));
 static rtx steal_delay_list_from_target PROTO((rtx, rtx, rtx, rtx,
                                               struct resources *,
                                               struct resources *,
@@ -251,442 +206,20 @@ static rtx steal_delay_list_from_fallthrough PROTO((rtx, rtx, rtx, rtx,
                                                    struct resources *,
                                                    struct resources *,
                                                    int, int *, int *));
-static void try_merge_delay_insns PROTO((rtx, rtx));
-static rtx redundant_insn      PROTO((rtx, rtx, rtx));
-static int own_thread_p                PROTO((rtx, rtx, int));
-static int find_basic_block    PROTO((rtx));
-static void update_block       PROTO((rtx, rtx));
-static int reorg_redirect_jump PROTO((rtx, rtx));
-static void update_reg_dead_notes PROTO((rtx, rtx));
-static void fix_reg_dead_note PROTO((rtx, rtx));
-static void update_reg_unused_notes PROTO((rtx, rtx));
-static void update_live_status PROTO((rtx, rtx));
-static rtx next_insn_no_annul  PROTO((rtx));
-static rtx find_dead_or_set_registers PROTO ((rtx, struct resources *, rtx *,
-                                             int, struct resources,
-                                             struct resources));
-static void mark_target_live_regs PROTO((rtx, struct resources *));
-static void fill_simple_delay_slots PROTO((int));
-static rtx fill_slots_from_thread PROTO((rtx, rtx, rtx, rtx, int, int,
-                                        int, int, int *, rtx));
-static void fill_eager_delay_slots PROTO((void));
-static void relax_delay_slots  PROTO((rtx));
-static void make_return_insns  PROTO((rtx));
-static int redirect_with_delay_slots_safe_p PROTO ((rtx, rtx, rtx));
-static int redirect_with_delay_list_safe_p PROTO ((rtx, rtx, rtx));
-\f
-/* Given X, some rtl, and RES, a pointer to a `struct resource', mark
-   which resources are references by the insn.  If INCLUDE_DELAYED_EFFECTS
-   is TRUE, resources used by the called routine will be included for
-   CALL_INSNs.  */
-
-static void
-mark_referenced_resources (x, res, include_delayed_effects)
-     register rtx x;
-     register struct resources *res;
-     register int include_delayed_effects;
-{
-  register enum rtx_code code = GET_CODE (x);
-  register int i, j;
-  register char *format_ptr;
-
-  /* Handle leaf items for which we set resource flags.  Also, special-case
-     CALL, SET and CLOBBER operators.  */
-  switch (code)
-    {
-    case CONST:
-    case CONST_INT:
-    case CONST_DOUBLE:
-    case PC:
-    case SYMBOL_REF:
-    case LABEL_REF:
-      return;
-
-    case SUBREG:
-      if (GET_CODE (SUBREG_REG (x)) != REG)
-       mark_referenced_resources (SUBREG_REG (x), res, 0);
-      else
-       {
-         int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
-         int last_regno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
-         for (i = regno; i < last_regno; i++)
-           SET_HARD_REG_BIT (res->regs, i);
-       }
-      return;
-
-    case REG:
-      for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++)
-       SET_HARD_REG_BIT (res->regs, REGNO (x) + i);
-      return;
-
-    case MEM:
-      /* If this memory shouldn't change, it really isn't referencing
-        memory.  */
-      if (RTX_UNCHANGING_P (x))
-       res->unch_memory = 1;
-      else
-       res->memory = 1;
-      res->volatil = MEM_VOLATILE_P (x);
-
-      /* Mark registers used to access memory.  */
-      mark_referenced_resources (XEXP (x, 0), res, 0);
-      return;
-
-    case CC0:
-      res->cc = 1;
-      return;
-
-    case UNSPEC_VOLATILE:
-    case ASM_INPUT:
-      /* Traditional asm's are always volatile.  */
-      res->volatil = 1;
-      return;
-
-    case TRAP_IF:
-      res->volatil = 1;
-      break;
-
-    case ASM_OPERANDS:
-      res->volatil = MEM_VOLATILE_P (x);
-
-      /* For all ASM_OPERANDS, we must traverse the vector of input operands.
-        We can not just fall through here since then we would be confused
-        by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate
-        traditional asms unlike their normal usage.  */
-      
-      for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
-       mark_referenced_resources (ASM_OPERANDS_INPUT (x, i), res, 0);
-      return;
-
-    case CALL:
-      /* The first operand will be a (MEM (xxx)) but doesn't really reference
-        memory.  The second operand may be referenced, though.  */
-      mark_referenced_resources (XEXP (XEXP (x, 0), 0), res, 0);
-      mark_referenced_resources (XEXP (x, 1), res, 0);
-      return;
-
-    case SET:
-      /* Usually, the first operand of SET is set, not referenced.  But
-        registers used to access memory are referenced.  SET_DEST is
-        also referenced if it is a ZERO_EXTRACT or SIGN_EXTRACT.  */
-
-      mark_referenced_resources (SET_SRC (x), res, 0);
-
-      x = SET_DEST (x);
-      if (GET_CODE (x) == SIGN_EXTRACT || GET_CODE (x) == ZERO_EXTRACT)
-       mark_referenced_resources (x, res, 0);
-      else if (GET_CODE (x) == SUBREG)
-       x = SUBREG_REG (x);
-      if (GET_CODE (x) == MEM)
-       mark_referenced_resources (XEXP (x, 0), res, 0);
-      return;
-
-    case CLOBBER:
-      return;
-
-    case CALL_INSN:
-      if (include_delayed_effects)
-       {
-         /* A CALL references memory, the frame pointer if it exists, the
-            stack pointer, any global registers and any registers given in
-            USE insns immediately in front of the CALL.
-
-            However, we may have moved some of the parameter loading insns
-            into the delay slot of this CALL.  If so, the USE's for them
-            don't count and should be skipped.  */
-         rtx insn = PREV_INSN (x);
-         rtx sequence = 0;
-         int seq_size = 0;
-         rtx next = NEXT_INSN (x);
-         int i;
-
-         /* If we are part of a delay slot sequence, point at the SEQUENCE.  */
-         if (NEXT_INSN (insn) != x)
-           {
-             next = NEXT_INSN (NEXT_INSN (insn));
-             sequence = PATTERN (NEXT_INSN (insn));
-             seq_size = XVECLEN (sequence, 0);
-             if (GET_CODE (sequence) != SEQUENCE)
-               abort ();
-           }
-
-         res->memory = 1;
-         SET_HARD_REG_BIT (res->regs, STACK_POINTER_REGNUM);
-         if (frame_pointer_needed)
-           {
-             SET_HARD_REG_BIT (res->regs, FRAME_POINTER_REGNUM);
-#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
-             SET_HARD_REG_BIT (res->regs, HARD_FRAME_POINTER_REGNUM);
-#endif
-           }
-
-         for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-           if (global_regs[i])
-             SET_HARD_REG_BIT (res->regs, i);
-
-         /* Check for a NOTE_INSN_SETJMP.  If it exists, then we must
-            assume that this call can need any register.
-
-            This is done to be more conservative about how we handle setjmp.
-            We assume that they both use and set all registers.  Using all
-            registers ensures that a register will not be considered dead
-            just because it crosses a setjmp call.  A register should be
-            considered dead only if the setjmp call returns non-zero.  */
-         if (next && GET_CODE (next) == NOTE
-             && NOTE_LINE_NUMBER (next) == NOTE_INSN_SETJMP)
-           SET_HARD_REG_SET (res->regs);
-
-         {
-           rtx link;
-
-           for (link = CALL_INSN_FUNCTION_USAGE (x);
-                link;
-                link = XEXP (link, 1))
-             if (GET_CODE (XEXP (link, 0)) == USE)
-               {
-                 for (i = 1; i < seq_size; i++)
-                   {
-                     rtx slot_pat = PATTERN (XVECEXP (sequence, 0, i));
-                     if (GET_CODE (slot_pat) == SET
-                         && rtx_equal_p (SET_DEST (slot_pat),
-                                         SET_DEST (XEXP (link, 0))))
-                       break;
-                   }
-                 if (i >= seq_size)
-                   mark_referenced_resources (SET_DEST (XEXP (link, 0)),
-                                              res, 0);
-               }
-         }
-       }
-
-      /* ... fall through to other INSN processing ...  */
-
-    case INSN:
-    case JUMP_INSN:
-
-#ifdef INSN_REFERENCES_ARE_DELAYED
-      if (! include_delayed_effects
-         && INSN_REFERENCES_ARE_DELAYED (x))
-       return;
-#endif
-
-      /* No special processing, just speed up.  */
-      mark_referenced_resources (PATTERN (x), res, include_delayed_effects);
-      return;
-
-    default:
-      break;
-    }
-
-  /* Process each sub-expression and flag what it needs.  */
-  format_ptr = GET_RTX_FORMAT (code);
-  for (i = 0; i < GET_RTX_LENGTH (code); i++)
-    switch (*format_ptr++)
-      {
-      case 'e':
-       mark_referenced_resources (XEXP (x, i), res, include_delayed_effects);
-       break;
-
-      case 'E':
-       for (j = 0; j < XVECLEN (x, i); j++)
-         mark_referenced_resources (XVECEXP (x, i, j), res,
-                                    include_delayed_effects);
-       break;
-      }
-}
-\f
-/* Given X, a part of an insn, and a pointer to a `struct resource',
-   RES, indicate which resources are modified by the insn. If
-   INCLUDE_DELAYED_EFFECTS is nonzero, also mark resources potentially
-   set by the called routine.
-
-   If IN_DEST is nonzero, it means we are inside a SET.  Otherwise,
-   objects are being referenced instead of set.
-
-   We never mark the insn as modifying the condition code unless it explicitly
-   SETs CC0 even though this is not totally correct.  The reason for this is
-   that we require a SET of CC0 to immediately precede the reference to CC0.
-   So if some other insn sets CC0 as a side-effect, we know it cannot affect
-   our computation and thus may be placed in a delay slot.   */
-
-static void
-mark_set_resources (x, res, in_dest, include_delayed_effects)
-     register rtx x;
-     register struct resources *res;
-     int in_dest;
-     int include_delayed_effects;
-{
-  register enum rtx_code code;
-  register int i, j;
-  register char *format_ptr;
-
- restart:
-
-  code = GET_CODE (x);
-
-  switch (code)
-    {
-    case NOTE:
-    case BARRIER:
-    case CODE_LABEL:
-    case USE:
-    case CONST_INT:
-    case CONST_DOUBLE:
-    case LABEL_REF:
-    case SYMBOL_REF:
-    case CONST:
-    case PC:
-      /* These don't set any resources.  */
-      return;
-
-    case CC0:
-      if (in_dest)
-       res->cc = 1;
-      return;
-
-    case CALL_INSN:
-      /* Called routine modifies the condition code, memory, any registers
-        that aren't saved across calls, global registers and anything
-        explicitly CLOBBERed immediately after the CALL_INSN.  */
-
-      if (include_delayed_effects)
-       {
-         rtx next = NEXT_INSN (x);
-         rtx prev = PREV_INSN (x);
-         rtx link;
-
-         res->cc = res->memory = 1;
-         for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-           if (call_used_regs[i] || global_regs[i])
-             SET_HARD_REG_BIT (res->regs, i);
-
-         /* If X is part of a delay slot sequence, then NEXT should be
-            the first insn after the sequence.  */
-         if (NEXT_INSN (prev) != x)
-           next = NEXT_INSN (NEXT_INSN (prev));
-
-         for (link = CALL_INSN_FUNCTION_USAGE (x);
-              link; link = XEXP (link, 1))
-           if (GET_CODE (XEXP (link, 0)) == CLOBBER)
-             mark_set_resources (SET_DEST (XEXP (link, 0)), res, 1, 0);
-
-         /* Check for a NOTE_INSN_SETJMP.  If it exists, then we must
-            assume that this call can clobber any register.  */
-         if (next && GET_CODE (next) == NOTE
-             && NOTE_LINE_NUMBER (next) == NOTE_INSN_SETJMP)
-           SET_HARD_REG_SET (res->regs);
-       }
-
-      /* ... and also what its RTL says it modifies, if anything.  */
-
-    case JUMP_INSN:
-    case INSN:
-
-       /* An insn consisting of just a CLOBBER (or USE) is just for flow
-          and doesn't actually do anything, so we ignore it.  */
-
-#ifdef INSN_SETS_ARE_DELAYED
-      if (! include_delayed_effects
-         && INSN_SETS_ARE_DELAYED (x))
-       return;
-#endif
-
-      x = PATTERN (x);
-      if (GET_CODE (x) != USE && GET_CODE (x) != CLOBBER)
-       goto restart;
-      return;
-
-    case SET:
-      /* If the source of a SET is a CALL, this is actually done by
-        the called routine.  So only include it if we are to include the
-        effects of the calling routine.  */
-
-      mark_set_resources (SET_DEST (x), res,
-                         (include_delayed_effects
-                          || GET_CODE (SET_SRC (x)) != CALL),
-                         0);
-
-      mark_set_resources (SET_SRC (x), res, 0, 0);
-      return;
-
-    case CLOBBER:
-      mark_set_resources (XEXP (x, 0), res, 1, 0);
-      return;
-      
-    case SEQUENCE:
-      for (i = 0; i < XVECLEN (x, 0); i++)
-       if (! (INSN_ANNULLED_BRANCH_P (XVECEXP (x, 0, 0))
-              && INSN_FROM_TARGET_P (XVECEXP (x, 0, i))))
-         mark_set_resources (XVECEXP (x, 0, i), res, 0,
-                             include_delayed_effects);
-      return;
-
-    case POST_INC:
-    case PRE_INC:
-    case POST_DEC:
-    case PRE_DEC:
-      mark_set_resources (XEXP (x, 0), res, 1, 0);
-      return;
-
-    case ZERO_EXTRACT:
-      mark_set_resources (XEXP (x, 0), res, in_dest, 0);
-      mark_set_resources (XEXP (x, 1), res, 0, 0);
-      mark_set_resources (XEXP (x, 2), res, 0, 0);
-      return;
-
-    case MEM:
-      if (in_dest)
-       {
-         res->memory = 1;
-         res->unch_memory = RTX_UNCHANGING_P (x);
-         res->volatil = MEM_VOLATILE_P (x);
-       }
-
-      mark_set_resources (XEXP (x, 0), res, 0, 0);
-      return;
-
-    case SUBREG:
-      if (in_dest)
-       {
-         if (GET_CODE (SUBREG_REG (x)) != REG)
-           mark_set_resources (SUBREG_REG (x), res,
-                               in_dest, include_delayed_effects);
-         else
-           {
-             int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
-             int last_regno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
-             for (i = regno; i < last_regno; i++)
-               SET_HARD_REG_BIT (res->regs, i);
-           }
-       }
-      return;
-
-    case REG:
-      if (in_dest)
-        for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++)
-         SET_HARD_REG_BIT (res->regs, REGNO (x) + i);
-      return;
-
-    default:
-      break;
-    }
-
-  /* Process each sub-expression and flag what it needs.  */
-  format_ptr = GET_RTX_FORMAT (code);
-  for (i = 0; i < GET_RTX_LENGTH (code); i++)
-    switch (*format_ptr++)
-      {
-      case 'e':
-       mark_set_resources (XEXP (x, i), res, in_dest, include_delayed_effects);
-       break;
-
-      case 'E':
-       for (j = 0; j < XVECLEN (x, i); j++)
-         mark_set_resources (XVECEXP (x, i, j), res, in_dest,
-                             include_delayed_effects);
-       break;
-      }
-}
+static void try_merge_delay_insns      PROTO((rtx, rtx));
+static rtx redundant_insn              PROTO((rtx, rtx, rtx));
+static int own_thread_p                        PROTO((rtx, rtx, int));
+static void update_block               PROTO((rtx, rtx));
+static int reorg_redirect_jump         PROTO((rtx, rtx));
+static void update_reg_dead_notes      PROTO((rtx, rtx));
+static void fix_reg_dead_note          PROTO((rtx, rtx));
+static void update_reg_unused_notes    PROTO((rtx, rtx));
+static void fill_simple_delay_slots    PROTO((int));
+static rtx fill_slots_from_thread      PROTO((rtx, rtx, rtx, rtx, int, int,
+                                              int, int, int *, rtx));
+static void fill_eager_delay_slots     PROTO((void));
+static void relax_delay_slots          PROTO((rtx));
+static void make_return_insns          PROTO((rtx));
 \f
 /* Return TRUE if this insn should stop the search for insn to fill delay
    slots.  LABELS_P indicates that labels should terminate the search.
@@ -986,16 +519,7 @@ add_to_delay_list (insn, delay_list)
 
   if (delay_list == 0)
     {
-      struct target_info *tinfo;
-      
-      for (tinfo = target_hash_table[INSN_UID (insn) % TARGET_HASH_PRIME];
-          tinfo; tinfo = tinfo->next)
-       if (tinfo->uid == INSN_UID (insn))
-         break;
-
-      if (tinfo)
-       tinfo->block = -1;
-
+      clear_hashed_info_for_insn (insn);
       return gen_rtx_INSN_LIST (VOIDmode, insn, NULL_RTX);
     }
 
@@ -1006,8 +530,8 @@ add_to_delay_list (insn, delay_list)
   return delay_list;
 }   
 \f
-/* Delete INSN from the delay slot of the insn that it is in.  This may
-   produce an insn without anything in its delay slots.  */
+/* Delete INSN from the delay slot of the insn that it is in, which may
+   produce an insn with no delay slots.  Return the new insn.  */
 
 static rtx
 delete_from_delay_slot (insn)
@@ -1193,7 +717,8 @@ optimize_skip (insn)
      we have one insn followed by a branch to the same label we branch to.
      In both of these cases, inverting the jump and annulling the delay
      slot give the same effect in fewer insns.  */
-  if ((next_trial == next_active_insn (JUMP_LABEL (insn)))
+  if ((next_trial == next_active_insn (JUMP_LABEL (insn))
+       && ! (next_trial == 0 && current_function_epilogue_delay_list != 0))
       || (next_trial != 0
          && GET_CODE (next_trial) == JUMP_INSN
          && JUMP_LABEL (insn) == JUMP_LABEL (next_trial)
@@ -1377,7 +902,7 @@ mostly_true_jump (jump_insn, condition)
      always gives a correct answer.  */
   if (flag_branch_probabilities)
     {
-      rtx note = find_reg_note (jump_insn, REG_BR_PROB, 0);;
+      rtx note = find_reg_note (jump_insn, REG_BR_PROB, 0);
       if (note)
        {
          int prob = XINT (note, 0);
@@ -1480,7 +1005,7 @@ mostly_true_jump (jump_insn, condition)
   return (target_label == 0 || INSN_UID (jump_insn) > max_uid
          || INSN_UID (target_label) > max_uid
          || (uid_to_ruid[INSN_UID (jump_insn)]
-             > uid_to_ruid[INSN_UID (target_label)]));;
+             > uid_to_ruid[INSN_UID (target_label)]));
 }
 
 /* Return the condition under which INSN will branch to TARGET.  If TARGET
@@ -1646,6 +1171,7 @@ check_annul_list_true_false (annul_true_p, delay_list)
            return 0;
         }
     }
+
   return 1;
 }
 
@@ -1689,8 +1215,8 @@ steal_delay_list_from_target (insn, condition, seq, delay_list,
   int total_slots_filled = *pslots_filled;
   rtx new_delay_list = 0;
   int must_annul = *pannul_p;
-  int i;
   int used_annul = 0;
+  int i;
   struct resources cc_set;
 
   /* We can't do anything if there are more delay slots in SEQ than we
@@ -2321,41 +1847,6 @@ own_thread_p (thread, label, allow_fallthrough)
   return 1;
 }
 \f
-/* Find the number of the basic block that starts closest to INSN.  Return -1
-   if we couldn't find such a basic block.  */
-
-static int
-find_basic_block (insn)
-     rtx insn;
-{
-  int i;
-
-  /* Scan backwards to the previous BARRIER.  Then see if we can find a
-     label that starts a basic block.  Return the basic block number.  */
-
-  for (insn = prev_nonnote_insn (insn);
-       insn && GET_CODE (insn) != BARRIER;
-       insn = prev_nonnote_insn (insn))
-    ;
-
-  /* The start of the function is basic block zero.  */
-  if (insn == 0)
-    return 0;
-
-  /* See if any of the upcoming CODE_LABELs start a basic block.  If we reach
-     anything other than a CODE_LABEL or note, we can't find this code.  */
-  for (insn = next_nonnote_insn (insn);
-       insn && GET_CODE (insn) == CODE_LABEL;
-       insn = next_nonnote_insn (insn))
-    {
-      for (i = 0; i < n_basic_blocks; i++)
-       if (insn == basic_block_head[i])
-         return i;
-    }
-
-  return -1;
-}
-\f
 /* Called when INSN is being moved from a location near the target of a jump.
    We leave a marker of the form (use (INSN)) immediately in front
    of WHERE for mark_target_live_regs.  These markers will be deleted when
@@ -2370,8 +1861,6 @@ update_block (insn, where)
      rtx insn;
      rtx where;
 {
-  int b;
-
   /* Ignore if this was in a delay slot and it came from the target of 
      a branch.  */
   if (INSN_FROM_TARGET_P (insn))
@@ -2382,9 +1871,7 @@ update_block (insn, where)
   /* INSN might be making a value live in a block where it didn't use to
      be.  So recompute liveness information for this block.  */
 
-  b = find_basic_block (insn);
-  if (b != -1)
-    bb_ticks[b]++;
+  incr_ticks_for_insn (insn);
 }
 
 /* Similar to REDIRECT_JUMP except that we update the BB_TICKS entry for
@@ -2395,11 +1882,7 @@ reorg_redirect_jump (jump, nlabel)
      rtx jump;
      rtx nlabel;
 {
-  int b = find_basic_block (jump);
-
-  if (b != -1)
-    bb_ticks[b]++;
-
+  incr_ticks_for_insn (jump);
   return redirect_jump (jump, nlabel);
 }
 
@@ -2499,549 +1982,6 @@ update_reg_unused_notes (insn, redundant_insn)
     }
 }
 \f
-/* Marks registers possibly live at the current place being scanned by
-   mark_target_live_regs.  Used only by next two function.    */
-
-static HARD_REG_SET current_live_regs;
-
-/* Marks registers for which we have seen a REG_DEAD note but no assignment.
-   Also only used by the next two functions.  */
-
-static HARD_REG_SET pending_dead_regs;
-
-/* Utility function called from mark_target_live_regs via note_stores.
-   It deadens any CLOBBERed registers and livens any SET registers.  */
-
-static void
-update_live_status (dest, x)
-     rtx dest;
-     rtx x;
-{
-  int first_regno, last_regno;
-  int i;
-
-  if (GET_CODE (dest) != REG
-      && (GET_CODE (dest) != SUBREG || GET_CODE (SUBREG_REG (dest)) != REG))
-    return;
-
-  if (GET_CODE (dest) == SUBREG)
-    first_regno = REGNO (SUBREG_REG (dest)) + SUBREG_WORD (dest);
-  else
-    first_regno = REGNO (dest);
-
-  last_regno = first_regno + HARD_REGNO_NREGS (first_regno, GET_MODE (dest));
-
-  if (GET_CODE (x) == CLOBBER)
-    for (i = first_regno; i < last_regno; i++)
-      CLEAR_HARD_REG_BIT (current_live_regs, i);
-  else
-    for (i = first_regno; i < last_regno; i++)
-      {
-       SET_HARD_REG_BIT (current_live_regs, i);
-       CLEAR_HARD_REG_BIT (pending_dead_regs, i);
-      }
-}
-
-/* Similar to next_insn, but ignores insns in the delay slots of
-   an annulled branch.  */
-
-static rtx
-next_insn_no_annul (insn)
-     rtx insn;
-{
-  if (insn)
-    {
-      /* If INSN is an annulled branch, skip any insns from the target
-        of the branch.  */
-      if (INSN_ANNULLED_BRANCH_P (insn)
-         && NEXT_INSN (PREV_INSN (insn)) != insn)
-       while (INSN_FROM_TARGET_P (NEXT_INSN (insn)))
-         insn = NEXT_INSN (insn);
-
-      insn = NEXT_INSN (insn);
-      if (insn && GET_CODE (insn) == INSN
-         && GET_CODE (PATTERN (insn)) == SEQUENCE)
-       insn = XVECEXP (PATTERN (insn), 0, 0);
-    }
-
-  return insn;
-}
-\f
-/* A subroutine of mark_target_live_regs.  Search forward from TARGET
-   looking for registers that are set before they are used.  These are dead. 
-   Stop after passing a few conditional jumps, and/or a small
-   number of unconditional branches.  */
-
-static rtx
-find_dead_or_set_registers (target, res, jump_target, jump_count, set, needed)
-     rtx target;
-     struct resources *res;
-     rtx *jump_target;
-     int jump_count;
-     struct resources set, needed;
-{
-  HARD_REG_SET scratch;
-  rtx insn, next;
-  rtx jump_insn = 0;
-  int i;
-
-  for (insn = target; insn; insn = next)
-    {
-      rtx this_jump_insn = insn;
-
-      next = NEXT_INSN (insn);
-      switch (GET_CODE (insn))
-       {
-       case CODE_LABEL:
-         /* After a label, any pending dead registers that weren't yet
-            used can be made dead.  */
-         AND_COMPL_HARD_REG_SET (pending_dead_regs, needed.regs);
-         AND_COMPL_HARD_REG_SET (res->regs, pending_dead_regs);
-         CLEAR_HARD_REG_SET (pending_dead_regs);
-
-         continue;
-
-       case BARRIER:
-       case NOTE:
-         continue;
-
-       case INSN:
-         if (GET_CODE (PATTERN (insn)) == USE)
-           {
-             /* If INSN is a USE made by update_block, we care about the
-                underlying insn.  Any registers set by the underlying insn
-                are live since the insn is being done somewhere else.  */
-             if (GET_RTX_CLASS (GET_CODE (XEXP (PATTERN (insn), 0))) == 'i')
-               mark_set_resources (XEXP (PATTERN (insn), 0), res, 0, 1);
-
-             /* All other USE insns are to be ignored.  */
-             continue;
-           }
-         else if (GET_CODE (PATTERN (insn)) == CLOBBER)
-           continue;
-         else if (GET_CODE (PATTERN (insn)) == SEQUENCE)
-           {
-             /* An unconditional jump can be used to fill the delay slot
-                of a call, so search for a JUMP_INSN in any position.  */
-             for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
-               {
-                 this_jump_insn = XVECEXP (PATTERN (insn), 0, i);
-                 if (GET_CODE (this_jump_insn) == JUMP_INSN)
-                   break;
-               }
-           }
-
-       default:
-         break;
-       }
-
-      if (GET_CODE (this_jump_insn) == JUMP_INSN)
-       {
-         if (jump_count++ < 10)
-           {
-             if (simplejump_p (this_jump_insn)
-                 || GET_CODE (PATTERN (this_jump_insn)) == RETURN)
-               {
-                 next = JUMP_LABEL (this_jump_insn);
-                 if (jump_insn == 0)
-                   {
-                     jump_insn = insn;
-                     if (jump_target)
-                       *jump_target = JUMP_LABEL (this_jump_insn);
-                   }
-               }
-             else if (condjump_p (this_jump_insn)
-                      || condjump_in_parallel_p (this_jump_insn))
-               {
-                 struct resources target_set, target_res;
-                 struct resources fallthrough_res;
-
-                 /* We can handle conditional branches here by following
-                    both paths, and then IOR the results of the two paths
-                    together, which will give us registers that are dead
-                    on both paths.  Since this is expensive, we give it
-                    a much higher cost than unconditional branches.  The
-                    cost was chosen so that we will follow at most 1
-                    conditional branch.  */
-
-                 jump_count += 4;
-                 if (jump_count >= 10)
-                   break;
-
-                 mark_referenced_resources (insn, &needed, 1);
-
-                 /* For an annulled branch, mark_set_resources ignores slots
-                    filled by instructions from the target.  This is correct
-                    if the branch is not taken.  Since we are following both
-                    paths from the branch, we must also compute correct info
-                    if the branch is taken.  We do this by inverting all of
-                    the INSN_FROM_TARGET_P bits, calling mark_set_resources,
-                    and then inverting the INSN_FROM_TARGET_P bits again.  */
-
-                 if (GET_CODE (PATTERN (insn)) == SEQUENCE
-                     && INSN_ANNULLED_BRANCH_P (this_jump_insn))
-                   {
-                     for (i = 1; i < XVECLEN (PATTERN (insn), 0); i++)
-                       INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i))
-                         = ! INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i));
-
-                     target_set = set;
-                     mark_set_resources (insn, &target_set, 0, 1);
-
-                     for (i = 1; i < XVECLEN (PATTERN (insn), 0); i++)
-                       INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i))
-                         = ! INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i));
-
-                     mark_set_resources (insn, &set, 0, 1);
-                   }
-                 else
-                   {
-                     mark_set_resources (insn, &set, 0, 1);
-                     target_set = set;
-                   }
-
-                 target_res = *res;
-                 COPY_HARD_REG_SET (scratch, target_set.regs);
-                 AND_COMPL_HARD_REG_SET (scratch, needed.regs);
-                 AND_COMPL_HARD_REG_SET (target_res.regs, scratch);
-
-                 fallthrough_res = *res;
-                 COPY_HARD_REG_SET (scratch, set.regs);
-                 AND_COMPL_HARD_REG_SET (scratch, needed.regs);
-                 AND_COMPL_HARD_REG_SET (fallthrough_res.regs, scratch);
-
-                 find_dead_or_set_registers (JUMP_LABEL (this_jump_insn),
-                                             &target_res, 0, jump_count,
-                                             target_set, needed);
-                 find_dead_or_set_registers (next,
-                                             &fallthrough_res, 0, jump_count,
-                                             set, needed);
-                 IOR_HARD_REG_SET (fallthrough_res.regs, target_res.regs);
-                 AND_HARD_REG_SET (res->regs, fallthrough_res.regs);
-                 break;
-               }
-             else
-               break;
-           }
-         else
-           {
-             /* Don't try this optimization if we expired our jump count
-                above, since that would mean there may be an infinite loop
-                in the function being compiled.  */
-             jump_insn = 0;
-             break;
-           }
-       }
-
-      mark_referenced_resources (insn, &needed, 1);
-      mark_set_resources (insn, &set, 0, 1);
-
-      COPY_HARD_REG_SET (scratch, set.regs);
-      AND_COMPL_HARD_REG_SET (scratch, needed.regs);
-      AND_COMPL_HARD_REG_SET (res->regs, scratch);
-    }
-
-  return jump_insn;
-}
-
-/* Set the resources that are live at TARGET.
-
-   If TARGET is zero, we refer to the end of the current function and can
-   return our precomputed value.
-
-   Otherwise, we try to find out what is live by consulting the basic block
-   information.  This is tricky, because we must consider the actions of
-   reload and jump optimization, which occur after the basic block information
-   has been computed.
-
-   Accordingly, we proceed as follows::
-
-   We find the previous BARRIER and look at all immediately following labels
-   (with no intervening active insns) to see if any of them start a basic
-   block.  If we hit the start of the function first, we use block 0.
-
-   Once we have found a basic block and a corresponding first insns, we can
-   accurately compute the live status from basic_block_live_regs and
-   reg_renumber.  (By starting at a label following a BARRIER, we are immune
-   to actions taken by reload and jump.)  Then we scan all insns between
-   that point and our target.  For each CLOBBER (or for call-clobbered regs
-   when we pass a CALL_INSN), mark the appropriate registers are dead.  For
-   a SET, mark them as live.
-
-   We have to be careful when using REG_DEAD notes because they are not
-   updated by such things as find_equiv_reg.  So keep track of registers
-   marked as dead that haven't been assigned to, and mark them dead at the
-   next CODE_LABEL since reload and jump won't propagate values across labels.
-
-   If we cannot find the start of a basic block (should be a very rare
-   case, if it can happen at all), mark everything as potentially live.
-
-   Next, scan forward from TARGET looking for things set or clobbered
-   before they are used.  These are not live.
-
-   Because we can be called many times on the same target, save our results
-   in a hash table indexed by INSN_UID.  */
-
-static void
-mark_target_live_regs (target, res)
-     rtx target;
-     struct resources *res;
-{
-  int b = -1;
-  int i;
-  struct target_info *tinfo;
-  rtx insn;
-  rtx jump_insn = 0;
-  rtx jump_target;
-  HARD_REG_SET scratch;
-  struct resources set, needed;
-
-  /* Handle end of function.  */
-  if (target == 0)
-    {
-      *res = end_of_function_needs;
-      return;
-    }
-
-  /* We have to assume memory is needed, but the CC isn't.  */
-  res->memory = 1;
-  res->volatil = res->unch_memory = 0;
-  res->cc = 0;
-
-  /* See if we have computed this value already.  */
-  for (tinfo = target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME];
-       tinfo; tinfo = tinfo->next)
-    if (tinfo->uid == INSN_UID (target))
-      break;
-
-  /* Start by getting the basic block number.  If we have saved information,
-     we can get it from there unless the insn at the start of the basic block
-     has been deleted.  */
-  if (tinfo && tinfo->block != -1
-      && ! INSN_DELETED_P (basic_block_head[tinfo->block]))
-    b = tinfo->block;
-
-  if (b == -1)
-    b = find_basic_block (target);
-
-  if (tinfo)
-    {
-      /* If the information is up-to-date, use it.  Otherwise, we will
-        update it below.  */
-      if (b == tinfo->block && b != -1 && tinfo->bb_tick == bb_ticks[b])
-       {
-         COPY_HARD_REG_SET (res->regs, tinfo->live_regs);
-         return;
-       }
-    }
-  else
-    {
-      /* Allocate a place to put our results and chain it into the 
-        hash table.  */
-      tinfo = (struct target_info *) oballoc (sizeof (struct target_info));
-      tinfo->uid = INSN_UID (target);
-      tinfo->block = b;
-      tinfo->next = target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME];
-      target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME] = tinfo;
-    }
-
-  CLEAR_HARD_REG_SET (pending_dead_regs);
-
-  /* If we found a basic block, get the live registers from it and update
-     them with anything set or killed between its start and the insn before
-     TARGET.  Otherwise, we must assume everything is live.  */
-  if (b != -1)
-    {
-      regset regs_live = basic_block_live_at_start[b];
-      int j;
-      int regno;
-      rtx start_insn, stop_insn;
-
-      /* Compute hard regs live at start of block -- this is the real hard regs
-        marked live, plus live pseudo regs that have been renumbered to
-        hard regs.  */
-
-      REG_SET_TO_HARD_REG_SET (current_live_regs, regs_live);
-
-      EXECUTE_IF_SET_IN_REG_SET
-       (regs_live, FIRST_PSEUDO_REGISTER, i,
-        {
-          if ((regno = reg_renumber[i]) >= 0)
-            for (j = regno;
-                 j < regno + HARD_REGNO_NREGS (regno,
-                                               PSEUDO_REGNO_MODE (i));
-                 j++)
-              SET_HARD_REG_BIT (current_live_regs, j);
-        });
-
-      /* Get starting and ending insn, handling the case where each might
-        be a SEQUENCE.  */
-      start_insn = (b == 0 ? get_insns () : basic_block_head[b]);
-      stop_insn = target;
-
-      if (GET_CODE (start_insn) == INSN
-         && GET_CODE (PATTERN (start_insn)) == SEQUENCE)
-       start_insn = XVECEXP (PATTERN (start_insn), 0, 0);
-
-      if (GET_CODE (stop_insn) == INSN
-         && GET_CODE (PATTERN (stop_insn)) == SEQUENCE)
-       stop_insn = next_insn (PREV_INSN (stop_insn));
-
-      for (insn = start_insn; insn != stop_insn;
-          insn = next_insn_no_annul (insn))
-       {
-         rtx link;
-         rtx real_insn = insn;
-
-         /* If this insn is from the target of a branch, it isn't going to
-            be used in the sequel.  If it is used in both cases, this
-            test will not be true.  */
-         if (INSN_FROM_TARGET_P (insn))
-           continue;
-
-         /* If this insn is a USE made by update_block, we care about the
-            underlying insn.  */
-         if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == USE
-             && GET_RTX_CLASS (GET_CODE (XEXP (PATTERN (insn), 0))) == 'i')
-             real_insn = XEXP (PATTERN (insn), 0);
-
-         if (GET_CODE (real_insn) == CALL_INSN)
-           {
-             /* CALL clobbers all call-used regs that aren't fixed except
-                sp, ap, and fp.  Do this before setting the result of the
-                call live.  */
-             for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-               if (call_used_regs[i]
-                   && i != STACK_POINTER_REGNUM && i != FRAME_POINTER_REGNUM
-                   && i != ARG_POINTER_REGNUM
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
-                   && i != HARD_FRAME_POINTER_REGNUM
-#endif
-#if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
-                   && ! (i == ARG_POINTER_REGNUM && fixed_regs[i])
-#endif
-#ifdef PIC_OFFSET_TABLE_REGNUM
-                   && ! (i == PIC_OFFSET_TABLE_REGNUM && flag_pic)
-#endif
-                   )
-                 CLEAR_HARD_REG_BIT (current_live_regs, i);
-
-             /* A CALL_INSN sets any global register live, since it may
-                have been modified by the call.  */
-             for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-               if (global_regs[i])
-                 SET_HARD_REG_BIT (current_live_regs, i);
-           }
-
-         /* Mark anything killed in an insn to be deadened at the next
-            label.  Ignore USE insns; the only REG_DEAD notes will be for
-            parameters.  But they might be early.  A CALL_INSN will usually
-            clobber registers used for parameters.  It isn't worth bothering
-            with the unlikely case when it won't.  */
-         if ((GET_CODE (real_insn) == INSN
-              && GET_CODE (PATTERN (real_insn)) != USE
-              && GET_CODE (PATTERN (real_insn)) != CLOBBER)
-             || GET_CODE (real_insn) == JUMP_INSN
-             || GET_CODE (real_insn) == CALL_INSN)
-           {
-             for (link = REG_NOTES (real_insn); link; link = XEXP (link, 1))
-               if (REG_NOTE_KIND (link) == REG_DEAD
-                   && GET_CODE (XEXP (link, 0)) == REG
-                   && REGNO (XEXP (link, 0)) < FIRST_PSEUDO_REGISTER)
-                 {
-                   int first_regno = REGNO (XEXP (link, 0));
-                   int last_regno
-                     = (first_regno
-                        + HARD_REGNO_NREGS (first_regno,
-                                            GET_MODE (XEXP (link, 0))));
-                        
-                   for (i = first_regno; i < last_regno; i++)
-                     SET_HARD_REG_BIT (pending_dead_regs, i);
-                 }
-
-             note_stores (PATTERN (real_insn), update_live_status);
-
-             /* If any registers were unused after this insn, kill them.
-                These notes will always be accurate.  */
-             for (link = REG_NOTES (real_insn); link; link = XEXP (link, 1))
-               if (REG_NOTE_KIND (link) == REG_UNUSED
-                   && GET_CODE (XEXP (link, 0)) == REG
-                   && REGNO (XEXP (link, 0)) < FIRST_PSEUDO_REGISTER)
-                 {
-                   int first_regno = REGNO (XEXP (link, 0));
-                   int last_regno
-                     = (first_regno
-                        + HARD_REGNO_NREGS (first_regno,
-                                            GET_MODE (XEXP (link, 0))));
-                        
-                   for (i = first_regno; i < last_regno; i++)
-                     CLEAR_HARD_REG_BIT (current_live_regs, i);
-                 }
-           }
-
-         else if (GET_CODE (real_insn) == CODE_LABEL)
-           {
-             /* A label clobbers the pending dead registers since neither
-                reload nor jump will propagate a value across a label.  */
-             AND_COMPL_HARD_REG_SET (current_live_regs, pending_dead_regs);
-             CLEAR_HARD_REG_SET (pending_dead_regs);
-           }
-
-         /* The beginning of the epilogue corresponds to the end of the
-            RTL chain when there are no epilogue insns.  Certain resources
-            are implicitly required at that point.  */
-         else if (GET_CODE (real_insn) == NOTE
-                  && NOTE_LINE_NUMBER (real_insn) == NOTE_INSN_EPILOGUE_BEG)
-           IOR_HARD_REG_SET (current_live_regs, start_of_epilogue_needs.regs);
-       }
-
-      COPY_HARD_REG_SET (res->regs, current_live_regs);
-      tinfo->block = b;
-      tinfo->bb_tick = bb_ticks[b];
-    }
-  else
-    /* We didn't find the start of a basic block.  Assume everything
-       in use.  This should happen only extremely rarely.  */
-    SET_HARD_REG_SET (res->regs);
-
-  CLEAR_RESOURCE (&set);
-  CLEAR_RESOURCE (&needed);
-
-  jump_insn = find_dead_or_set_registers (target, res, &jump_target, 0,
-                                         set, needed);
-
-  /* If we hit an unconditional branch, we have another way of finding out
-     what is live: we can see what is live at the branch target and include
-     anything used but not set before the branch.  The only things that are
-     live are those that are live using the above test and the test below.  */
-
-  if (jump_insn)
-    {
-      struct resources new_resources;
-      rtx stop_insn = next_active_insn (jump_insn);
-
-      mark_target_live_regs (next_active_insn (jump_target), &new_resources);
-      CLEAR_RESOURCE (&set);
-      CLEAR_RESOURCE (&needed);
-
-      /* Include JUMP_INSN in the needed registers.  */
-      for (insn = target; insn != stop_insn; insn = next_active_insn (insn))
-       {
-         mark_referenced_resources (insn, &needed, 1);
-
-         COPY_HARD_REG_SET (scratch, needed.regs);
-         AND_COMPL_HARD_REG_SET (scratch, set.regs);
-         IOR_HARD_REG_SET (new_resources.regs, scratch);
-
-         mark_set_resources (insn, &set, 0, 1);
-       }
-
-      AND_HARD_REG_SET (res->regs, new_resources.regs);
-    }
-
-  COPY_HARD_REG_SET (tinfo->live_regs, res->regs);
-}
-\f
 /* Scan a function looking for insns that need a delay slot and find insns to
    put into the delay slot.
 
@@ -3082,10 +2022,10 @@ fill_simple_delay_slots (non_jumps_p)
          || (GET_CODE (insn) != JUMP_INSN && ! non_jumps_p))
        continue;
      
-      if (GET_CODE (insn) == JUMP_INSN)
-       flags = get_jump_flags (insn, JUMP_LABEL (insn));
-      else
-       flags = get_jump_flags (insn, NULL_RTX);
+      /* It may have been that this insn used to need delay slots, but
+        now doesn't; ignore in that case.  This can happen, for example,
+        on the HP PA RISC, where the number of delay slots depends on
+        what insns are nearby.  */
       slots_to_fill = num_delay_slots (insn);
 
       /* Some machine description have defined instructions to have
@@ -3123,6 +2063,11 @@ fill_simple_delay_slots (non_jumps_p)
       slots_filled = 0;
       delay_list = 0;
 
+      if (GET_CODE (insn) == JUMP_INSN)
+       flags = get_jump_flags (insn, JUMP_LABEL (insn));
+      else
+       flags = get_jump_flags (insn, NULL_RTX);
+
       if ((trial = next_active_insn (insn))
          && GET_CODE (trial) == JUMP_INSN
          && simplejump_p (trial)
@@ -3195,8 +2140,7 @@ fill_simple_delay_slots (non_jumps_p)
                  && ! insn_sets_resource_p (trial, &needed, 1)
 #ifdef HAVE_cc0
                  /* Can't separate set of cc0 from its use.  */
-                 && ! (reg_mentioned_p (cc0_rtx, pat)
-                       && ! sets_cc0_p (cc0_rtx, pat))
+                 && ! (reg_mentioned_p (cc0_rtx, pat) && ! sets_cc0_p (pat))
 #endif
                  )
                {
@@ -3314,9 +2258,11 @@ fill_simple_delay_slots (non_jumps_p)
                    break;
                  else if (JUMP_LABEL (trial_delay) != target)
                    {
-                     mark_target_live_regs
-                       (next_active_insn (JUMP_LABEL (trial_delay)),
-                        &needed_at_jump);
+                     rtx ninsn = 
+                       next_active_insn (JUMP_LABEL (trial_delay));
+
+                     mark_target_live_regs (get_insns (), ninsn,
+                                            &needed_at_jump);
                      needed.memory |= needed_at_jump.memory;
                      needed.unch_memory |= needed_at_jump.unch_memory;
                      IOR_HARD_REG_SET (needed.regs, needed_at_jump.regs);
@@ -3502,7 +2448,7 @@ fill_simple_delay_slots (non_jumps_p)
              current_function_epilogue_delay_list
                = gen_rtx_INSN_LIST (VOIDmode, trial,
                                     current_function_epilogue_delay_list);
-             mark_referenced_resources (trial, &end_of_function_needs, 1);
+             mark_end_of_function_resources (trial, 1);
              update_block (trial, trial);
              delete_insn (trial);
 
@@ -3584,7 +2530,7 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
   if (condition == const_true_rtx)
     CLEAR_RESOURCE (&opposite_needed);
   else
-    mark_target_live_regs (opposite_thread, &opposite_needed);
+    mark_target_live_regs (get_insns (), opposite_thread, &opposite_needed);
 
   /* If the insn at THREAD can be split, do it here to avoid having to
      update THREAD and NEW_THREAD if it is done in the loop below.  Also
@@ -3875,8 +2821,7 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
                                   insn);
 
          if (recog_memoized (ninsn) < 0
-             || (insn_extract (ninsn),
-                 ! constrain_operands (INSN_CODE (ninsn), 1)))
+             || (extract_insn (ninsn), ! constrain_operands (1)))
            {
              delete_insn (ninsn);
              return 0;
@@ -3985,7 +2930,7 @@ fill_eager_delay_slots ()
         allows the port to favor filling the delay slot of the call with
         the unconditional jump.  */
       if (slots_to_fill == 0)
-        continue;
+       continue;
 
       slots_filled = 0;
       target_label = JUMP_LABEL (insn);
@@ -4164,7 +3109,7 @@ relax_delay_slots (first)
          && (other = prev_active_insn (insn)) != 0
          && (condjump_p (other) || condjump_in_parallel_p (other))
          && no_labels_between_p (other, insn)
-         && 0 < mostly_true_jump (other,
+         && 0 > mostly_true_jump (other,
                                   get_branch_condition (other,
                                                         JUMP_LABEL (other))))
        {
@@ -4201,6 +3146,40 @@ relax_delay_slots (first)
          continue;
        }
 
+      /* See if we have a RETURN insn with a filled delay slot followed
+        by a RETURN insn with an unfilled a delay slot.  If so, we can delete
+        the first RETURN (but not it's delay insn).  This gives the same
+        effect in fewer instructions.
+
+        Only do so if optimizing for size since this results in slower, but
+        smaller code.  */
+      if (optimize_size
+         && GET_CODE (PATTERN (delay_insn)) == RETURN
+         && next
+         && GET_CODE (next) == JUMP_INSN
+         && GET_CODE (PATTERN (next)) == RETURN)
+       {
+         int i;
+
+         /* Delete the RETURN and just execute the delay list insns.
+
+            We do this by deleting the INSN containing the SEQUENCE, then
+            re-emitting the insns separately, and then deleting the RETURN.
+            This allows the count of the jump target to be properly
+            decremented.  */
+
+         /* Clear the from target bit, since these insns are no longer
+            in delay slots.  */
+         for (i = 0; i < XVECLEN (pat, 0); i++)
+           INSN_FROM_TARGET_P (XVECEXP (pat, 0, i)) = 0;
+
+         trial = PREV_INSN (insn);
+         delete_insn (insn);
+         emit_insn_after (pat, trial);
+         delete_scheduled_jump (delay_insn);
+         continue;
+       }
+
       /* Now look only at the cases where we have a filled JUMP_INSN.  */
       if (GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) != JUMP_INSN
          || ! (condjump_p (XVECEXP (PATTERN (insn), 0, 0))
@@ -4587,80 +3566,11 @@ dbr_schedule (first, file)
        redirect_jump (insn, target);
     }
 
-  /* Indicate what resources are required to be valid at the end of the current
-     function.  The condition code never is and memory always is.  If the
-     frame pointer is needed, it is and so is the stack pointer unless
-     EXIT_IGNORE_STACK is non-zero.  If the frame pointer is not needed, the
-     stack pointer is.  Registers used to return the function value are
-     needed.  Registers holding global variables are needed.  */
-
-  end_of_function_needs.cc = 0;
-  end_of_function_needs.memory = 1;
-  end_of_function_needs.unch_memory = 0;
-  CLEAR_HARD_REG_SET (end_of_function_needs.regs);
-
-  if (frame_pointer_needed)
-    {
-      SET_HARD_REG_BIT (end_of_function_needs.regs, FRAME_POINTER_REGNUM);
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
-      SET_HARD_REG_BIT (end_of_function_needs.regs, HARD_FRAME_POINTER_REGNUM);
-#endif
-#ifdef EXIT_IGNORE_STACK
-      if (! EXIT_IGNORE_STACK
-         || current_function_sp_is_unchanging)
-#endif
-       SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM);
-    }
-  else
-    SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM);
-
-  if (current_function_return_rtx != 0)
-    mark_referenced_resources (current_function_return_rtx,
-                              &end_of_function_needs, 1);
-
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    if (global_regs[i]
-#ifdef EPILOGUE_USES
-       || EPILOGUE_USES (i)
-#endif
-       )
-      SET_HARD_REG_BIT (end_of_function_needs.regs, i);
-
-  /* The registers required to be live at the end of the function are
-     represented in the flow information as being dead just prior to
-     reaching the end of the function.  For example, the return of a value
-     might be represented by a USE of the return register immediately
-     followed by an unconditional jump to the return label where the
-     return label is the end of the RTL chain.  The end of the RTL chain
-     is then taken to mean that the return register is live.
-
-     This sequence is no longer maintained when epilogue instructions are
-     added to the RTL chain.  To reconstruct the original meaning, the
-     start of the epilogue (NOTE_INSN_EPILOGUE_BEG) is regarded as the
-     point where these registers become live (start_of_epilogue_needs).
-     If epilogue instructions are present, the registers set by those
-     instructions won't have been processed by flow.  Thus, those
-     registers are additionally required at the end of the RTL chain
-     (end_of_function_needs).  */
-
-  start_of_epilogue_needs = end_of_function_needs;
-
-  while ((epilogue_insn = next_nonnote_insn (epilogue_insn)))
-    mark_set_resources (epilogue_insn, &end_of_function_needs, 0, 1);
+  init_resource_info (epilogue_insn);
 
   /* Show we haven't computed an end-of-function label yet.  */
   end_of_function_label = 0;
 
-  /* Allocate and initialize the tables used by mark_target_live_regs.  */
-  target_hash_table
-    = (struct target_info **) alloca ((TARGET_HASH_PRIME
-                                      * sizeof (struct target_info *)));
-  bzero ((char *) target_hash_table,
-        TARGET_HASH_PRIME * sizeof (struct target_info *));
-
-  bb_ticks = (int *) alloca (n_basic_blocks * sizeof (int));
-  bzero ((char *) bb_ticks, n_basic_blocks * sizeof (int));
-
   /* Initialize the statistics for this function.  */
   bzero ((char *) num_insns_needing_delays, sizeof num_insns_needing_delays);
   bzero ((char *) num_filled_delays, sizeof num_filled_delays);
@@ -4764,5 +3674,6 @@ dbr_schedule (first, file)
                                            GEN_INT (pred_flags),
                                            REG_NOTES (insn));
     }
+  free_resource_info ();
 }
 #endif /* DELAY_SLOTS */