OSDN Git Service

Refine previous change.
[pf3gnuchains/gcc-fork.git] / gcc / reorg.c
index 059bf75..97d02e9 100644 (file)
@@ -1,6 +1,6 @@
 /* Perform instruction reorganizations for delay slot filling.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu).
    Hacked by Michael Tiemann (tiemann@cygnus.com).
@@ -115,7 +115,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "toplev.h"
+#include "diagnostic-core.h"
 #include "rtl.h"
 #include "tm_p.h"
 #include "expr.h"
@@ -173,8 +173,8 @@ static int max_uid;
 
 static int stop_search_p (rtx, int);
 static int resource_conflicts_p (struct resources *, struct resources *);
-static int insn_references_resource_p (rtx, struct resources *, int);
-static int insn_sets_resource_p (rtx, struct resources *, int);
+static int insn_references_resource_p (rtx, struct resources *, bool);
+static int insn_sets_resource_p (rtx, struct resources *, bool);
 static rtx find_end_label (void);
 static rtx emit_delay_sequence (rtx, rtx, int);
 static rtx add_to_delay_list (rtx, rtx);
@@ -220,6 +220,17 @@ static void relax_delay_slots (rtx);
 static void make_return_insns (rtx);
 #endif
 \f
+/* A wrapper around next_active_insn which takes care to return ret_rtx
+   unchanged.  */
+
+static rtx
+first_active_target_insn (rtx insn)
+{
+  if (ANY_RETURN_P (insn))
+    return insn;
+  return next_active_insn (insn);
+}
+\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.
    In all cases, jumps terminate the search.  */
@@ -297,7 +308,7 @@ resource_conflicts_p (struct resources *res1, struct resources *res2)
 
 static int
 insn_references_resource_p (rtx insn, struct resources *res,
-                           int include_delayed_effects)
+                           bool include_delayed_effects)
 {
   struct resources insn_res;
 
@@ -313,7 +324,7 @@ insn_references_resource_p (rtx insn, struct resources *res,
 
 static int
 insn_sets_resource_p (rtx insn, struct resources *res,
-                     int include_delayed_effects)
+                     bool include_delayed_effects)
 {
   struct resources insn_sets;
 
@@ -437,6 +448,7 @@ find_end_label (void)
              /* The return we make may have delay slots too.  */
              rtx insn = gen_return ();
              insn = emit_jump_insn (insn);
+             JUMP_LABEL (insn) = ret_rtx;
              emit_barrier ();
              if (num_delay_slots (insn) > 0)
                obstack_ptr_grow (&unfilled_slots_obstack, insn);
@@ -824,7 +836,7 @@ optimize_skip (rtx insn)
              || GET_CODE (PATTERN (next_trial)) == RETURN))
        {
          rtx target_label = JUMP_LABEL (next_trial);
-         if (target_label == 0)
+         if (ANY_RETURN_P (target_label))
            target_label = find_end_label ();
 
          if (target_label)
@@ -861,12 +873,12 @@ get_jump_flags (rtx insn, rtx label)
      be INSNs, CALL_INSNs, or JUMP_INSNs.  Only JUMP_INSNs have branch
      direction information, and only if they are conditional jumps.
 
-     If LABEL is zero, then there is no way to determine the branch
+     If LABEL is a return, then there is no way to determine the branch
      direction.  */
   if (JUMP_P (insn)
       && (condjump_p (insn) || condjump_in_parallel_p (insn))
+      && !ANY_RETURN_P (label)
       && INSN_UID (insn) <= max_uid
-      && label != 0
       && INSN_UID (label) <= max_uid)
     flags
       = (uid_to_ruid[INSN_UID (label)] > uid_to_ruid[INSN_UID (insn)])
@@ -921,7 +933,7 @@ rare_destination (rtx insn)
   int jump_count = 0;
   rtx next;
 
-  for (; insn; insn = next)
+  for (; insn && !ANY_RETURN_P (insn); insn = next)
     {
       if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
        insn = XVECEXP (PATTERN (insn), 0, 0);
@@ -1017,7 +1029,7 @@ mostly_true_jump (rtx jump_insn, rtx condition)
   /* Predict backward branches usually take, forward branches usually not.  If
      we don't know whether this is forward or backward, assume the branch
      will be taken, since most are.  */
-  return (target_label == 0 || INSN_UID (jump_insn) > max_uid
+  return (ANY_RETURN_P (target_label) || 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)]));
@@ -1037,10 +1049,10 @@ get_branch_condition (rtx insn, rtx target)
   if (condjump_in_parallel_p (insn))
     pat = XVECEXP (pat, 0, 0);
 
-  if (GET_CODE (pat) == RETURN)
-    return target == 0 ? const_true_rtx : 0;
+  if (ANY_RETURN_P (pat))
+    return pat == target ? const_true_rtx : 0;
 
-  else if (GET_CODE (pat) != SET || SET_DEST (pat) != pc_rtx)
+  if (GET_CODE (pat) != SET || SET_DEST (pat) != pc_rtx)
     return 0;
 
   src = SET_SRC (pat);
@@ -1048,16 +1060,12 @@ get_branch_condition (rtx insn, rtx target)
     return const_true_rtx;
 
   else if (GET_CODE (src) == IF_THEN_ELSE
-          && ((target == 0 && GET_CODE (XEXP (src, 1)) == RETURN)
-              || (GET_CODE (XEXP (src, 1)) == LABEL_REF
-                  && XEXP (XEXP (src, 1), 0) == target))
+          && XEXP (XEXP (src, 1), 0) == target
           && XEXP (src, 2) == pc_rtx)
     return XEXP (src, 0);
 
   else if (GET_CODE (src) == IF_THEN_ELSE
-          && ((target == 0 && GET_CODE (XEXP (src, 2)) == RETURN)
-              || (GET_CODE (XEXP (src, 2)) == LABEL_REF
-                  && XEXP (XEXP (src, 2), 0) == target))
+          && XEXP (XEXP (src, 2), 0) == target
           && XEXP (src, 1) == pc_rtx)
     {
       enum rtx_code rev;
@@ -1246,7 +1254,7 @@ steal_delay_list_from_target (rtx insn, rtx condition, rtx seq,
       rtx trial = XEXP (temp, 0);
 
       mark_set_resources (trial, &cc_set, 0, MARK_SRC_DEST_CALL);
-      if (insn_references_resource_p (XVECEXP (seq , 0, 0), &cc_set, 0))
+      if (insn_references_resource_p (XVECEXP (seq , 0, 0), &cc_set, false))
        return delay_list;
     }
 
@@ -1268,9 +1276,9 @@ steal_delay_list_from_target (rtx insn, rtx condition, rtx seq,
       rtx trial = XVECEXP (seq, 0, i);
       int flags;
 
-      if (insn_references_resource_p (trial, sets, 0)
-         || insn_sets_resource_p (trial, needed, 0)
-         || insn_sets_resource_p (trial, sets, 0)
+      if (insn_references_resource_p (trial, sets, false)
+         || insn_sets_resource_p (trial, needed, false)
+         || insn_sets_resource_p (trial, sets, false)
 #ifdef HAVE_cc0
          /* If TRIAL sets CC0, we can't copy it, so we can't steal this
             delay list.  */
@@ -1293,7 +1301,7 @@ steal_delay_list_from_target (rtx insn, rtx condition, rtx seq,
 
       if (! must_annul
          && ((condition == const_true_rtx
-              || (! insn_sets_resource_p (trial, other_needed, 0)
+              || (! insn_sets_resource_p (trial, other_needed, false)
                   && ! may_trap_or_fault_p (PATTERN (trial)))))
          ? eligible_for_delay (insn, total_slots_filled, trial, flags)
          : (must_annul || (delay_list == NULL && new_delay_list == NULL))
@@ -1318,7 +1326,7 @@ steal_delay_list_from_target (rtx insn, rtx condition, rtx seq,
     }
 
   /* Show the place to which we will be branching.  */
-  *pnew_thread = next_active_insn (JUMP_LABEL (XVECEXP (seq, 0, 0)));
+  *pnew_thread = first_active_target_insn (JUMP_LABEL (XVECEXP (seq, 0, 0)));
 
   /* Add any new insns to the delay list and update the count of the
      number of slots filled.  */
@@ -1368,9 +1376,9 @@ steal_delay_list_from_fallthrough (rtx insn, rtx condition, rtx seq,
 
       /* If TRIAL sets CC0, stealing it will move it too far from the use
         of CC0.  */
-      if (insn_references_resource_p (trial, sets, 0)
-         || insn_sets_resource_p (trial, needed, 0)
-         || insn_sets_resource_p (trial, sets, 0)
+      if (insn_references_resource_p (trial, sets, false)
+         || insn_sets_resource_p (trial, needed, false)
+         || insn_sets_resource_p (trial, sets, false)
 #ifdef HAVE_cc0
          || sets_cc0_p (PATTERN (trial))
 #endif
@@ -1387,7 +1395,7 @@ steal_delay_list_from_fallthrough (rtx insn, rtx condition, rtx seq,
 
       if (! must_annul
          && ((condition == const_true_rtx
-              || (! insn_sets_resource_p (trial, other_needed, 0)
+              || (! insn_sets_resource_p (trial, other_needed, false)
                   && ! may_trap_or_fault_p (PATTERN (trial)))))
          ? eligible_for_delay (insn, *pslots_filled, trial, flags)
          : (must_annul || delay_list == NULL) && (must_annul = 1,
@@ -1448,7 +1456,8 @@ try_merge_delay_insns (rtx insn, rtx thread)
   if (! annul_p)
     for (i = 1 ; i < num_slots; i++)
       if (XVECEXP (PATTERN (insn), 0, i))
-       mark_referenced_resources (XVECEXP (PATTERN (insn), 0, i), &needed, 1);
+       mark_referenced_resources (XVECEXP (PATTERN (insn), 0, i), &needed,
+                                  true);
 
   for (trial = thread; !stop_search_p (trial, 1); trial = next_trial)
     {
@@ -1467,9 +1476,9 @@ try_merge_delay_insns (rtx insn, rtx thread)
          /* We can't share an insn that sets cc0.  */
          && ! sets_cc0_p (pat)
 #endif
-         && ! insn_references_resource_p (trial, &set, 1)
-         && ! insn_sets_resource_p (trial, &set, 1)
-         && ! insn_sets_resource_p (trial, &needed, 1)
+         && ! insn_references_resource_p (trial, &set, true)
+         && ! insn_sets_resource_p (trial, &set, true)
+         && ! insn_sets_resource_p (trial, &needed, true)
          && (trial = try_split (pat, trial, 0)) != 0
          /* Update next_trial, in case try_split succeeded.  */
          && (next_trial = next_nonnote_insn (trial))
@@ -1500,7 +1509,7 @@ try_merge_delay_insns (rtx insn, rtx thread)
        }
 
       mark_set_resources (trial, &set, 0, MARK_SRC_DEST_CALL);
-      mark_referenced_resources (trial, &needed, 1);
+      mark_referenced_resources (trial, &needed, true);
     }
 
   /* See if we stopped on a filled insn.  If we did, try to see if its
@@ -1515,15 +1524,15 @@ try_merge_delay_insns (rtx insn, rtx thread)
 
       /* Account for resources set/needed by the filled insn.  */
       mark_set_resources (filled_insn, &set, 0, MARK_SRC_DEST_CALL);
-      mark_referenced_resources (filled_insn, &needed, 1);
+      mark_referenced_resources (filled_insn, &needed, true);
 
       for (i = 1; i < XVECLEN (pat, 0); i++)
        {
          rtx dtrial = XVECEXP (pat, 0, i);
 
-         if (! insn_references_resource_p (dtrial, &set, 1)
-             && ! insn_sets_resource_p (dtrial, &set, 1)
-             && ! insn_sets_resource_p (dtrial, &needed, 1)
+         if (! insn_references_resource_p (dtrial, &set, true)
+             && ! insn_sets_resource_p (dtrial, &set, true)
+             && ! insn_sets_resource_p (dtrial, &needed, true)
 #ifdef HAVE_cc0
              && ! sets_cc0_p (PATTERN (dtrial))
 #endif
@@ -1554,7 +1563,7 @@ try_merge_delay_insns (rtx insn, rtx thread)
              /* Keep track of the set/referenced resources for the delay
                 slots of any trial insns we encounter.  */
              mark_set_resources (dtrial, &set, 0, MARK_SRC_DEST_CALL);
-             mark_referenced_resources (dtrial, &needed, 1);
+             mark_referenced_resources (dtrial, &needed, true);
            }
        }
     }
@@ -1629,13 +1638,14 @@ redundant_insn (rtx insn, rtx target, rtx delay_list)
   for (trial = PREV_INSN (target),
         insns_to_search = MAX_DELAY_SLOT_INSN_SEARCH;
        trial && insns_to_search > 0;
-       trial = PREV_INSN (trial), --insns_to_search)
+       trial = PREV_INSN (trial))
     {
       if (LABEL_P (trial))
        return 0;
 
-      if (! INSN_P (trial))
+      if (!NONDEBUG_INSN_P (trial))
        continue;
+      --insns_to_search;
 
       pat = PATTERN (trial);
       if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
@@ -1690,7 +1700,7 @@ redundant_insn (rtx insn, rtx target, rtx delay_list)
   CLEAR_RESOURCE (&needed);
   CLEAR_RESOURCE (&set);
   mark_set_resources (insn, &set, 0, MARK_SRC_DEST_CALL);
-  mark_referenced_resources (insn, &needed, 1);
+  mark_referenced_resources (insn, &needed, true);
 
   /* If TARGET is a SEQUENCE, get the main insn.  */
   if (NONJUMP_INSN_P (target) && GET_CODE (PATTERN (target)) == SEQUENCE)
@@ -1702,8 +1712,8 @@ redundant_insn (rtx insn, rtx target, rtx delay_list)
 #endif
       /* The insn requiring the delay may not set anything needed or set by
         INSN.  */
-      || insn_sets_resource_p (target_main, &needed, 1)
-      || insn_sets_resource_p (target_main, &set, 1))
+      || insn_sets_resource_p (target_main, &needed, true)
+      || insn_sets_resource_p (target_main, &set, true))
     return 0;
 
   /* Insns we pass may not set either NEEDED or SET, so merge them for
@@ -1717,14 +1727,15 @@ redundant_insn (rtx insn, rtx target, rtx delay_list)
 
   while (delay_list)
     {
-      if (insn_sets_resource_p (XEXP (delay_list, 0), &needed, 1))
+      if (insn_sets_resource_p (XEXP (delay_list, 0), &needed, true))
        return 0;
       delay_list = XEXP (delay_list, 1);
     }
 
   if (NONJUMP_INSN_P (target) && GET_CODE (PATTERN (target)) == SEQUENCE)
     for (i = 1; i < XVECLEN (PATTERN (target), 0); i++)
-      if (insn_sets_resource_p (XVECEXP (PATTERN (target), 0, i), &needed, 1))
+      if (insn_sets_resource_p (XVECEXP (PATTERN (target), 0, i), &needed,
+                               true))
        return 0;
 
   /* Scan backwards until we reach a label or an insn that uses something
@@ -1733,10 +1744,11 @@ redundant_insn (rtx insn, rtx target, rtx delay_list)
   for (trial = PREV_INSN (target),
         insns_to_search = MAX_DELAY_SLOT_INSN_SEARCH;
        trial && !LABEL_P (trial) && insns_to_search > 0;
-       trial = PREV_INSN (trial), --insns_to_search)
+       trial = PREV_INSN (trial))
     {
-      if (!INSN_P (trial))
+      if (!NONDEBUG_INSN_P (trial))
        continue;
+      --insns_to_search;
 
       pat = PATTERN (trial);
       if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
@@ -1783,13 +1795,13 @@ redundant_insn (rtx insn, rtx target, rtx delay_list)
                 we must stop if it sets anything needed or set by INSN.  */
              if ((! INSN_ANNULLED_BRANCH_P (XVECEXP (pat, 0, 0))
                   || ! INSN_FROM_TARGET_P (candidate))
-                 && insn_sets_resource_p (candidate, &needed, 1))
+                 && insn_sets_resource_p (candidate, &needed, true))
                return 0;
            }
 
          /* If the insn requiring the delay slot conflicts with INSN, we
             must stop.  */
-         if (insn_sets_resource_p (XVECEXP (pat, 0, 0), &needed, 1))
+         if (insn_sets_resource_p (XVECEXP (pat, 0, 0), &needed, true))
            return 0;
        }
       else
@@ -1800,7 +1812,7 @@ redundant_insn (rtx insn, rtx target, rtx delay_list)
            return trial;
 
          /* Can't go any further if TRIAL conflicts with INSN.  */
-         if (insn_sets_resource_p (trial, &needed, 1))
+         if (insn_sets_resource_p (trial, &needed, true))
            return 0;
        }
     }
@@ -1823,7 +1835,7 @@ own_thread_p (rtx thread, rtx label, int allow_fallthrough)
   rtx insn;
 
   /* We don't own the function end.  */
-  if (thread == 0)
+  if (thread == 0 || ANY_RETURN_P (thread))
     return 0;
 
   /* Get the first active insn, or THREAD, if it is an active insn.  */
@@ -2138,7 +2150,7 @@ fill_simple_delay_slots (int non_jumps_p)
          CLEAR_RESOURCE (&needed);
          CLEAR_RESOURCE (&set);
          mark_set_resources (insn, &set, 0, MARK_SRC_DEST);
-         mark_referenced_resources (insn, &needed, 0);
+         mark_referenced_resources (insn, &needed, false);
 
          for (trial = prev_nonnote_insn (insn); ! stop_search_p (trial, 1);
               trial = next_trial)
@@ -2148,15 +2160,15 @@ fill_simple_delay_slots (int non_jumps_p)
              /* This must be an INSN or CALL_INSN.  */
              pat = PATTERN (trial);
 
-             /* USE and CLOBBER at this level was just for flow; ignore it.  */
+             /* Stand-alone USE and CLOBBER are just for flow.  */
              if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
                continue;
 
              /* Check for resource conflict first, to avoid unnecessary
                 splitting.  */
-             if (! insn_references_resource_p (trial, &set, 1)
-                 && ! insn_sets_resource_p (trial, &set, 1)
-                 && ! insn_sets_resource_p (trial, &needed, 1)
+             if (! insn_references_resource_p (trial, &set, true)
+                 && ! insn_sets_resource_p (trial, &set, true)
+                 && ! insn_sets_resource_p (trial, &needed, true)
 #ifdef HAVE_cc0
                  /* Can't separate set of cc0 from its use.  */
                  && ! (reg_mentioned_p (cc0_rtx, pat) && ! sets_cc0_p (pat))
@@ -2184,7 +2196,7 @@ fill_simple_delay_slots (int non_jumps_p)
                }
 
              mark_set_resources (trial, &set, 0, MARK_SRC_DEST_CALL);
-             mark_referenced_resources (trial, &needed, 1);
+             mark_referenced_resources (trial, &needed, true);
            }
        }
 
@@ -2241,7 +2253,7 @@ fill_simple_delay_slots (int non_jumps_p)
          && (!JUMP_P (insn)
              || ((condjump_p (insn) || condjump_in_parallel_p (insn))
                  && ! simplejump_p (insn)
-                 && JUMP_LABEL (insn) != 0)))
+                 && !ANY_RETURN_P (JUMP_LABEL (insn)))))
        {
          /* Invariant: If insn is a JUMP_INSN, the insn's jump
             label.  Otherwise, zero.  */
@@ -2255,27 +2267,24 @@ fill_simple_delay_slots (int non_jumps_p)
          if (CALL_P (insn))
            {
              mark_set_resources (insn, &set, 0, MARK_SRC_DEST_CALL);
-             mark_referenced_resources (insn, &needed, 1);
+             mark_referenced_resources (insn, &needed, true);
              maybe_never = 1;
            }
          else
            {
              mark_set_resources (insn, &set, 0, MARK_SRC_DEST_CALL);
-             mark_referenced_resources (insn, &needed, 1);
+             mark_referenced_resources (insn, &needed, true);
              if (JUMP_P (insn))
                target = JUMP_LABEL (insn);
            }
 
-         if (target == 0)
-           for (trial = next_nonnote_insn (insn); trial; trial = next_trial)
+         if (target == 0 || ANY_RETURN_P (target))
+           for (trial = next_nonnote_insn (insn); !stop_search_p (trial, 1);
+                trial = next_trial)
              {
                next_trial = next_nonnote_insn (trial);
 
-               if (LABEL_P (trial)
-                   || BARRIER_P (trial))
-                 break;
-
-               /* We must have an INSN, JUMP_INSN, or CALL_INSN.  */
+               /* This must be an INSN or CALL_INSN.  */
                pat = PATTERN (trial);
 
                /* Stand-alone USE and CLOBBER are just for flow.  */
@@ -2289,16 +2298,16 @@ fill_simple_delay_slots (int non_jumps_p)
                else
                  trial_delay = trial;
 
-               /* Stop our search when seeing an unconditional jump.  */
+               /* Stop our search when seeing a jump.  */
                if (JUMP_P (trial_delay))
                  break;
 
                /* See if we have a resource problem before we try to
                   split.  */
                if (GET_CODE (pat) != SEQUENCE
-                   && ! insn_references_resource_p (trial, &set, 1)
-                   && ! insn_sets_resource_p (trial, &set, 1)
-                   && ! insn_sets_resource_p (trial, &needed, 1)
+                   && ! insn_references_resource_p (trial, &set, true)
+                   && ! insn_sets_resource_p (trial, &set, true)
+                   && ! insn_sets_resource_p (trial, &needed, true)
 #ifdef HAVE_cc0
                    && ! (reg_mentioned_p (cc0_rtx, pat) && ! sets_cc0_p (pat))
 #endif
@@ -2322,7 +2331,7 @@ fill_simple_delay_slots (int non_jumps_p)
                  }
 
                mark_set_resources (trial, &set, 0, MARK_SRC_DEST_CALL);
-               mark_referenced_resources (trial, &needed, 1);
+               mark_referenced_resources (trial, &needed, true);
 
                /* Ensure we don't put insns between the setting of cc and the
                   comparison by moving a setting of cc into an earlier delay
@@ -2342,16 +2351,16 @@ fill_simple_delay_slots (int non_jumps_p)
             Don't do this if the insn at the branch target is a branch.  */
          if (slots_to_fill != slots_filled
              && trial
-             && JUMP_P (trial)
+             && jump_to_label_p (trial)
              && simplejump_p (trial)
              && (target == 0 || JUMP_LABEL (trial) == target)
              && (next_trial = next_active_insn (JUMP_LABEL (trial))) != 0
              && ! (NONJUMP_INSN_P (next_trial)
                    && GET_CODE (PATTERN (next_trial)) == SEQUENCE)
              && !JUMP_P (next_trial)
-             && ! insn_references_resource_p (next_trial, &set, 1)
-             && ! insn_sets_resource_p (next_trial, &set, 1)
-             && ! insn_sets_resource_p (next_trial, &needed, 1)
+             && ! insn_references_resource_p (next_trial, &set, true)
+             && ! insn_sets_resource_p (next_trial, &set, true)
+             && ! insn_sets_resource_p (next_trial, &needed, true)
 #ifdef HAVE_cc0
              && ! reg_mentioned_p (cc0_rtx, PATTERN (next_trial))
 #endif
@@ -2458,9 +2467,9 @@ fill_simple_delay_slots (int non_jumps_p)
       if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
        continue;
 
-      if (! insn_references_resource_p (trial, &set, 1)
-         && ! insn_sets_resource_p (trial, &needed, 1)
-         && ! insn_sets_resource_p (trial, &set, 1)
+      if (! insn_references_resource_p (trial, &set, true)
+         && ! insn_sets_resource_p (trial, &needed, true)
+         && ! insn_sets_resource_p (trial, &set, true)
 #ifdef HAVE_cc0
          /* Don't want to mess with cc0 here.  */
          && ! reg_mentioned_p (cc0_rtx, pat)
@@ -2476,7 +2485,7 @@ fill_simple_delay_slots (int non_jumps_p)
              crtl->epilogue_delay_list
                = gen_rtx_INSN_LIST (VOIDmode, trial,
                                     crtl->epilogue_delay_list);
-             mark_end_of_function_resources (trial, 1);
+             mark_end_of_function_resources (trial, true);
              update_block (trial, trial);
              delete_related_insns (trial);
 
@@ -2490,7 +2499,7 @@ fill_simple_delay_slots (int non_jumps_p)
        }
 
       mark_set_resources (trial, &set, 0, MARK_SRC_DEST_CALL);
-      mark_referenced_resources (trial, &needed, 1);
+      mark_referenced_resources (trial, &needed, true);
     }
 
   note_delay_statistics (slots_filled, 0);
@@ -2499,7 +2508,7 @@ fill_simple_delay_slots (int non_jumps_p)
 \f
 /* Follow any unconditional jump at LABEL;
    return the ultimate label reached by any such chain of jumps.
-   Return null if the chain ultimately leads to a return instruction.
+   Return ret_rtx if the chain ultimately leads to a return instruction.
    If LABEL is not followed by a jump, return LABEL.
    If the chain loops or we can't find end, return LABEL,
    since that tells caller to avoid changing the insn.  */
@@ -2512,29 +2521,34 @@ follow_jumps (rtx label)
   rtx value = label;
   int depth;
 
+  if (ANY_RETURN_P (label))
+    return label;
   for (depth = 0;
        (depth < 10
        && (insn = next_active_insn (value)) != 0
        && JUMP_P (insn)
-       && ((JUMP_LABEL (insn) != 0 && any_uncondjump_p (insn)
-            && onlyjump_p (insn))
+       && JUMP_LABEL (insn) != NULL_RTX
+       && ((any_uncondjump_p (insn) && onlyjump_p (insn))
            || GET_CODE (PATTERN (insn)) == RETURN)
        && (next = NEXT_INSN (insn))
        && BARRIER_P (next));
        depth++)
     {
+      rtx this_label = JUMP_LABEL (insn);
       rtx tem;
 
       /* If we have found a cycle, make the insn jump to itself.  */
-      if (JUMP_LABEL (insn) == label)
+      if (this_label == label)
        return label;
-
-      tem = next_active_insn (JUMP_LABEL (insn));
-      if (tem && (GET_CODE (PATTERN (tem)) == ADDR_VEC
-                 || GET_CODE (PATTERN (tem)) == ADDR_DIFF_VEC))
+      if (ANY_RETURN_P (this_label))
+       return this_label;
+      tem = next_active_insn (this_label);
+      if (tem
+         && (GET_CODE (PATTERN (tem)) == ADDR_VEC
+             || GET_CODE (PATTERN (tem)) == ADDR_DIFF_VEC))
        break;
 
-      value = JUMP_LABEL (insn);
+      value = this_label;
     }
   if (depth == 10)
     return label;
@@ -2586,7 +2600,7 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
 
   /* If our thread is the end of subroutine, we can't get any delay
      insns from that.  */
-  if (thread == 0)
+  if (thread == NULL_RTX || ANY_RETURN_P (thread))
     return delay_list;
 
   /* If this is an unconditional branch, nothing is needed at the
@@ -2635,9 +2649,9 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
 
       /* If TRIAL conflicts with the insns ahead of it, we lose.  Also,
         don't separate or copy insns that set and use CC0.  */
-      if (! insn_references_resource_p (trial, &set, 1)
-         && ! insn_sets_resource_p (trial, &set, 1)
-         && ! insn_sets_resource_p (trial, &needed, 1)
+      if (! insn_references_resource_p (trial, &set, true)
+         && ! insn_sets_resource_p (trial, &set, true)
+         && ! insn_sets_resource_p (trial, &needed, true)
 #ifdef HAVE_cc0
          && ! (reg_mentioned_p (cc0_rtx, pat)
                && (! own_thread || ! sets_cc0_p (pat)))
@@ -2678,7 +2692,7 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
             go into an annulled delay slot.  */
          if (!must_annul
              && (condition == const_true_rtx
-                 || (! insn_sets_resource_p (trial, &opposite_needed, 1)
+                 || (! insn_sets_resource_p (trial, &opposite_needed, true)
                      && ! may_trap_or_fault_p (pat))))
            {
              old_trial = trial;
@@ -2756,7 +2770,7 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
                              gcc_assert (REG_NOTE_KIND (note)
                                          == REG_LABEL_OPERAND);
                          }
-                     if (JUMP_P (trial) && JUMP_LABEL (trial))
+                     if (jump_to_label_p (trial))
                        LABEL_NUSES (JUMP_LABEL (trial))++;
 
                      delete_related_insns (trial);
@@ -2775,7 +2789,7 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
                              gcc_assert (REG_NOTE_KIND (note)
                                          == REG_LABEL_OPERAND);
                          }
-                     if (JUMP_P (trial) && JUMP_LABEL (trial))
+                     if (jump_to_label_p (trial))
                        LABEL_NUSES (JUMP_LABEL (trial))--;
                    }
                  else
@@ -2793,10 +2807,11 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
                         may be branching to a location that has a
                         redundant insn.  Skip any if so.  */
                      while (new_thread && ! own_thread
-                            && ! insn_sets_resource_p (new_thread, &set, 1)
-                            && ! insn_sets_resource_p (new_thread, &needed, 1)
+                            && ! insn_sets_resource_p (new_thread, &set, true)
+                            && ! insn_sets_resource_p (new_thread, &needed,
+                                                       true)
                             && ! insn_references_resource_p (new_thread,
-                                                             &set, 1)
+                                                             &set, true)
                             && (prior_insn
                                 = redundant_insn (new_thread, insn,
                                                   delay_list)))
@@ -2818,7 +2833,7 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
       /* This insn can't go into a delay slot.  */
       lose = 1;
       mark_set_resources (trial, &set, 0, MARK_SRC_DEST_CALL);
-      mark_referenced_resources (trial, &needed, 1);
+      mark_referenced_resources (trial, &needed, true);
 
       /* Ensure we don't put insns between the setting of cc and the comparison
         by moving a setting of cc into an earlier delay slot since these insns
@@ -2895,7 +2910,8 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
      depend on the destination register.  If so, try to place the opposite
      arithmetic insn after the jump insn and put the arithmetic insn in the
      delay slot.  If we can't do this, return.  */
-  if (delay_list == 0 && likely && new_thread
+  if (delay_list == 0 && likely
+      && new_thread && !ANY_RETURN_P (new_thread)
       && NONJUMP_INSN_P (new_thread)
       && GET_CODE (PATTERN (new_thread)) != ASM_INPUT
       && asm_noperands (PATTERN (new_thread)) < 0)
@@ -2928,7 +2944,7 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
          /* If this is a constant adjustment, use the same code with
             the negated constant.  Otherwise, reverse the sense of the
             arithmetic.  */
-         if (GET_CODE (other) == CONST_INT)
+         if (CONST_INT_P (other))
            new_arith = gen_rtx_fmt_ee (GET_CODE (src), GET_MODE (src), dest,
                                        negate_rtx (GET_MODE (src), other));
          else
@@ -2988,7 +3004,7 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
                                              delay_list))
        new_thread = follow_jumps (JUMP_LABEL (new_thread));
 
-      if (new_thread == 0)
+      if (ANY_RETURN_P (new_thread))
        label = find_end_label ();
       else if (LABEL_P (new_thread))
        label = new_thread;
@@ -3061,7 +3077,7 @@ fill_eager_delay_slots (void)
         them.  Then see whether the branch is likely true.  We don't need
         to do a lot of this for unconditional branches.  */
 
-      insn_at_target = next_active_insn (target_label);
+      insn_at_target = first_active_target_insn (target_label);
       own_target = own_thread_p (target_label, target_label, 0);
 
       if (condition == const_true_rtx)
@@ -3096,7 +3112,7 @@ fill_eager_delay_slots (void)
                 from the thread that was filled.  So we have to recompute
                 the next insn at the target.  */
              target_label = JUMP_LABEL (insn);
-             insn_at_target = next_active_insn (target_label);
+             insn_at_target = first_active_target_insn (target_label);
 
              delay_list
                = fill_slots_from_thread (insn, condition, fallthrough_insn,
@@ -3248,13 +3264,10 @@ delete_prior_computation (rtx note, rtx insn)
 
 /* Delete INSN and recursively delete insns that compute values used only
    by INSN.  This uses the REG_DEAD notes computed during flow analysis.
-   If we are running before flow.c, we need do nothing since flow.c will
-   delete dead code.  We also can't know if the registers being used are
-   dead or not at this point.
 
-   Otherwise, look at all our REG_DEAD notes.  If a previous insn does
-   nothing other than set a register that dies in this insn, we can delete
-   that insn as well.
+   Look at all our REG_DEAD notes.  If a previous insn does nothing other
+   than set a register that dies in this insn, we can delete that insn
+   as well.
 
    On machines with CC0, if CC0 is used in this insn, we may be able to
    delete the insn that set it.  */
@@ -3338,10 +3351,10 @@ relax_delay_slots (rtx first)
         group of consecutive labels.  */
       if (JUMP_P (insn)
          && (condjump_p (insn) || condjump_in_parallel_p (insn))
-         && (target_label = JUMP_LABEL (insn)) != 0)
+         && !ANY_RETURN_P (target_label = JUMP_LABEL (insn)))
        {
          target_label = skip_consecutive_labels (follow_jumps (target_label));
-         if (target_label == 0)
+         if (ANY_RETURN_P (target_label))
            target_label = find_end_label ();
 
          if (target_label && next_active_insn (target_label) == next
@@ -3374,7 +3387,7 @@ relax_delay_slots (rtx first)
                 invert_jump fails.  */
 
              ++LABEL_NUSES (target_label);
-             if (label)
+             if (!ANY_RETURN_P (label))
                ++LABEL_NUSES (label);
 
              if (invert_jump (insn, label, 1))
@@ -3383,7 +3396,7 @@ relax_delay_slots (rtx first)
                  next = insn;
                }
 
-             if (label)
+             if (!ANY_RETURN_P (label))
                --LABEL_NUSES (label);
 
              if (--LABEL_NUSES (target_label) == 0)
@@ -3456,9 +3469,13 @@ relax_delay_slots (rtx first)
             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.  */
+            decremented.
 
-         /* Clear the from target bit, since these insns are no longer
+            Note that we need to change the INSN_UID of the re-emitted insns
+            since it is used to hash the insns for mark_target_live_regs and
+            the re-emitted insns will no longer be wrapped up in a SEQUENCE.
+
+            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;
@@ -3466,13 +3483,10 @@ relax_delay_slots (rtx first)
          trial = PREV_INSN (insn);
          delete_related_insns (insn);
          gcc_assert (GET_CODE (pat) == SEQUENCE);
-         after = trial;
-         for (i = 0; i < XVECLEN (pat, 0); i++)
-           {
-             rtx this_insn = XVECEXP (pat, 0, i);
-             add_insn_after (this_insn, after, NULL);
-             after = this_insn;
-           }
+         add_insn_after (delay_insn, trial, NULL);
+         after = delay_insn;
+         for (i = 1; i < XVECLEN (pat, 0); i++)
+           after = emit_copy_of_insn_after (XVECEXP (pat, 0, i), after);
          delete_scheduled_jump (delay_insn);
          continue;
        }
@@ -3485,12 +3499,12 @@ relax_delay_slots (rtx first)
 
       target_label = JUMP_LABEL (delay_insn);
 
-      if (target_label)
+      if (!ANY_RETURN_P (target_label))
        {
          /* If this jump goes to another unconditional jump, thread it, but
             don't convert a jump into a RETURN here.  */
          trial = skip_consecutive_labels (follow_jumps (target_label));
-         if (trial == 0)
+         if (ANY_RETURN_P (trial))
            trial = find_end_label ();
 
          if (trial && trial != target_label
@@ -3501,8 +3515,11 @@ relax_delay_slots (rtx first)
            }
 
          /* If the first insn at TARGET_LABEL is redundant with a previous
-            insn, redirect the jump to the following insn process again.  */
-         trial = next_active_insn (target_label);
+            insn, redirect the jump to the following insn and process again.
+            We use next_real_insn instead of next_active_insn so we
+            don't skip USE-markers, or we'll end up with incorrect
+            liveness info.  */
+         trial = next_real_insn (target_label);
          if (trial && GET_CODE (PATTERN (trial)) != SEQUENCE
              && redundant_insn (trial, insn, 0)
              && ! can_throw_internal (trial))
@@ -3537,7 +3554,7 @@ relax_delay_slots (rtx first)
              && redundant_insn (XVECEXP (PATTERN (trial), 0, 1), insn, 0))
            {
              target_label = JUMP_LABEL (XVECEXP (PATTERN (trial), 0, 0));
-             if (target_label == 0)
+             if (ANY_RETURN_P (target_label))
                target_label = find_end_label ();
 
              if (target_label
@@ -3574,9 +3591,13 @@ relax_delay_slots (rtx first)
             We do this by deleting the INSN containing the SEQUENCE, then
             re-emitting the insns separately, and then deleting the jump.
             This allows the count of the jump target to be properly
-            decremented.  */
+            decremented.
+
+            Note that we need to change the INSN_UID of the re-emitted insns
+            since it is used to hash the insns for mark_target_live_regs and
+            the re-emitted insns will no longer be wrapped up in a SEQUENCE.
 
-         /* Clear the from target bit, since these insns are no longer
+            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;
@@ -3584,13 +3605,10 @@ relax_delay_slots (rtx first)
          trial = PREV_INSN (insn);
          delete_related_insns (insn);
          gcc_assert (GET_CODE (pat) == SEQUENCE);
-         after = trial;
-         for (i = 0; i < XVECLEN (pat, 0); i++)
-           {
-             rtx this_insn = XVECEXP (pat, 0, i);
-             add_insn_after (this_insn, after, NULL);
-             after = this_insn;
-           }
+         add_insn_after (delay_insn, trial, NULL);
+         after = delay_insn;
+         for (i = 1; i < XVECLEN (pat, 0); i++)
+           after = emit_copy_of_insn_after (XVECEXP (pat, 0, i), after);
          delete_scheduled_jump (delay_insn);
          continue;
        }
@@ -3623,7 +3641,7 @@ relax_delay_slots (rtx first)
          rtx label = JUMP_LABEL (next);
          rtx old_label = JUMP_LABEL (delay_insn);
 
-         if (label == 0)
+         if (ANY_RETURN_P (label))
            label = find_end_label ();
 
          /* find_end_label can generate a new label. Check this first.  */
@@ -3733,7 +3751,7 @@ make_return_insns (rtx first)
 
       /* If we can't make the jump into a RETURN, try to redirect it to the best
         RETURN and go on to the next insn.  */
-      if (! reorg_redirect_jump (jump_insn, NULL_RTX))
+      if (! reorg_redirect_jump (jump_insn, ret_rtx))
        {
          /* Make sure redirecting the jump will not invalidate the delay
             slot insns.  */
@@ -3853,9 +3871,7 @@ dbr_schedule (rtx first)
       INSN_FROM_TARGET_P (insn) = 0;
 
       /* Skip vector tables.  We can't get attributes for them.  */
-      if (JUMP_P (insn)
-         && (GET_CODE (PATTERN (insn)) == ADDR_VEC
-             || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
+      if (JUMP_TABLE_DATA_P (insn))
        continue;
 
       if (num_delay_slots (insn) > 0)
@@ -3864,7 +3880,7 @@ dbr_schedule (rtx first)
       /* Ensure all jumps go to the last of a set of consecutive labels.  */
       if (JUMP_P (insn)
          && (condjump_p (insn) || condjump_in_parallel_p (insn))
-         && JUMP_LABEL (insn) != 0
+         && !ANY_RETURN_P (JUMP_LABEL (insn))
          && ((target = skip_consecutive_labels (JUMP_LABEL (insn)))
              != JUMP_LABEL (insn)))
        redirect_jump (insn, target, 1);
@@ -4081,7 +4097,6 @@ struct rtl_opt_pass pass_delay_slots =
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_dump_func |
   TODO_ggc_collect                      /* todo_flags_finish */
  }
 };
@@ -4116,7 +4131,6 @@ struct rtl_opt_pass pass_machine_reorg =
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_dump_func |
   TODO_ggc_collect                      /* todo_flags_finish */
  }
 };