t-aarch64-linux (MULTILIB_OSDIRNAMES): Handle multi-arch for ilp32.
[gcc.git] / gcc / reorg.c
index c51e03cf366effb8f5be3cb2a12ec9df25e55a53..02d8adc61808ed1514b6481e3724d89adbc12123 100644 (file)
@@ -1,5 +1,5 @@
 /* Perform instruction reorganizations for delay slot filling.
-   Copyright (C) 1992-2015 Free Software Foundation, Inc.
+   Copyright (C) 1992-2017 Free Software Foundation, Inc.
    Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu).
    Hacked by Michael Tiemann (tiemann@cygnus.com).
 
@@ -104,42 +104,21 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "backend.h"
-#include "predict.h"
-#include "tree.h"
+#include "target.h"
 #include "rtl.h"
-#include "df.h"
-#include "diagnostic-core.h"
+#include "tree.h"
+#include "predict.h"
+#include "memmodel.h"
 #include "tm_p.h"
-#include "flags.h"
-#include "alias.h"
-#include "insn-config.h"
 #include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
+#include "insn-config.h"
 #include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
-#include "expr.h"
-#include "conditions.h"
-#include "regs.h"
 #include "recog.h"
 #include "insn-attr.h"
 #include "resource.h"
-#include "except.h"
 #include "params.h"
-#include "target.h"
 #include "tree-pass.h"
 
-#ifdef DELAY_SLOTS
-
-#ifndef ANNUL_IFTRUE_SLOTS
-#define eligible_for_annul_true(INSN, SLOTS, TRIAL, FLAGS) 0
-#endif
-#ifndef ANNUL_IFFALSE_SLOTS
-#define eligible_for_annul_false(INSN, SLOTS, TRIAL, FLAGS) 0
-#endif
-
 \f
 /* First, some functions that were used before GCC got a control flow graph.
    These functions are now only used here in reorg.c, and have therefore
@@ -219,9 +198,6 @@ static void add_to_delay_list (rtx_insn *, vec<rtx_insn *> *);
 static rtx_insn *delete_from_delay_slot (rtx_insn *);
 static void delete_scheduled_jump (rtx_insn *);
 static void note_delay_statistics (int, int);
-#if defined(ANNUL_IFFALSE_SLOTS) || defined(ANNUL_IFTRUE_SLOTS)
-static void optimize_skip (rtx_jump_insn *, vec<rtx_insn *> *);
-#endif
 static int get_jump_flags (const rtx_insn *, rtx);
 static int mostly_true_jump (rtx);
 static rtx get_branch_condition (const rtx_insn *, rtx);
@@ -244,13 +220,13 @@ static void steal_delay_list_from_fallthrough (rtx_insn *, rtx, rtx_sequence *,
                                               struct resources *,
                                               int, int *, int *);
 static void try_merge_delay_insns (rtx_insn *, rtx_insn *);
-static rtx redundant_insn (rtx, rtx_insn *, const vec<rtx_insn *> &);
+static rtx_insn *redundant_insn (rtx, rtx_insn *, const vec<rtx_insn *> &);
 static int own_thread_p (rtx, rtx, int);
-static void update_block (rtx_insn *, rtx);
+static void update_block (rtx_insn *, rtx_insn *);
 static int reorg_redirect_jump (rtx_jump_insn *, rtx);
 static void update_reg_dead_notes (rtx_insn *, rtx_insn *);
-static void fix_reg_dead_note (rtx, rtx);
-static void update_reg_unused_notes (rtx, rtx);
+static void fix_reg_dead_note (rtx_insn *, rtx);
+static void update_reg_unused_notes (rtx_insn *, rtx);
 static void fill_simple_delay_slots (int);
 static void fill_slots_from_thread (rtx_jump_insn *, rtx, rtx, rtx,
                                    int, int, int, int,
@@ -717,8 +693,6 @@ note_delay_statistics (int slots_filled, int index)
   num_filled_delays[index][slots_filled][reorg_pass_number]++;
 }
 \f
-#if defined(ANNUL_IFFALSE_SLOTS) || defined(ANNUL_IFTRUE_SLOTS)
-
 /* Optimize the following cases:
 
    1.  When a conditional branch skips over only one instruction,
@@ -766,6 +740,7 @@ optimize_skip (rtx_jump_insn *insn, vec<rtx_insn *> *delay_list)
       || recog_memoized (trial) < 0
       || (! eligible_for_annul_false (insn, 0, trial, flags)
          && ! eligible_for_annul_true (insn, 0, trial, flags))
+      || RTX_FRAME_RELATED_P (trial)
       || can_throw_internal (trial))
     return;
 
@@ -775,7 +750,7 @@ optimize_skip (rtx_jump_insn *insn, vec<rtx_insn *> *delay_list)
      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_AS_INSN (insn))
       || (next_trial != 0
          && simplejump_or_return_p (next_trial)
          && JUMP_LABEL (insn) == JUMP_LABEL (next_trial)))
@@ -818,7 +793,6 @@ optimize_skip (rtx_jump_insn *insn, vec<rtx_insn *> *delay_list)
       INSN_ANNULLED_BRANCH_P (insn) = 1;
     }
 }
-#endif
 \f
 /*  Encode and return branch direction and prediction information for
     INSN assuming it will jump to LABEL.
@@ -866,7 +840,8 @@ mostly_true_jump (rtx jump_insn)
   rtx note = find_reg_note (jump_insn, REG_BR_PROB, 0);
   if (note)
     {
-      int prob = XINT (note, 0);
+      int prob = profile_probability::from_reg_br_prob_note (XINT (note, 0))
+                       .to_reg_br_prob_base ();
 
       if (prob >= REG_BR_PROB_BASE * 9 / 10)
        return 2;
@@ -904,20 +879,20 @@ get_branch_condition (const rtx_insn *insn, rtx target)
     return 0;
 
   src = SET_SRC (pat);
-  if (GET_CODE (src) == LABEL_REF && LABEL_REF_LABEL (src) == target)
+  if (GET_CODE (src) == LABEL_REF && label_ref_label (src) == target)
     return const_true_rtx;
 
   else if (GET_CODE (src) == IF_THEN_ELSE
           && XEXP (src, 2) == pc_rtx
           && ((GET_CODE (XEXP (src, 1)) == LABEL_REF
-               && LABEL_REF_LABEL (XEXP (src, 1)) == target)
+               && label_ref_label (XEXP (src, 1)) == target)
               || (ANY_RETURN_P (XEXP (src, 1)) && XEXP (src, 1) == target)))
     return XEXP (src, 0);
 
   else if (GET_CODE (src) == IF_THEN_ELSE
           && XEXP (src, 1) == pc_rtx
           && ((GET_CODE (XEXP (src, 2)) == LABEL_REF
-               && LABEL_REF_LABEL (XEXP (src, 2)) == target)
+               && label_ref_label (XEXP (src, 2)) == target)
               || (ANY_RETURN_P (XEXP (src, 2)) && XEXP (src, 2) == target)))
     {
       enum rtx_code rev;
@@ -973,12 +948,12 @@ redirect_with_delay_slots_safe_p (rtx_insn *jump, rtx newlabel, rtx seq)
   flags = get_jump_flags (jump, newlabel);
   for (i = 1; i < pat->len (); i++)
     if (! (
-#ifdef ANNUL_IFFALSE_SLOTS
+#if ANNUL_IFFALSE_SLOTS
           (INSN_ANNULLED_BRANCH_P (jump)
            && INSN_FROM_TARGET_P (pat->insn (i)))
           ? eligible_for_annul_false (jump, i - 1, pat->insn (i), flags) :
 #endif
-#ifdef ANNUL_IFTRUE_SLOTS
+#if ANNUL_IFTRUE_SLOTS
           (INSN_ANNULLED_BRANCH_P (jump)
            && ! INSN_FROM_TARGET_P (XVECEXP (pat, 0, i)))
           ? eligible_for_annul_true (jump, i - 1, pat->insn (i), flags) :
@@ -1005,12 +980,12 @@ redirect_with_delay_list_safe_p (rtx_insn *jump, rtx newlabel,
   unsigned int i = 0;
   for (; i < delay_insns; i++)
     if (! (
-#ifdef ANNUL_IFFALSE_SLOTS
+#if ANNUL_IFFALSE_SLOTS
           (INSN_ANNULLED_BRANCH_P (jump)
            && INSN_FROM_TARGET_P (delay_list[i]))
           ? eligible_for_annul_false (jump, i, delay_list[i], flags) :
 #endif
-#ifdef ANNUL_IFTRUE_SLOTS
+#if ANNUL_IFTRUE_SLOTS
           (INSN_ANNULLED_BRANCH_P (jump)
            && ! INSN_FROM_TARGET_P (delay_list[i]))
           ? eligible_for_annul_true (jump, i, delay_list[i], flags) :
@@ -1154,7 +1129,13 @@ steal_delay_list_from_target (rtx_insn *insn, rtx condition, rtx_sequence *seq,
                                              trial, flags)))
        {
          if (must_annul)
-           used_annul = 1;
+           {
+             /* Frame related instructions cannot go into annulled delay
+                slots, it messes up the dwarf info.  */
+             if (RTX_FRAME_RELATED_P (trial))
+               return;
+             used_annul = 1;
+           }
          rtx_insn *temp = copy_delay_slot_insn (trial);
          INSN_FROM_TARGET_P (temp) = 1;
          add_to_delay_list (temp, &new_delay_list);
@@ -1280,8 +1261,7 @@ try_merge_delay_insns (rtx_insn *insn, rtx_insn *thread)
   int num_slots = XVECLEN (PATTERN (insn), 0);
   rtx next_to_match = XVECEXP (PATTERN (insn), 0, slot_number);
   struct resources set, needed, modified;
-  rtx_insn_list *merged_insns = 0;
-  int i, j;
+  auto_vec<std::pair<rtx_insn *, bool>, 10> merged_insns;
   int flags;
 
   flags = get_jump_flags (delay_insn, JUMP_LABEL (delay_insn));
@@ -1296,7 +1276,7 @@ try_merge_delay_insns (rtx_insn *insn, rtx_insn *thread)
      will essentially disable this optimization.  This method is somewhat of
      a kludge, but I don't see a better way.)  */
   if (! annul_p)
-    for (i = 1 ; i < num_slots; i++)
+    for (int i = 1; i < num_slots; i++)
       if (XVECEXP (PATTERN (insn), 0, i))
        mark_referenced_resources (XVECEXP (PATTERN (insn), 0, i), &needed,
                                   true);
@@ -1340,7 +1320,7 @@ try_merge_delay_insns (rtx_insn *insn, rtx_insn *thread)
              INSN_FROM_TARGET_P (next_to_match) = 0;
            }
          else
-           merged_insns = gen_rtx_INSN_LIST (VOIDmode, trial, merged_insns);
+           merged_insns.safe_push (std::pair<rtx_insn *, bool> (trial, false));
 
          if (++slot_number == num_slots)
            break;
@@ -1367,19 +1347,19 @@ try_merge_delay_insns (rtx_insn *insn, rtx_insn *thread)
       mark_set_resources (filled_insn, &set, 0, MARK_SRC_DEST_CALL);
       mark_referenced_resources (filled_insn, &needed, true);
 
-      for (i = 1; i < pat->len (); i++)
+      for (int i = 1; i < pat->len (); i++)
        {
          rtx_insn *dtrial = pat->insn (i);
 
          CLEAR_RESOURCE (&modified);
          /* Account for resources set by the insn following NEXT_TO_MATCH
             inside INSN's delay list. */
-         for (j = 1; slot_number + j < num_slots; j++)
+         for (int j = 1; slot_number + j < num_slots; j++)
            mark_set_resources (XVECEXP (PATTERN (insn), 0, slot_number + j),
                                &modified, 0, MARK_SRC_DEST_CALL);
          /* Account for resources set by the insn before DTRIAL and inside
             TRIAL's delay list. */
-         for (j = 1; j < i; j++)
+         for (int j = 1; j < i; j++)
            mark_set_resources (XVECEXP (pat, 0, j),
                                &modified, 0, MARK_SRC_DEST_CALL); 
          if (! insn_references_resource_p (dtrial, &set, true)
@@ -1405,8 +1385,8 @@ try_merge_delay_insns (rtx_insn *insn, rtx_insn *thread)
                  INSN_FROM_TARGET_P (next_to_match) = 0;
                }
              else
-               merged_insns = gen_rtx_INSN_LIST (SImode, dtrial,
-                                                 merged_insns);
+               merged_insns.safe_push (std::pair<rtx_insn *, bool> (dtrial,
+                                                                    true));
 
              if (++slot_number == num_slots)
                break;
@@ -1430,27 +1410,24 @@ try_merge_delay_insns (rtx_insn *insn, rtx_insn *thread)
      target.  */
   if (slot_number == num_slots && annul_p)
     {
-      for (; merged_insns; merged_insns = merged_insns->next ())
-       {
-         if (GET_MODE (merged_insns) == SImode)
-           {
-             rtx_insn *new_rtx;
-
-             update_block (merged_insns->insn (), thread);
-             new_rtx = delete_from_delay_slot (merged_insns->insn ());
-             if (thread->deleted ())
-               thread = new_rtx;
-           }
-         else
-           {
-             update_block (merged_insns->insn (), thread);
-             delete_related_insns (merged_insns->insn ());
-           }
-       }
+      unsigned int len = merged_insns.length ();
+      for (unsigned int i = len - 1; i < len; i--)
+       if (merged_insns[i].second)
+         {
+           update_block (merged_insns[i].first, thread);
+           rtx_insn *new_rtx = delete_from_delay_slot (merged_insns[i].first);
+           if (thread->deleted ())
+             thread = new_rtx;
+         }
+       else
+         {
+           update_block (merged_insns[i].first, thread);
+           delete_related_insns (merged_insns[i].first);
+         }
 
       INSN_ANNULLED_BRANCH_P (delay_insn) = 0;
 
-      for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
+      for (int i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
        INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i)) = 0;
     }
 }
@@ -1474,7 +1451,7 @@ try_merge_delay_insns (rtx_insn *insn, rtx_insn *thread)
    redundant insn, but the cost of splitting seems greater than the possible
    gain in rare cases.  */
 
-static rtx
+static rtx_insn *
 redundant_insn (rtx insn, rtx_insn *target, const vec<rtx_insn *> &delay_list)
 {
   rtx target_main = target;
@@ -1631,7 +1608,7 @@ redundant_insn (rtx insn, rtx_insn *target, const vec<rtx_insn *> &delay_list)
             resource requirements as we go.  */
          for (i = seq->len () - 1; i > 0; i--)
            {
-             rtx candidate = seq->element (i);
+             rtx_insn *candidate = seq->insn (i);
 
              /* If an insn will be annulled if the branch is false, it isn't
                 considered as a possible duplicate insn.  */
@@ -1718,27 +1695,20 @@ own_thread_p (rtx thread, rtx label, int allow_fallthrough)
 }
 \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
-   reorg finishes.
+   We leave a marker of the form (use (INSN)) immediately in front of WHERE
+   for mark_target_live_regs.  These markers will be deleted at the end.
 
    We used to try to update the live status of registers if WHERE is at
    the start of a basic block, but that can't work since we may remove a
    BARRIER in relax_delay_slots.  */
 
 static void
-update_block (rtx_insn *insn, rtx where)
+update_block (rtx_insn *insn, rtx_insn *where)
 {
-  /* Ignore if this was in a delay slot and it came from the target of
-     a branch.  */
-  if (INSN_FROM_TARGET_P (insn))
-    return;
-
   emit_insn_before (gen_rtx_USE (VOIDmode, 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.  */
-
   incr_ticks_for_insn (insn);
 }
 
@@ -1798,7 +1768,7 @@ update_reg_dead_notes (rtx_insn *insn, rtx_insn *delayed_insn)
    confused into thinking the register is dead.  */
 
 static void
-fix_reg_dead_note (rtx start_insn, rtx stop_insn)
+fix_reg_dead_note (rtx_insn *start_insn, rtx stop_insn)
 {
   rtx link, next;
   rtx_insn *p;
@@ -1829,7 +1799,7 @@ fix_reg_dead_note (rtx start_insn, rtx stop_insn)
    does.  */
 
 static void
-update_reg_unused_notes (rtx insn, rtx redundant_insn)
+update_reg_unused_notes (rtx_insn *insn, rtx redundant_insn)
 {
   rtx link, next;
 
@@ -2096,8 +2066,8 @@ fill_simple_delay_slots (int non_jumps_p)
       /* If all needed slots haven't been filled, we come here.  */
 
       /* Try to optimize case of jumping around a single insn.  */
-#if defined(ANNUL_IFFALSE_SLOTS) || defined(ANNUL_IFTRUE_SLOTS)
-      if (slots_filled != slots_to_fill
+      if ((ANNUL_IFTRUE_SLOTS || ANNUL_IFFALSE_SLOTS)
+       && slots_filled != slots_to_fill
          && delay_list.is_empty ()
          && JUMP_P (insn)
          && (condjump_p (insn) || condjump_in_parallel_p (insn))
@@ -2107,7 +2077,6 @@ fill_simple_delay_slots (int non_jumps_p)
          if (!delay_list.is_empty ())
            slots_filled += 1;
        }
-#endif
 
       /* Try to get insns from beyond the insn needing the delay slot.
         These insns can neither set or reference resources set in insns being
@@ -2224,7 +2193,7 @@ fill_simple_delay_slots (int non_jumps_p)
              && trial
              && jump_to_label_p (trial)
              && simplejump_p (trial)
-             && (next_trial = next_active_insn (JUMP_LABEL (trial))) != 0
+             && (next_trial = next_active_insn (JUMP_LABEL_AS_INSN (trial))) != 0
              && ! (NONJUMP_INSN_P (next_trial)
                    && GET_CODE (PATTERN (next_trial)) == SEQUENCE)
              && !JUMP_P (next_trial)
@@ -2264,8 +2233,8 @@ fill_simple_delay_slots (int non_jumps_p)
          && simplejump_p (jump_insn)
          && slots_filled != slots_to_fill)
        fill_slots_from_thread (jump_insn, const_true_rtx,
-                               next_active_insn (JUMP_LABEL (insn)), NULL, 1,
-                               1, own_thread_p (JUMP_LABEL (insn),
+                               next_active_insn (JUMP_LABEL_AS_INSN (insn)),
+                               NULL, 1, 1, own_thread_p (JUMP_LABEL (insn),
                                                 JUMP_LABEL (insn), 0),
                                slots_to_fill, &slots_filled, &delay_list);
 
@@ -2443,7 +2412,7 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition,
                              && (! own_thread || ! sets_cc0_p (pat)))))
          && ! can_throw_internal (trial))
        {
-         rtx prior_insn;
+         rtx_insn *prior_insn;
 
          /* If TRIAL is redundant with some insn before INSN, we don't
             actually need to add it to the delay list; we can merely pretend
@@ -2493,14 +2462,9 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition,
              if (eligible_for_delay (insn, *pslots_filled, trial, flags))
                goto winner;
            }
-         else if (0
-#ifdef ANNUL_IFTRUE_SLOTS
-                  || ! thread_if_true
-#endif
-#ifdef ANNUL_IFFALSE_SLOTS
-                  || thread_if_true
-#endif
-                  )
+         else if (!RTX_FRAME_RELATED_P (trial)
+                  && ((ANNUL_IFTRUE_SLOTS && ! thread_if_true)
+                       || (ANNUL_IFFALSE_SLOTS && thread_if_true)))
            {
              old_trial = trial;
              trial = try_split (pat, trial, 0);
@@ -2606,7 +2570,8 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition,
                             to call update_block and delete_insn.  */
                          fix_reg_dead_note (prior_insn, insn);
                          update_reg_unused_notes (prior_insn, new_thread);
-                         new_thread = next_active_insn (new_thread);
+                         new_thread
+                           = next_active_insn (as_a<rtx_insn *> (new_thread));
                        }
                      break;
                    }
@@ -2935,16 +2900,16 @@ fill_eager_delay_slots (void)
     }
 }
 \f
-static void delete_computation (rtx insn);
+static void delete_computation (rtx_insn *insn);
 
 /* Recursively delete prior insns that compute the value (used only by INSN
    which the caller is deleting) stored in the register mentioned by NOTE
    which is a REG_DEAD note associated with INSN.  */
 
 static void
-delete_prior_computation (rtx note, rtx insn)
+delete_prior_computation (rtx note, rtx_insn *insn)
 {
-  rtx our_prev;
+  rtx_insn *our_prev;
   rtx reg = XEXP (note, 0);
 
   for (our_prev = prev_nonnote_insn (insn);
@@ -3056,7 +3021,7 @@ delete_prior_computation (rtx note, rtx insn)
    delete the insn that set it.  */
 
 static void
-delete_computation (rtx insn)
+delete_computation (rtx_insn *insn)
 {
   rtx note, next;
 
@@ -3110,7 +3075,7 @@ delete_jump (rtx_insn *insn)
 }
 
 static rtx_insn *
-label_before_next_insn (rtx x, rtx scan_limit)
+label_before_next_insn (rtx_insn *x, rtx scan_limit)
 {
   rtx_insn *insn = next_active_insn (x);
   while (insn)
@@ -3147,7 +3112,6 @@ relax_delay_slots (rtx_insn *first)
 {
   rtx_insn *insn, *next;
   rtx_sequence *pat;
-  rtx trial;
   rtx_insn *delay_insn;
   rtx target_label;
 
@@ -3173,7 +3137,8 @@ relax_delay_slots (rtx_insn *first)
          if (ANY_RETURN_P (target_label))
            target_label = find_end_label (target_label);
 
-         if (target_label && next_active_insn (target_label) == next
+         if (target_label
+             && next_active_insn (as_a<rtx_insn *> (target_label)) == next
              && ! condjump_in_parallel_p (jump_insn)
              && ! (next && switch_text_sections_between_p (jump_insn, next)))
            {
@@ -3194,7 +3159,8 @@ relax_delay_slots (rtx_insn *first)
          if (next && simplejump_or_return_p (next)
              && any_condjump_p (jump_insn)
              && target_label
-             && next_active_insn (target_label) == next_active_insn (next)
+             && (next_active_insn (as_a<rtx_insn *> (target_label))
+                 == next_active_insn (next))
              && no_labels_between_p (jump_insn, next)
              && targetm.can_follow_jump (jump_insn, next))
            {
@@ -3239,7 +3205,7 @@ relax_delay_slots (rtx_insn *first)
          && (other = prev_active_insn (insn)) != 0
          && any_condjump_p (other)
          && no_labels_between_p (other, insn)
-         && 0 > mostly_true_jump (other))
+         && mostly_true_jump (other) < 0)
        {
          rtx other_target = JUMP_LABEL (other);
          target_label = JUMP_LABEL (insn);
@@ -3298,10 +3264,10 @@ relax_delay_slots (rtx_insn *first)
          for (i = 0; i < XVECLEN (pat, 0); i++)
            INSN_FROM_TARGET_P (XVECEXP (pat, 0, i)) = 0;
 
-         trial = PREV_INSN (insn);
+         rtx_insn *prev = PREV_INSN (insn);
          delete_related_insns (insn);
          gcc_assert (GET_CODE (pat) == SEQUENCE);
-         add_insn_after (delay_insn, trial, NULL);
+         add_insn_after (delay_insn, prev, NULL);
          after = delay_insn;
          for (i = 1; i < pat->len (); i++)
            after = emit_copy_of_insn_after (pat->insn (i), after);
@@ -3322,9 +3288,9 @@ relax_delay_slots (rtx_insn *first)
 
       /* 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,
-                                                    delay_jump_insn,
-                                                    &crossing));
+      rtx trial = skip_consecutive_labels (follow_jumps (target_label,
+                                                        delay_jump_insn,
+                                                        &crossing));
       if (ANY_RETURN_P (trial))
        trial = find_end_label (trial);
 
@@ -3334,7 +3300,7 @@ relax_delay_slots (rtx_insn *first)
          reorg_redirect_jump (delay_jump_insn, trial);
          target_label = trial;
          if (crossing)
-           CROSSING_JUMP_P (insn) = 1;
+           CROSSING_JUMP_P (delay_jump_insn) = 1;
        }
 
       /* If the first insn at TARGET_LABEL is redundant with a previous
@@ -3349,7 +3315,7 @@ relax_delay_slots (rtx_insn *first)
        {
          /* Figure out where to emit the special USE insn so we don't
             later incorrectly compute register live/death info.  */
-         rtx_insn *tmp = next_active_insn (trial);
+         rtx_insn *tmp = next_active_insn (as_a<rtx_insn *> (trial));
          if (tmp == 0)
            tmp = find_end_label (simple_return_rtx);
 
@@ -3379,26 +3345,27 @@ relax_delay_slots (rtx_insn *first)
          && simplejump_or_return_p (trial_seq->insn (0))
          && redundant_insn (trial_seq->insn (1), insn, vNULL))
        {
-         target_label = JUMP_LABEL (trial_seq->insn (0));
-         if (ANY_RETURN_P (target_label))
-           target_label = find_end_label (target_label);
+         rtx temp_label = JUMP_LABEL (trial_seq->insn (0));
+         if (ANY_RETURN_P (temp_label))
+           temp_label = find_end_label (temp_label);
          
-         if (target_label
+         if (temp_label
              && redirect_with_delay_slots_safe_p (delay_jump_insn,
-                                                  target_label, insn))
+                                                  temp_label, insn))
            {
              update_block (trial_seq->insn (1), insn);
-             reorg_redirect_jump (delay_jump_insn, target_label);
+             reorg_redirect_jump (delay_jump_insn, temp_label);
              next = insn;
              continue;
            }
        }
 
       /* See if we have a simple (conditional) jump that is useless.  */
-      if (! INSN_ANNULLED_BRANCH_P (delay_jump_insn)
-         && ! condjump_in_parallel_p (delay_jump_insn)
-         && prev_active_insn (target_label) == insn
-         && ! BARRIER_P (prev_nonnote_insn (target_label))
+      if (!CROSSING_JUMP_P (delay_jump_insn)
+         && !INSN_ANNULLED_BRANCH_P (delay_jump_insn)
+         && !condjump_in_parallel_p (delay_jump_insn)
+         && prev_active_insn (as_a<rtx_insn *> (target_label)) == insn
+         && !BARRIER_P (prev_nonnote_insn (as_a<rtx_insn *> (target_label)))
          /* If the last insn in the delay slot sets CC0 for some insn,
             various code assumes that it is in a delay slot.  We could
             put it back where it belonged and delete the register notes,
@@ -3428,10 +3395,10 @@ relax_delay_slots (rtx_insn *first)
          for (i = 0; i < XVECLEN (pat, 0); i++)
            INSN_FROM_TARGET_P (XVECEXP (pat, 0, i)) = 0;
 
-         trial = PREV_INSN (insn);
+         rtx_insn *prev = PREV_INSN (insn);
          delete_related_insns (insn);
          gcc_assert (GET_CODE (pat) == SEQUENCE);
-         add_insn_after (delay_jump_insn, trial, NULL);
+         add_insn_after (delay_jump_insn, prev, NULL);
          after = delay_jump_insn;
          for (i = 1; i < pat->len (); i++)
            after = emit_copy_of_insn_after (pat->insn (i), after);
@@ -3460,7 +3427,8 @@ relax_delay_slots (rtx_insn *first)
       if (! INSN_ANNULLED_BRANCH_P (delay_jump_insn)
          && any_condjump_p (delay_jump_insn)
          && next && simplejump_or_return_p (next)
-         && next_active_insn (target_label) == next_active_insn (next)
+         && (next_active_insn (as_a<rtx_insn *> (target_label))
+             == next_active_insn (next))
          && no_labels_between_p (insn, next))
        {
          rtx label = JUMP_LABEL (next);
@@ -3511,7 +3479,8 @@ relax_delay_slots (rtx_insn *first)
        try_merge_delay_insns (insn, next);
       else if (! INSN_FROM_TARGET_P (pat->insn (1))
               && own_thread_p (target_label, target_label, 0))
-       try_merge_delay_insns (insn, next_active_insn (target_label));
+       try_merge_delay_insns (insn,
+                              next_active_insn (as_a<rtx_insn *> (target_label)));
 
       /* If we get here, we haven't deleted INSN.  But we may have deleted
         NEXT, so recompute it.  */
@@ -3611,13 +3580,13 @@ make_return_insns (rtx_insn *first)
        {
          for (i = 1; i < XVECLEN (pat, 0); i++)
            if (! (
-#ifdef ANNUL_IFFALSE_SLOTS
+#if ANNUL_IFFALSE_SLOTS
                   (INSN_ANNULLED_BRANCH_P (jump_insn)
                    && INSN_FROM_TARGET_P (pat->insn (i)))
                   ? eligible_for_annul_false (jump_insn, i - 1,
                                               pat->insn (i), flags) :
 #endif
-#ifdef ANNUL_IFTRUE_SLOTS
+#if ANNUL_IFTRUE_SLOTS
                   (INSN_ANNULLED_BRANCH_P (jump_insn)
                    && ! INSN_FROM_TARGET_P (pat->insn (i)))
                   ? eligible_for_annul_true (jump_insn, i - 1,
@@ -3643,9 +3612,14 @@ make_return_insns (rtx_insn *first)
 
          delete_related_insns (insn);
          for (i = 1; i < XVECLEN (pat, 0); i++)
-           prev = emit_insn_after (PATTERN (XVECEXP (pat, 0, i)), prev);
+           {
+             rtx_insn *in_seq_insn = as_a<rtx_insn *> (XVECEXP (pat, 0, i));
+             prev = emit_insn_after_setloc (PATTERN (in_seq_insn), prev,
+                                            INSN_LOCATION (in_seq_insn));
+           }
 
-         insn = emit_jump_insn_after (PATTERN (jump_insn), prev);
+         insn = emit_jump_insn_after_setloc (PATTERN (jump_insn), prev,
+                                             INSN_LOCATION (jump_insn));
          emit_barrier_after (insn);
 
          if (slots)
@@ -3747,7 +3721,8 @@ dbr_schedule (rtx_insn *first)
     {
       fill_simple_delay_slots (1);
       fill_simple_delay_slots (0);
-      fill_eager_delay_slots ();
+      if (!targetm.no_speculation_in_delay_slots_p ())
+       fill_eager_delay_slots ();
       relax_delay_slots (first);
     }
 
@@ -3852,21 +3827,24 @@ dbr_schedule (rtx_insn *first)
            }
        }
       fprintf (dump_file, "\n");
-#if defined (ANNUL_IFTRUE_SLOTS) || defined (ANNUL_IFFALSE_SLOTS)
-      fprintf (dump_file, ";; Reorg annuls: ");
-      need_comma = 0;
-      for (j = 0; j < MAX_DELAY_HISTOGRAM + 1; j++)
+
+      if (ANNUL_IFTRUE_SLOTS || ANNUL_IFFALSE_SLOTS)
        {
-         if (total_annul_slots[j])
+         fprintf (dump_file, ";; Reorg annuls: ");
+         need_comma = 0;
+         for (j = 0; j < MAX_DELAY_HISTOGRAM + 1; j++)
            {
-             if (need_comma)
-               fprintf (dump_file, ", ");
-             need_comma = 1;
-             fprintf (dump_file, "%d got %d delays", total_annul_slots[j], j);
+             if (total_annul_slots[j])
+               {
+                 if (need_comma)
+                   fprintf (dump_file, ", ");
+                 need_comma = 1;
+                 fprintf (dump_file, "%d got %d delays", total_annul_slots[j], j);
+               }
            }
+         fprintf (dump_file, "\n");
        }
-      fprintf (dump_file, "\n");
-#endif
+
       fprintf (dump_file, "\n");
     }
 
@@ -3880,15 +3858,14 @@ dbr_schedule (rtx_insn *first)
   free (uid_to_ruid);
   crtl->dbr_scheduled_p = true;
 }
-#endif /* DELAY_SLOTS */
 \f
 /* Run delay slot optimization.  */
 static unsigned int
 rest_of_handle_delay_slots (void)
 {
-#ifdef DELAY_SLOTS
-  dbr_schedule (get_insns ());
-#endif
+  if (DELAY_SLOTS)
+    dbr_schedule (get_insns ());
+
   return 0;
 }
 
@@ -3926,12 +3903,11 @@ public:
 bool
 pass_delay_slots::gate (function *)
 {
-#ifdef DELAY_SLOTS
   /* At -O0 dataflow info isn't updated after RA.  */
-  return optimize > 0 && flag_delayed_branch && !crtl->dbr_scheduled_p;
-#else
-  return 0;
-#endif
+  if (DELAY_SLOTS)
+    return optimize > 0 && flag_delayed_branch && !crtl->dbr_scheduled_p;
+
+  return false;
 }
 
 } // anon namespace