rtlanal.c (tablejump_p): False for returns.
authorBernd Schmidt <bernds@codesourcery.com>
Thu, 28 Jul 2011 18:45:20 +0000 (18:45 +0000)
committerBernd Schmidt <bernds@gcc.gnu.org>
Thu, 28 Jul 2011 18:45:20 +0000 (18:45 +0000)
* rtlanal.c (tablejump_p): False for returns.
* reorg.c (first_active_target_insn): New static function.
(find_end_label): Set JUMP_LABEL for a new returnjump.
(optimize_skip, get_jump_flags, rare_destination,
mostly_true_jump, get_branch_condition,
steal_delay_list_from_target, own_thread_p,
fill_simple_delay_slots, follow_jumps, fill_slots_from_thread,
fill_eager_delay_slots, relax_delay_slots, make_return_insns,
dbr_schedule): Adjust to handle ret_rtx in JUMP_LABELs.
* jump.c (delete_related_insns): Likewise.
(jump_to_label_p): New function.
(redirect_target): New static function.
(redirect_exp_1): Use it.  Adjust to handle ret_rtx in JUMP_LABELS.
(redirect_jump_1): Assert that the new label is nonnull.
(redirect_jump): Likewise.
(redirect_jump_2): Check for ANY_RETURN_P rather than NULL labels.
* ifcvt.c (find_if_case_1): Take care when redirecting jumps to the
exit block.
(dead_or_predicable): Change NEW_DEST arg to DEST_EDGE.  All callers
changed.  Ensure that the right label is passed to redirect_jump.
* function.c (emit_return_into_block,
thread_prologue_and_epilogue_insns): Ensure new returnjumps have
ret_rtx in their JUMP_LABEL.
* print-rtl.c (print_rtx): Handle ret_rtx in a JUMP_LABEL.
* emit-rtl.c (skip_consecutive_labels): Allow the caller to
pass ret_rtx as label.
* cfglayout.c (fixup_reorder_chain): Use
force_nonfallthru_and_redirect rather than force_nonfallthru.
(duplicate_insn_chain): Copy JUMP_LABELs for returns.
* rtl.h (ANY_RETURN_P): New macro.
(jump_to_label_p): Declare.
* resource.c (find_dead_or_set_registers): Handle ret_rtx in
JUMP_LABELs.
(mark_target_live_regs): Likewise.
* basic-block.h (force_nonfallthru_and_redirect): Declare.
* cfgrtl.c (force_nonfallthru_and_redirect): No longer static.
* config/alpha/alpha.c (alpha_tablejump_addr_vec,
alpha_tablejump_best_label): Remove functions.
* config/alpha/alpha-protos.c (alpha_tablejump_addr_vec,
alpha_tablejump_best_label): Remove declarations.
* config/sh/sh.c (barrier_align, split_branches): Adjust for
ret_rtx in JUMP_LABELs.
* config/arm/arm.c (is_jump_table): Likewise.

From-SVN: r176881

17 files changed:
gcc/ChangeLog
gcc/basic-block.h
gcc/cfglayout.c
gcc/cfgrtl.c
gcc/config/alpha/alpha-protos.h
gcc/config/alpha/alpha.c
gcc/config/arm/arm.c
gcc/config/sh/sh.c
gcc/emit-rtl.c
gcc/function.c
gcc/ifcvt.c
gcc/jump.c
gcc/print-rtl.c
gcc/reorg.c
gcc/resource.c
gcc/rtl.h
gcc/rtlanal.c

index 7fdc1e5be8beb73a64adc5e42fac1d87c83e3827..8b6111e6630ea73705f39c01c52ecdd6e601aaa9 100644 (file)
@@ -1,3 +1,49 @@
+2011-07-28  Bernd Schmidt  <bernds@codesourcery.com>
+
+       * rtlanal.c (tablejump_p): False for returns.
+       * reorg.c (first_active_target_insn): New static function.
+       (find_end_label): Set JUMP_LABEL for a new returnjump.
+       (optimize_skip, get_jump_flags, rare_destination,
+       mostly_true_jump, get_branch_condition,
+       steal_delay_list_from_target, own_thread_p,
+       fill_simple_delay_slots, follow_jumps, fill_slots_from_thread,
+       fill_eager_delay_slots, relax_delay_slots, make_return_insns,
+       dbr_schedule): Adjust to handle ret_rtx in JUMP_LABELs.
+       * jump.c (delete_related_insns): Likewise.
+       (jump_to_label_p): New function.
+       (redirect_target): New static function.
+       (redirect_exp_1): Use it.  Adjust to handle ret_rtx in JUMP_LABELS.
+       (redirect_jump_1): Assert that the new label is nonnull.
+       (redirect_jump): Likewise.
+       (redirect_jump_2): Check for ANY_RETURN_P rather than NULL labels.
+       * ifcvt.c (find_if_case_1): Take care when redirecting jumps to the
+       exit block.
+       (dead_or_predicable): Change NEW_DEST arg to DEST_EDGE.  All callers
+       changed.  Ensure that the right label is passed to redirect_jump.
+       * function.c (emit_return_into_block,
+       thread_prologue_and_epilogue_insns): Ensure new returnjumps have
+       ret_rtx in their JUMP_LABEL.
+       * print-rtl.c (print_rtx): Handle ret_rtx in a JUMP_LABEL.
+       * emit-rtl.c (skip_consecutive_labels): Allow the caller to
+       pass ret_rtx as label.
+       * cfglayout.c (fixup_reorder_chain): Use
+       force_nonfallthru_and_redirect rather than force_nonfallthru.
+       (duplicate_insn_chain): Copy JUMP_LABELs for returns.
+       * rtl.h (ANY_RETURN_P): New macro.
+       (jump_to_label_p): Declare.
+       * resource.c (find_dead_or_set_registers): Handle ret_rtx in
+       JUMP_LABELs.
+       (mark_target_live_regs): Likewise.
+       * basic-block.h (force_nonfallthru_and_redirect): Declare.
+       * cfgrtl.c (force_nonfallthru_and_redirect): No longer static.
+       * config/alpha/alpha.c (alpha_tablejump_addr_vec,
+       alpha_tablejump_best_label): Remove functions.
+       * config/alpha/alpha-protos.c (alpha_tablejump_addr_vec,
+       alpha_tablejump_best_label): Remove declarations.
+       * config/sh/sh.c (barrier_align, split_branches): Adjust for
+       ret_rtx in JUMP_LABELs.
+       * config/arm/arm.c (is_jump_table): Likewise.
+
 2011-07-28  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/predicates.md (pic_32bit_opreand): Do not define as
index c03129c6abfa62375620ad8190e7cea1689ae5c0..41c35697a5f83c83da9418413a83708065585037 100644 (file)
@@ -804,6 +804,7 @@ extern rtx block_label (basic_block);
 extern bool purge_all_dead_edges (void);
 extern bool purge_dead_edges (basic_block);
 extern bool fixup_abnormal_edges (void);
+extern basic_block force_nonfallthru_and_redirect (edge, basic_block);
 
 /* In cfgbuild.c.  */
 extern void find_many_sub_basic_blocks (sbitmap);
index d320fcc5dbd8a1fea9668934dd19e0c1187b8c98..c62138f6d88252ca10ac759da2026b324bcdbbe0 100644 (file)
@@ -899,7 +899,7 @@ fixup_reorder_chain (void)
         Note force_nonfallthru can delete E_FALL and thus we have to
         save E_FALL->src prior to the call to force_nonfallthru.  */
       src_bb = e_fall->src;
-      nb = force_nonfallthru (e_fall);
+      nb = force_nonfallthru_and_redirect (e_fall, e_fall->dest);
       if (nb)
        {
          nb->il.rtl->visited = 1;
@@ -1195,6 +1195,9 @@ duplicate_insn_chain (rtx from, rtx to)
              break;
            }
          copy = emit_copy_of_insn_after (insn, get_last_insn ());
+         if (JUMP_P (insn) && JUMP_LABEL (insn) != NULL_RTX
+             && ANY_RETURN_P (JUMP_LABEL (insn)))
+           JUMP_LABEL (copy) = JUMP_LABEL (insn);
           maybe_copy_prologue_epilogue_insn (insn, copy);
          break;
 
index 076ff03d056cd46eb9b93a7ed1c75cf04c02753b..69377957cd6df13fc8870119f5fc273d59af8cd7 100644 (file)
@@ -1119,7 +1119,7 @@ rtl_redirect_edge_and_branch (edge e, basic_block target)
 /* Like force_nonfallthru below, but additionally performs redirection
    Used by redirect_edge_and_branch_force.  */
 
-static basic_block
+basic_block
 force_nonfallthru_and_redirect (edge e, basic_block target)
 {
   basic_block jump_block, new_bb = NULL, src = e->src;
index 58723aa81a463a22c8a6c29e8929cd22fd3173fc..13b5ce936b8543df6f108e1fef8dad419b694f3f 100644 (file)
@@ -31,9 +31,6 @@ extern void alpha_expand_prologue (void);
 extern void alpha_expand_epilogue (void);
 extern void alpha_output_filename (FILE *, const char *);
 
-extern rtx alpha_tablejump_addr_vec (rtx);
-extern rtx alpha_tablejump_best_label (rtx);
-
 extern bool alpha_legitimate_constant_p (enum machine_mode, rtx);
 extern rtx alpha_legitimize_reload_address (rtx, enum machine_mode,
                                            int, int, int);
index 3d32de32e43c17a6546e82eb12223559c948b730..e390075f102daaf8d26e3518228e218e328c89ce 100644 (file)
@@ -571,59 +571,6 @@ direct_return (void)
          && crtl->args.pretend_args_size == 0);
 }
 
-/* Return the ADDR_VEC associated with a tablejump insn.  */
-
-rtx
-alpha_tablejump_addr_vec (rtx insn)
-{
-  rtx tmp;
-
-  tmp = JUMP_LABEL (insn);
-  if (!tmp)
-    return NULL_RTX;
-  tmp = NEXT_INSN (tmp);
-  if (!tmp)
-    return NULL_RTX;
-  if (JUMP_P (tmp)
-      && GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC)
-    return PATTERN (tmp);
-  return NULL_RTX;
-}
-
-/* Return the label of the predicted edge, or CONST0_RTX if we don't know.  */
-
-rtx
-alpha_tablejump_best_label (rtx insn)
-{
-  rtx jump_table = alpha_tablejump_addr_vec (insn);
-  rtx best_label = NULL_RTX;
-
-  /* ??? Once the CFG doesn't keep getting completely rebuilt, look
-     there for edge frequency counts from profile data.  */
-
-  if (jump_table)
-    {
-      int n_labels = XVECLEN (jump_table, 1);
-      int best_count = -1;
-      int i, j;
-
-      for (i = 0; i < n_labels; i++)
-       {
-         int count = 1;
-
-         for (j = i + 1; j < n_labels; j++)
-           if (XEXP (XVECEXP (jump_table, 1, i), 0)
-               == XEXP (XVECEXP (jump_table, 1, j), 0))
-             count++;
-
-         if (count > best_count)
-           best_count = count, best_label = XVECEXP (jump_table, 1, i);
-       }
-    }
-
-  return best_label ? best_label : const0_rtx;
-}
-
 /* Return the TLS model to use for SYMBOL.  */
 
 static enum tls_model
index a51c87a078f38ea95d94ece256852cb2b8ef098c..4193515b3421115e00a1ca02f4ff70ae94b7c1d1 100644 (file)
@@ -11477,8 +11477,7 @@ is_jump_table (rtx insn)
 {
   rtx table;
 
-  if (GET_CODE (insn) == JUMP_INSN
-      && JUMP_LABEL (insn) != NULL
+  if (jump_to_label_p (insn)
       && ((table = next_real_insn (JUMP_LABEL (insn)))
          == next_real_insn (insn))
       && table != NULL
index 70fbf884bce87be1c93d97b5fe65030fcad43d82..31d9cfce3ef6536da3472ac6bd0042fb7c3c27d4 100644 (file)
@@ -5274,9 +5274,7 @@ barrier_align (rtx barrier_or_label)
            slot = 0;
          credit -= get_attr_length (prev);
        }
-      if (prev
-         && JUMP_P (prev)
-         && JUMP_LABEL (prev))
+      if (prev && jump_to_label_p (prev))
        {
          rtx x;
          if (jump_to_next
@@ -5975,7 +5973,7 @@ split_branches (rtx first)
                        JUMP_LABEL (insn) = far_label;
                        LABEL_NUSES (far_label)++;
                      }
-                   redirect_jump (insn, NULL_RTX, 1);
+                   redirect_jump (insn, ret_rtx, 1);
                    far_label = 0;
                  }
              }
index f1b8eb93daf6de405d452f3b32d2bcbd2d18240d..99b02bae315eefb4966fe7259c163c0431d4101c 100644 (file)
@@ -3322,14 +3322,17 @@ prev_label (rtx insn)
   return insn;
 }
 
-/* Return the last label to mark the same position as LABEL.  Return null
-   if LABEL itself is null.  */
+/* Return the last label to mark the same position as LABEL.  Return LABEL
+   itself if it is null or any return rtx.  */
 
 rtx
 skip_consecutive_labels (rtx label)
 {
   rtx insn;
 
+  if (label && ANY_RETURN_P (label))
+    return label;
+
   for (insn = label; insn != 0 && !INSN_P (insn); insn = NEXT_INSN (insn))
     if (LABEL_P (insn))
       label = insn;
index 361a8dce19737a146d900cba1dc679c211e138fd..c94680c76b7233df9a0d142403686f570a2c476f 100644 (file)
@@ -5305,7 +5305,8 @@ emit_use_return_register_into_block (basic_block bb)
 static void
 emit_return_into_block (basic_block bb)
 {
-  emit_jump_insn_after (gen_return (), BB_END (bb));
+  rtx jump = emit_jump_insn_after (gen_return (), BB_END (bb));
+  JUMP_LABEL (jump) = ret_rtx;
 }
 #endif /* HAVE_return */
 
@@ -5464,7 +5465,7 @@ thread_prologue_and_epilogue_insns (void)
                 that with a conditional return instruction.  */
              else if (condjump_p (jump))
                {
-                 if (! redirect_jump (jump, 0, 0))
+                 if (! redirect_jump (jump, ret_rtx, 0))
                    {
                      ei_next (&ei2);
                      continue;
@@ -5547,6 +5548,8 @@ thread_prologue_and_epilogue_insns (void)
 #ifdef HAVE_epilogue
   if (HAVE_epilogue)
     {
+      rtx returnjump;
+
       start_sequence ();
       epilogue_end = emit_note (NOTE_INSN_EPILOGUE_BEG);
       seq = gen_epilogue ();
@@ -5557,11 +5560,25 @@ thread_prologue_and_epilogue_insns (void)
       record_insns (seq, NULL, &epilogue_insn_hash);
       set_insn_locators (seq, epilogue_locator);
 
+      returnjump = get_last_insn ();
       seq = get_insns ();
       end_sequence ();
 
       insert_insn_on_edge (seq, e);
       inserted = true;
+
+      if (JUMP_P (returnjump))
+       {
+         rtx pat = PATTERN (returnjump);
+         if (GET_CODE (pat) == PARALLEL)
+           pat = XVECEXP (pat, 0, 0);
+         if (ANY_RETURN_P (pat))
+           JUMP_LABEL (returnjump) = pat;
+         else
+           JUMP_LABEL (returnjump) = ret_rtx;
+       }
+      else
+       returnjump = NULL_RTX;
     }
   else
 #endif
index a26df192a923d62b315841dd6724ea9b587f19ce..41bc01213160bee1d36a76d857b5f1cf69c5a78c 100644 (file)
@@ -104,7 +104,7 @@ static int cond_exec_find_if_block (ce_if_block_t *);
 static int find_if_case_1 (basic_block, edge, edge);
 static int find_if_case_2 (basic_block, edge, edge);
 static int dead_or_predicable (basic_block, basic_block, basic_block,
-                              basic_block, int);
+                              edge, int);
 static void noce_emit_move_insn (rtx, rtx);
 static rtx block_has_only_trap (basic_block);
 \f
@@ -3847,7 +3847,7 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
 
   /* Registers set are dead, or are predicable.  */
   if (! dead_or_predicable (test_bb, then_bb, else_bb,
-                           single_succ (then_bb), 1))
+                           single_succ_edge (then_bb), 1))
     return FALSE;
 
   /* Conversion went ok, including moving the insns and fixing up the
@@ -3962,7 +3962,7 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
     return FALSE;
 
   /* Registers set are dead, or are predicable.  */
-  if (! dead_or_predicable (test_bb, else_bb, then_bb, else_succ->dest, 0))
+  if (! dead_or_predicable (test_bb, else_bb, then_bb, else_succ, 0))
     return FALSE;
 
   /* Conversion went ok, including moving the insns and fixing up the
@@ -3985,18 +3985,21 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
    Return TRUE if successful.
 
    TEST_BB is the block containing the conditional branch.  MERGE_BB
-   is the block containing the code to manipulate.  NEW_DEST is the
-   label TEST_BB should be branching to after the conversion.
+   is the block containing the code to manipulate.  DEST_EDGE is an
+   edge representing a jump to the join block; after the conversion,
+   TEST_BB should be branching to its destination.
    REVERSEP is true if the sense of the branch should be reversed.  */
 
 static int
 dead_or_predicable (basic_block test_bb, basic_block merge_bb,
-                   basic_block other_bb, basic_block new_dest, int reversep)
+                   basic_block other_bb, edge dest_edge, int reversep)
 {
-  rtx head, end, jump, earliest = NULL_RTX, old_dest, new_label = NULL_RTX;
+  basic_block new_dest = dest_edge->dest;
+  rtx head, end, jump, earliest = NULL_RTX, old_dest;
   bitmap merge_set = NULL;
   /* Number of pending changes.  */
   int n_validated_changes = 0;
+  rtx new_dest_label = NULL_RTX;
 
   jump = BB_END (test_bb);
 
@@ -4134,10 +4137,16 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
   old_dest = JUMP_LABEL (jump);
   if (other_bb != new_dest)
     {
-      new_label = block_label (new_dest);
+      if (JUMP_P (BB_END (dest_edge->src)))
+       new_dest_label = JUMP_LABEL (BB_END (dest_edge->src));
+      else if (new_dest == EXIT_BLOCK_PTR)
+       new_dest_label = ret_rtx;
+      else
+       new_dest_label = block_label (new_dest);
+
       if (reversep
-         ? ! invert_jump_1 (jump, new_label)
-         : ! redirect_jump_1 (jump, new_label))
+         ? ! invert_jump_1 (jump, new_dest_label)
+         : ! redirect_jump_1 (jump, new_dest_label))
        goto cancel;
     }
 
@@ -4148,7 +4157,7 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
 
   if (other_bb != new_dest)
     {
-      redirect_jump_2 (jump, old_dest, new_label, 0, reversep);
+      redirect_jump_2 (jump, old_dest, new_dest_label, 0, reversep);
 
       redirect_edge_succ (BRANCH_EDGE (test_bb), new_dest);
       if (reversep)
index 0d29f0fcb18c47219eba6f07087eabc63bca84bd..2026243fd29de87b3ecc89e3c366faf0fe18308e 100644 (file)
@@ -970,6 +970,15 @@ onlyjump_p (const_rtx insn)
   return 1;
 }
 
+/* Return true iff INSN is a jump and its JUMP_LABEL is a label, not
+   NULL or a return.  */
+bool
+jump_to_label_p (rtx insn)
+{
+  return (JUMP_P (insn)
+         && JUMP_LABEL (insn) != NULL && !ANY_RETURN_P (JUMP_LABEL (insn)));
+}
+
 #ifdef HAVE_cc0
 
 /* Return nonzero if X is an RTX that only sets the condition codes
@@ -1233,7 +1242,7 @@ delete_related_insns (rtx insn)
   /* If deleting a jump, decrement the count of the label,
      and delete the label if it is now unused.  */
 
-  if (JUMP_P (insn) && JUMP_LABEL (insn))
+  if (jump_to_label_p (insn))
     {
       rtx lab = JUMP_LABEL (insn), lab_next;
 
@@ -1364,6 +1373,18 @@ delete_for_peephole (rtx from, rtx to)
      is also an unconditional jump in that case.  */
 }
 \f
+/* A helper function for redirect_exp_1; examines its input X and returns
+   either a LABEL_REF around a label, or a RETURN if X was NULL.  */
+static rtx
+redirect_target (rtx x)
+{
+  if (x == NULL_RTX)
+    return ret_rtx;
+  if (!ANY_RETURN_P (x))
+    return gen_rtx_LABEL_REF (Pmode, x);
+  return x;
+}
+
 /* Throughout LOC, redirect OLABEL to NLABEL.  Treat null OLABEL or
    NLABEL as a return.  Accrue modifications into the change group.  */
 
@@ -1375,37 +1396,22 @@ redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx insn)
   int i;
   const char *fmt;
 
-  if (code == LABEL_REF)
+      if ((code == LABEL_REF && XEXP (x, 0) == olabel)
+      || x == olabel)
     {
-      if (XEXP (x, 0) == olabel)
-       {
-         rtx n;
-         if (nlabel)
-           n = gen_rtx_LABEL_REF (Pmode, nlabel);
-         else
-           n = ret_rtx;
-
-         validate_change (insn, loc, n, 1);
-         return;
-       }
-    }
-  else if (code == RETURN && olabel == 0)
-    {
-      if (nlabel)
-       x = gen_rtx_LABEL_REF (Pmode, nlabel);
-      else
-       x = ret_rtx;
-      if (loc == &PATTERN (insn))
-       x = gen_rtx_SET (VOIDmode, pc_rtx, x);
+      x = redirect_target (nlabel);
+      if (GET_CODE (x) == LABEL_REF && loc == &PATTERN (insn))
+       x = gen_rtx_SET (VOIDmode, pc_rtx, x);
       validate_change (insn, loc, x, 1);
       return;
     }
 
-  if (code == SET && nlabel == 0 && SET_DEST (x) == pc_rtx
+  if (code == SET && SET_DEST (x) == pc_rtx
+      && ANY_RETURN_P (nlabel)
       && GET_CODE (SET_SRC (x)) == LABEL_REF
       && XEXP (SET_SRC (x), 0) == olabel)
     {
-      validate_change (insn, loc, ret_rtx, 1);
+      validate_change (insn, loc, nlabel, 1);
       return;
     }
 
@@ -1442,6 +1448,7 @@ redirect_jump_1 (rtx jump, rtx nlabel)
   int ochanges = num_validated_changes ();
   rtx *loc, asmop;
 
+  gcc_assert (nlabel != NULL_RTX);
   asmop = extract_asm_operands (PATTERN (jump));
   if (asmop)
     {
@@ -1463,17 +1470,20 @@ redirect_jump_1 (rtx jump, rtx nlabel)
    jump target label is unused as a result, it and the code following
    it may be deleted.
 
-   If NLABEL is zero, we are to turn the jump into a (possibly conditional)
-   RETURN insn.
+   Normally, NLABEL will be a label, but it may also be a RETURN rtx;
+   in that case we are to turn the jump into a (possibly conditional)
+   return insn.
 
    The return value will be 1 if the change was made, 0 if it wasn't
-   (this can only occur for NLABEL == 0).  */
+   (this can only occur when trying to produce return insns).  */
 
 int
 redirect_jump (rtx jump, rtx nlabel, int delete_unused)
 {
   rtx olabel = JUMP_LABEL (jump);
 
+  gcc_assert (nlabel != NULL_RTX);
+
   if (nlabel == olabel)
     return 1;
 
@@ -1501,13 +1511,14 @@ redirect_jump_2 (rtx jump, rtx olabel, rtx nlabel, int delete_unused,
      about this.  */
   gcc_assert (delete_unused >= 0);
   JUMP_LABEL (jump) = nlabel;
-  if (nlabel)
+  if (!ANY_RETURN_P (nlabel))
     ++LABEL_NUSES (nlabel);
 
   /* Update labels in any REG_EQUAL note.  */
   if ((note = find_reg_note (jump, REG_EQUAL, NULL_RTX)) != NULL_RTX)
     {
-      if (!nlabel || (invert && !invert_exp_1 (XEXP (note, 0), jump)))
+      if (ANY_RETURN_P (nlabel)
+         || (invert && !invert_exp_1 (XEXP (note, 0), jump)))
        remove_note (jump, note);
       else
        {
@@ -1516,7 +1527,8 @@ redirect_jump_2 (rtx jump, rtx olabel, rtx nlabel, int delete_unused,
        }
     }
 
-  if (olabel && --LABEL_NUSES (olabel) == 0 && delete_unused > 0
+  if (!ANY_RETURN_P (olabel)
+      && --LABEL_NUSES (olabel) == 0 && delete_unused > 0
       /* Undefined labels will remain outside the insn stream.  */
       && INSN_UID (olabel))
     delete_related_insns (olabel);
index 8e80630fbb363125871613285f09cc3ca7318317..9336f006aa5764e3b9d255bff64f7195fcfedd85 100644 (file)
@@ -323,9 +323,14 @@ print_rtx (const_rtx in_rtx)
              }
          }
        else if (i == 8 && JUMP_P (in_rtx) && JUMP_LABEL (in_rtx) != NULL)
-         /* Output the JUMP_LABEL reference.  */
-         fprintf (outfile, "\n%s%*s -> %d", print_rtx_head, indent * 2, "",
-                  INSN_UID (JUMP_LABEL (in_rtx)));
+         {
+           /* Output the JUMP_LABEL reference.  */
+           fprintf (outfile, "\n%s%*s -> ", print_rtx_head, indent * 2, "");
+           if (GET_CODE (JUMP_LABEL (in_rtx)) == RETURN)
+             fprintf (outfile, "return");
+           else
+             fprintf (outfile, "%d", INSN_UID (JUMP_LABEL (in_rtx)));
+         }
        else if (i == 0 && GET_CODE (in_rtx) == VALUE)
          {
 #ifndef GENERATOR_FILE
index 4df9105cb9a92d488f66c3f3fa6ceb7a357c27c5..97d02e934b5f8a8a76f63ede1a64179d07fb31cd 100644 (file)
@@ -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.  */
@@ -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;
@@ -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.  */
@@ -1827,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.  */
@@ -2245,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.  */
@@ -2270,7 +2278,7 @@ fill_simple_delay_slots (int non_jumps_p)
                target = JUMP_LABEL (insn);
            }
 
-         if (target == 0)
+         if (target == 0 || ANY_RETURN_P (target))
            for (trial = next_nonnote_insn (insn); !stop_search_p (trial, 1);
                 trial = next_trial)
              {
@@ -2343,7 +2351,7 @@ 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
@@ -2500,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.  */
@@ -2513,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;
@@ -2587,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
@@ -2757,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);
@@ -2776,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
@@ -2897,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)
@@ -2990,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;
@@ -3063,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)
@@ -3098,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,
@@ -3337,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
@@ -3373,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))
@@ -3382,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)
@@ -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
@@ -3540,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
@@ -3627,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.  */
@@ -3737,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.  */
@@ -3866,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);
index 1ee87c017afe7754d2b42b139d64ff1a3464b332..838011121134af858ffa05c3ff966de673f0568e 100644 (file)
@@ -495,6 +495,8 @@ find_dead_or_set_registers (rtx target, struct resources *res,
                  || GET_CODE (PATTERN (this_jump_insn)) == RETURN)
                {
                  next = JUMP_LABEL (this_jump_insn);
+                 if (ANY_RETURN_P (next))
+                   next = NULL_RTX;
                  if (jump_insn == 0)
                    {
                      jump_insn = insn;
@@ -562,9 +564,10 @@ find_dead_or_set_registers (rtx target, struct resources *res,
                  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);
+                 if (!ANY_RETURN_P (JUMP_LABEL (this_jump_insn)))
+                   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);
@@ -878,7 +881,7 @@ mark_target_live_regs (rtx insns, rtx target, struct resources *res)
   struct resources set, needed;
 
   /* Handle end of function.  */
-  if (target == 0)
+  if (target == 0 || ANY_RETURN_P (target))
     {
       *res = end_of_function_needs;
       return;
@@ -1097,8 +1100,9 @@ mark_target_live_regs (rtx insns, rtx target, struct resources *res)
       struct resources new_resources;
       rtx stop_insn = next_active_insn (jump_insn);
 
-      mark_target_live_regs (insns, next_active_insn (jump_target),
-                            &new_resources);
+      if (!ANY_RETURN_P (jump_target))
+       jump_target = next_active_insn (jump_target);
+      mark_target_live_regs (insns, jump_target, &new_resources);
       CLEAR_RESOURCE (&set);
       CLEAR_RESOURCE (&needed);
 
index 1490bfe432ca1214f6c6791523606d7054dfffde..3156006c85d4e439f786b95fd7ad01ebfa33201d 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -432,6 +432,9 @@ struct GTY((variable_size)) rtvec_def {
   (JUMP_P (INSN) && (GET_CODE (PATTERN (INSN)) == ADDR_VEC || \
                     GET_CODE (PATTERN (INSN)) == ADDR_DIFF_VEC))
 
+/* Predicate yielding nonzero iff X is a return.  */
+#define ANY_RETURN_P(X) ((X) == ret_rtx)
+
 /* 1 if X is a unary operator.  */
 
 #define UNARY_P(X)   \
@@ -2341,6 +2344,7 @@ extern void check_for_inc_dec (rtx insn);
 
 /* In jump.c */
 extern int comparison_dominates_p (enum rtx_code, enum rtx_code);
+extern bool jump_to_label_p (rtx);
 extern int condjump_p (const_rtx);
 extern int any_condjump_p (const_rtx);
 extern int any_uncondjump_p (const_rtx);
index 3692c16004b6a3e3e089b83581dc33a89d193b49..4b71b1ed879596679e45d2c1076032da7d1feb2d 100644 (file)
@@ -2660,8 +2660,11 @@ tablejump_p (const_rtx insn, rtx *labelp, rtx *tablep)
 {
   rtx label, table;
 
-  if (JUMP_P (insn)
-      && (label = JUMP_LABEL (insn)) != NULL_RTX
+  if (!JUMP_P (insn))
+    return false;
+
+  label = JUMP_LABEL (insn);
+  if (label != NULL_RTX && !ANY_RETURN_P (label)
       && (table = next_active_insn (label)) != NULL_RTX
       && JUMP_TABLE_DATA_P (table))
     {