OSDN Git Service

2004-03-01 Paolo Bonzini <bonzini@gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / jump.c
index dd099f2..ff161b2 100644 (file)
@@ -1,23 +1,23 @@
 /* Optimize jump instructions, for GNU compiler.
    Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
 /* Optimize jump instructions, for GNU compiler.
    Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
-   1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 
-This file is part of GNU CC.
+This file is part of GCC.
 
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 /* This is the pathetic reminder of old fame of the jump-optimization pass
    of the compiler.  Now it contains basically set of utility function to
 
 /* This is the pathetic reminder of old fame of the jump-optimization pass
    of the compiler.  Now it contains basically set of utility function to
@@ -31,11 +31,13 @@ Boston, MA 02111-1307, USA.  */
    formerly used them.  The JUMP_LABEL info is sometimes looked
    at by later passes.
 
    formerly used them.  The JUMP_LABEL info is sometimes looked
    at by later passes.
 
-   The subroutines delete_insn, redirect_jump, and invert_jump are used
+   The subroutines redirect_jump and invert_jump are used
    from other passes as well.  */
 
 #include "config.h"
 #include "system.h"
    from other passes as well.  */
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "tm_p.h"
 #include "flags.h"
 #include "rtl.h"
 #include "tm_p.h"
 #include "flags.h"
@@ -48,9 +50,11 @@ Boston, MA 02111-1307, USA.  */
 #include "expr.h"
 #include "real.h"
 #include "except.h"
 #include "expr.h"
 #include "real.h"
 #include "except.h"
+#include "diagnostic.h"
 #include "toplev.h"
 #include "reload.h"
 #include "predict.h"
 #include "toplev.h"
 #include "reload.h"
 #include "predict.h"
+#include "timevar.h"
 
 /* Optimize jump y; x: ... y: jumpif... x?
    Don't know if it is worth bothering with.  */
 
 /* Optimize jump y; x: ... y: jumpif... x?
    Don't know if it is worth bothering with.  */
@@ -59,30 +63,28 @@ Boston, MA 02111-1307, USA.  */
    or even change what is live at any point.
    So perhaps let combiner do it.  */
 
    or even change what is live at any point.
    So perhaps let combiner do it.  */
 
-static int init_label_info             PARAMS ((rtx));
-static void mark_all_labels            PARAMS ((rtx));
-static int duplicate_loop_exit_test    PARAMS ((rtx));
-static void delete_computation         PARAMS ((rtx));
-static void redirect_exp_1             PARAMS ((rtx *, rtx, rtx, rtx));
-static int redirect_exp                        PARAMS ((rtx, rtx, rtx));
-static void invert_exp_1               PARAMS ((rtx));
-static int invert_exp                  PARAMS ((rtx));
-static int returnjump_p_1              PARAMS ((rtx *, void *));
-static void delete_prior_computation    PARAMS ((rtx, rtx));
-static void mark_modified_reg          PARAMS ((rtx, rtx, void *));
+static rtx next_nonnote_insn_in_loop (rtx);
+static void init_label_info (rtx);
+static void mark_all_labels (rtx);
+static int duplicate_loop_exit_test (rtx);
+static void delete_computation (rtx);
+static void redirect_exp_1 (rtx *, rtx, rtx, rtx);
+static int redirect_exp (rtx, rtx, rtx);
+static void invert_exp_1 (rtx);
+static int invert_exp (rtx);
+static int returnjump_p_1 (rtx *, void *);
+static void delete_prior_computation (rtx, rtx);
 \f
 /* Alternate entry into the jump optimizer.  This entry point only rebuilds
    the JUMP_LABEL field in jumping insns and REG_LABEL notes in non-jumping
    instructions.  */
 void
 \f
 /* Alternate entry into the jump optimizer.  This entry point only rebuilds
    the JUMP_LABEL field in jumping insns and REG_LABEL notes in non-jumping
    instructions.  */
 void
-rebuild_jump_labels (f)
-     rtx f;
+rebuild_jump_labels (rtx f)
 {
 {
-  register rtx insn;
-  int max_uid = 0;
-
-  max_uid = init_label_info (f) + 1;
+  rtx insn;
 
 
+  timevar_push (TV_REBUILD_JUMP);
+  init_label_info (f);
   mark_all_labels (f);
 
   /* Keep track of labels used from static data; we don't track them
   mark_all_labels (f);
 
   /* Keep track of labels used from static data; we don't track them
@@ -92,13 +94,7 @@ rebuild_jump_labels (f)
   for (insn = forced_labels; insn; insn = XEXP (insn, 1))
     if (GET_CODE (XEXP (insn, 0)) == CODE_LABEL)
       LABEL_NUSES (XEXP (insn, 0))++;
   for (insn = forced_labels; insn; insn = XEXP (insn, 1))
     if (GET_CODE (XEXP (insn, 0)) == CODE_LABEL)
       LABEL_NUSES (XEXP (insn, 0))++;
-
-  /* Keep track of labels used for marking handlers for exception
-     regions; they cannot usually be deleted.  */
-
-  for (insn = exception_handler_labels; insn; insn = XEXP (insn, 1))
-    if (GET_CODE (XEXP (insn, 0)) == CODE_LABEL)
-      LABEL_NUSES (XEXP (insn, 0))++;
+  timevar_pop (TV_REBUILD_JUMP);
 }
 \f
 /* Some old code expects exactly one BARRIER as the NEXT_INSN of a
 }
 \f
 /* Some old code expects exactly one BARRIER as the NEXT_INSN of a
@@ -110,7 +106,7 @@ rebuild_jump_labels (f)
    old code is happy.
  */
 void
    old code is happy.
  */
 void
-cleanup_barriers ()
+cleanup_barriers (void)
 {
   rtx insn, next, prev;
   for (insn = get_insns (); insn; insn = next)
 {
   rtx insn, next, prev;
   for (insn = get_insns (); insn; insn = next)
@@ -127,11 +123,30 @@ cleanup_barriers ()
     }
 }
 \f
     }
 }
 \f
+/* Return the next insn after INSN that is not a NOTE and is in the loop,
+   i.e. when there is no such INSN before NOTE_INSN_LOOP_END return NULL_RTX.
+   This routine does not look inside SEQUENCEs.  */
+
+static rtx
+next_nonnote_insn_in_loop (rtx insn)
+{
+  while (insn)
+    {
+      insn = NEXT_INSN (insn);
+      if (insn == 0 || GET_CODE (insn) != NOTE)
+       break;
+      if (GET_CODE (insn) == NOTE
+         && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
+       return NULL_RTX;
+    }
+
+  return insn;
+}
+
 void
 void
-copy_loop_headers (f)
-     rtx f;
+copy_loop_headers (rtx f)
 {
 {
-  register rtx insn, next;
+  rtx insn, next;
   /* Now iterate optimizing jumps until nothing changes over one pass.  */
   for (insn = f; insn; insn = next)
     {
   /* Now iterate optimizing jumps until nothing changes over one pass.  */
   for (insn = f; insn; insn = next)
     {
@@ -145,7 +160,7 @@ copy_loop_headers (f)
         the values of regno_first_uid and regno_last_uid.  */
       if (GET_CODE (insn) == NOTE
          && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
         the values of regno_first_uid and regno_last_uid.  */
       if (GET_CODE (insn) == NOTE
          && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
-         && (temp1 = next_nonnote_insn (insn)) != 0
+         && (temp1 = next_nonnote_insn_in_loop (insn)) != 0
          && any_uncondjump_p (temp1) && onlyjump_p (temp1))
        {
          temp = PREV_INSN (insn);
          && any_uncondjump_p (temp1) && onlyjump_p (temp1))
        {
          temp = PREV_INSN (insn);
@@ -158,8 +173,7 @@ copy_loop_headers (f)
 }
 
 void
 }
 
 void
-purge_line_number_notes (f)
-     rtx f;
+purge_line_number_notes (rtx f)
 {
   rtx last_note = 0;
   rtx insn;
 {
   rtx last_note = 0;
   rtx insn;
@@ -182,7 +196,7 @@ purge_line_number_notes (f)
                && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last_note)
                && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last_note))
              {
                && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last_note)
                && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last_note))
              {
-               delete_insn (insn);
+               delete_related_insns (insn);
                continue;
              }
 
                continue;
              }
 
@@ -194,44 +208,35 @@ purge_line_number_notes (f)
 /* Initialize LABEL_NUSES and JUMP_LABEL fields.  Delete any REG_LABEL
    notes whose labels don't occur in the insn any more.  Returns the
    largest INSN_UID found.  */
 /* Initialize LABEL_NUSES and JUMP_LABEL fields.  Delete any REG_LABEL
    notes whose labels don't occur in the insn any more.  Returns the
    largest INSN_UID found.  */
-static int
-init_label_info (f)
-     rtx f;
+static void
+init_label_info (rtx f)
 {
 {
-  int largest_uid = 0;
   rtx insn;
 
   for (insn = f; insn; insn = NEXT_INSN (insn))
   rtx insn;
 
   for (insn = f; insn; insn = NEXT_INSN (insn))
-    {
-      if (GET_CODE (insn) == CODE_LABEL)
-       LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
-      else if (GET_CODE (insn) == JUMP_INSN)
-       JUMP_LABEL (insn) = 0;
-      else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
-       {
-         rtx note, next;
-
-         for (note = REG_NOTES (insn); note; note = next)
-           {
-             next = XEXP (note, 1);
-             if (REG_NOTE_KIND (note) == REG_LABEL
-                 && ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
-               remove_note (insn, note);
-           }
-       }
-      if (INSN_UID (insn) > largest_uid)
-       largest_uid = INSN_UID (insn);
-    }
+    if (GET_CODE (insn) == CODE_LABEL)
+      LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
+    else if (GET_CODE (insn) == JUMP_INSN)
+      JUMP_LABEL (insn) = 0;
+    else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
+      {
+       rtx note, next;
 
 
-  return largest_uid;
+       for (note = REG_NOTES (insn); note; note = next)
+         {
+           next = XEXP (note, 1);
+           if (REG_NOTE_KIND (note) == REG_LABEL
+               && ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
+             remove_note (insn, note);
+         }
+      }
 }
 
 /* Mark the label each jump jumps to.
    Combine consecutive labels, and count uses of labels.  */
 
 static void
 }
 
 /* Mark the label each jump jumps to.
    Combine consecutive labels, and count uses of labels.  */
 
 static void
-mark_all_labels (f)
-     rtx f;
+mark_all_labels (rtx f)
 {
   rtx insn;
 
 {
   rtx insn;
 
@@ -295,13 +300,13 @@ mark_all_labels (f)
    values of regno_first_uid and regno_last_uid.  */
 
 static int
    values of regno_first_uid and regno_last_uid.  */
 
 static int
-duplicate_loop_exit_test (loop_start)
-     rtx loop_start;
+duplicate_loop_exit_test (rtx loop_start)
 {
   rtx insn, set, reg, p, link;
   rtx copy = 0, first_copy = 0;
   int num_insns = 0;
 {
   rtx insn, set, reg, p, link;
   rtx copy = 0, first_copy = 0;
   int num_insns = 0;
-  rtx exitcode = NEXT_INSN (JUMP_LABEL (next_nonnote_insn (loop_start)));
+  rtx exitcode
+    = NEXT_INSN (JUMP_LABEL (next_nonnote_insn_in_loop (loop_start)));
   rtx lastexit;
   int max_reg = max_reg_num ();
   rtx *reg_map = 0;
   rtx lastexit;
   int max_reg = max_reg_num ();
   rtx *reg_map = 0;
@@ -313,8 +318,6 @@ duplicate_loop_exit_test (loop_start)
         is a CODE_LABEL
         has a REG_RETVAL or REG_LIBCALL note (hard to adjust)
         is a NOTE_INSN_LOOP_BEG because this means we have a nested loop
         is a CODE_LABEL
         has a REG_RETVAL or REG_LIBCALL note (hard to adjust)
         is a NOTE_INSN_LOOP_BEG because this means we have a nested loop
-        is a NOTE_INSN_BLOCK_{BEG,END} because duplicating these notes
-             is not valid.
 
      We also do not do this if we find an insn with ASM_OPERANDS.  While
      this restriction should not be necessary, copying an insn with
 
      We also do not do this if we find an insn with ASM_OPERANDS.  While
      this restriction should not be necessary, copying an insn with
@@ -334,18 +337,6 @@ duplicate_loop_exit_test (loop_start)
        case CALL_INSN:
          return 0;
        case NOTE:
        case CALL_INSN:
          return 0;
        case NOTE:
-         /* We could be in front of the wrong NOTE_INSN_LOOP_END if there is
-            a jump immediately after the loop start that branches outside
-            the loop but within an outer loop, near the exit test.
-            If we copied this exit test and created a phony
-            NOTE_INSN_LOOP_VTOP, this could make instructions immediately
-            before the exit test look like these could be safely moved
-            out of the loop even if they actually may be never executed.
-            This can be avoided by checking here for NOTE_INSN_LOOP_CONT.  */
-
-         if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
-             || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_CONT)
-           return 0;
 
          if (optimize < 2
              && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
 
          if (optimize < 2
              && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
@@ -359,10 +350,6 @@ duplicate_loop_exit_test (loop_start)
          break;
        case JUMP_INSN:
        case INSN:
          break;
        case JUMP_INSN:
        case INSN:
-         /* The code below would grossly mishandle REG_WAS_0 notes,
-            so get rid of them here.  */
-         while ((p = find_reg_note (insn, REG_WAS_0, NULL_RTX)) != 0)
-           remove_note (insn, p);
          if (++num_insns > 20
              || find_reg_note (insn, REG_RETVAL, NULL_RTX)
              || find_reg_note (insn, REG_LIBCALL, NULL_RTX))
          if (++num_insns > 20
              || find_reg_note (insn, REG_RETVAL, NULL_RTX)
              || find_reg_note (insn, REG_LIBCALL, NULL_RTX))
@@ -399,7 +386,7 @@ duplicate_loop_exit_test (loop_start)
            /* We can do the replacement.  Allocate reg_map if this is the
               first replacement we found.  */
            if (reg_map == 0)
            /* We can do the replacement.  Allocate reg_map if this is the
               first replacement we found.  */
            if (reg_map == 0)
-             reg_map = (rtx *) xcalloc (max_reg, sizeof (rtx));
+             reg_map = xcalloc (max_reg, sizeof (rtx));
 
            REG_LOOP_TEST_P (reg) = 1;
 
 
            REG_LOOP_TEST_P (reg) = 1;
 
@@ -431,6 +418,7 @@ duplicate_loop_exit_test (loop_start)
            replace_regs (PATTERN (copy), reg_map, max_reg, 1);
 
          mark_jump_label (PATTERN (copy), copy, 0);
            replace_regs (PATTERN (copy), reg_map, max_reg, 1);
 
          mark_jump_label (PATTERN (copy), copy, 0);
+         INSN_LOCATOR (copy) = INSN_LOCATOR (insn);
 
          /* Copy all REG_NOTES except REG_LABEL since mark_jump_label will
             make them.  */
 
          /* Copy all REG_NOTES except REG_LABEL since mark_jump_label will
             make them.  */
@@ -456,6 +444,7 @@ duplicate_loop_exit_test (loop_start)
        case JUMP_INSN:
          copy = emit_jump_insn_before (copy_insn (PATTERN (insn)),
                                        loop_start);
        case JUMP_INSN:
          copy = emit_jump_insn_before (copy_insn (PATTERN (insn)),
                                        loop_start);
+         INSN_LOCATOR (copy) = INSN_LOCATOR (insn);
          if (reg_map)
            replace_regs (PATTERN (copy), reg_map, max_reg, 1);
          mark_jump_label (PATTERN (copy), copy, 0);
          if (reg_map)
            replace_regs (PATTERN (copy), reg_map, max_reg, 1);
          mark_jump_label (PATTERN (copy), copy, 0);
@@ -529,7 +518,7 @@ duplicate_loop_exit_test (loop_start)
   /* Mark the exit code as the virtual top of the converted loop.  */
   emit_note_before (NOTE_INSN_LOOP_VTOP, exitcode);
 
   /* Mark the exit code as the virtual top of the converted loop.  */
   emit_note_before (NOTE_INSN_LOOP_VTOP, exitcode);
 
-  delete_insn (next_nonnote_insn (loop_start));
+  delete_related_insns (next_nonnote_insn (loop_start));
 
   /* Clean up.  */
   if (reg_map)
 
   /* Clean up.  */
   if (reg_map)
@@ -539,19 +528,23 @@ duplicate_loop_exit_test (loop_start)
 }
 \f
 /* Move all block-beg, block-end, loop-beg, loop-cont, loop-vtop, loop-end,
 }
 \f
 /* Move all block-beg, block-end, loop-beg, loop-cont, loop-vtop, loop-end,
-   notes between START and END out before START.  Assume that END is not
-   such a note.  START may be such a note.  Returns the value of the new
-   starting insn, which may be different if the original start was such a
-   note.  */
+   notes between START and END out before START.  START and END may be such
+   notes.  Returns the values of the new starting and ending insns, which
+   may be different if the original ones were such notes.
+   Return true if there were only such notes and no real instructions.  */
 
 
-rtx
-squeeze_notes (start, end)
-     rtx start, end;
+bool
+squeeze_notes (rtx* startp, rtx* endp)
 {
 {
+  rtx start = *startp;
+  rtx end = *endp;
+
   rtx insn;
   rtx next;
   rtx insn;
   rtx next;
+  rtx last = NULL;
+  rtx past_end = NEXT_INSN (end);
 
 
-  for (insn = start; insn != end; insn = next)
+  for (insn = start; insn != past_end; insn = next)
     {
       next = NEXT_INSN (insn);
       if (GET_CODE (insn) == NOTE
     {
       next = NEXT_INSN (insn);
       if (GET_CODE (insn) == NOTE
@@ -575,16 +568,25 @@ squeeze_notes (start, end)
              PREV_INSN (next) = prev;
            }
        }
              PREV_INSN (next) = prev;
            }
        }
+      else
+       last = insn;
     }
 
     }
 
-  return start;
+  /* There were no real instructions.  */
+  if (start == past_end)
+    return true;
+
+  end = last;
+
+  *startp = start;
+  *endp = end;
+  return false;
 }
 \f
 /* Return the label before INSN, or put a new label there.  */
 
 rtx
 }
 \f
 /* Return the label before INSN, or put a new label there.  */
 
 rtx
-get_label_before (insn)
-     rtx insn;
+get_label_before (rtx insn)
 {
   rtx label;
 
 {
   rtx label;
 
@@ -606,8 +608,7 @@ get_label_before (insn)
 /* Return the label after INSN, or put a new label there.  */
 
 rtx
 /* Return the label after INSN, or put a new label there.  */
 
 rtx
-get_label_after (insn)
-     rtx insn;
+get_label_after (rtx insn)
 {
   rtx label;
 
 {
   rtx label;
 
@@ -631,9 +632,7 @@ get_label_after (insn)
    description should define REVERSIBLE_CC_MODE and REVERSE_CONDITION macros
    to help this function avoid overhead in these cases.  */
 enum rtx_code
    description should define REVERSIBLE_CC_MODE and REVERSE_CONDITION macros
    to help this function avoid overhead in these cases.  */
 enum rtx_code
-reversed_comparison_code_parts (code, arg0, arg1, insn)
-     rtx insn, arg0, arg1;
-     enum rtx_code code;
+reversed_comparison_code_parts (enum rtx_code code, rtx arg0, rtx arg1, rtx insn)
 {
   enum machine_mode mode;
 
 {
   enum machine_mode mode;
 
@@ -653,52 +652,43 @@ reversed_comparison_code_parts (code, arg0, arg1, insn)
       && REVERSIBLE_CC_MODE (mode))
     {
 #ifdef REVERSE_CONDITION
       && REVERSIBLE_CC_MODE (mode))
     {
 #ifdef REVERSE_CONDITION
-          return REVERSE_CONDITION (code, mode);
+      return REVERSE_CONDITION (code, mode);
 #endif
 #endif
-          return reverse_condition (code);
-       }
+      return reverse_condition (code);
+    }
 #endif
 
   /* Try a few special cases based on the comparison code.  */
   switch (code)
     {
 #endif
 
   /* Try a few special cases based on the comparison code.  */
   switch (code)
     {
-      case GEU:
-      case GTU:
-      case LEU:
-      case LTU:
-      case NE:
-      case EQ:
-        /* It is always safe to reverse EQ and NE, even for the floating
-          point.  Similary the unsigned comparisons are never used for
-          floating point so we can reverse them in the default way.  */
-       return reverse_condition (code);
-      case ORDERED:
-      case UNORDERED:
-      case LTGT:
-      case UNEQ:
-       /* In case we already see unordered comparison, we can be sure to
-          be dealing with floating point so we don't need any more tests.  */
-       return reverse_condition_maybe_unordered (code);
-      case UNLT:
-      case UNLE:
-      case UNGT:
-      case UNGE:
-       /* We don't have safe way to reverse these yet.  */
-       return UNKNOWN;
-      default:
-       break;
+    case GEU:
+    case GTU:
+    case LEU:
+    case LTU:
+    case NE:
+    case EQ:
+      /* It is always safe to reverse EQ and NE, even for the floating
+        point.  Similarly the unsigned comparisons are never used for
+        floating point so we can reverse them in the default way.  */
+      return reverse_condition (code);
+    case ORDERED:
+    case UNORDERED:
+    case LTGT:
+    case UNEQ:
+      /* In case we already see unordered comparison, we can be sure to
+        be dealing with floating point so we don't need any more tests.  */
+      return reverse_condition_maybe_unordered (code);
+    case UNLT:
+    case UNLE:
+    case UNGT:
+    case UNGE:
+      /* We don't have safe way to reverse these yet.  */
+      return UNKNOWN;
+    default:
+      break;
     }
 
     }
 
-  /* In case we give up IEEE compatibility, all comparisons are reversible.  */
-  if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-      || flag_unsafe_math_optimizations)
-    return reverse_condition (code);
-
-  if (GET_MODE_CLASS (mode) == MODE_CC
-#ifdef HAVE_cc0
-      || arg0 == cc0_rtx
-#endif
-      )
+  if (GET_MODE_CLASS (mode) == MODE_CC || CC0_P (arg0))
     {
       rtx prev;
       /* Try to search for the comparison to determine the real mode.
     {
       rtx prev;
       /* Try to search for the comparison to determine the real mode.
@@ -727,7 +717,7 @@ reversed_comparison_code_parts (code, arg0, arg1, insn)
                    mode = GET_MODE (XEXP (comparison, 1));
                  break;
                }
                    mode = GET_MODE (XEXP (comparison, 1));
                  break;
                }
-             /* We can get past reg-reg moves.  This may be usefull for model
+             /* We can get past reg-reg moves.  This may be useful for model
                 of i387 comparisons that first move flag registers around.  */
              if (REG_P (src))
                {
                 of i387 comparisons that first move flag registers around.  */
              if (REG_P (src))
                {
@@ -742,21 +732,21 @@ reversed_comparison_code_parts (code, arg0, arg1, insn)
        }
     }
 
        }
     }
 
-  /* An integer condition.  */
+  /* Test for an integer condition, or a floating-point comparison
+     in which NaNs can be ignored.  */
   if (GET_CODE (arg0) == CONST_INT
       || (GET_MODE (arg0) != VOIDmode
          && GET_MODE_CLASS (mode) != MODE_CC
   if (GET_CODE (arg0) == CONST_INT
       || (GET_MODE (arg0) != VOIDmode
          && GET_MODE_CLASS (mode) != MODE_CC
-         && ! FLOAT_MODE_P (mode)))
+         && !HONOR_NANS (mode)))
     return reverse_condition (code);
 
   return UNKNOWN;
 }
 
     return reverse_condition (code);
 
   return UNKNOWN;
 }
 
-/* An wrapper around the previous function to take COMPARISON as rtx
+/* A wrapper around the previous function to take COMPARISON as rtx
    expression.  This simplifies many callers.  */
 enum rtx_code
    expression.  This simplifies many callers.  */
 enum rtx_code
-reversed_comparison_code (comparison, insn)
-     rtx comparison, insn;
+reversed_comparison_code (rtx comparison, rtx insn)
 {
   if (GET_RTX_CLASS (GET_CODE (comparison)) != '<')
     return UNKNOWN;
 {
   if (GET_RTX_CLASS (GET_CODE (comparison)) != '<')
     return UNKNOWN;
@@ -774,8 +764,7 @@ reversed_comparison_code (comparison, insn)
    Use reversed_comparison_code instead.  */
 
 enum rtx_code
    Use reversed_comparison_code instead.  */
 
 enum rtx_code
-reverse_condition (code)
-     enum rtx_code code;
+reverse_condition (enum rtx_code code)
 {
   switch (code)
     {
 {
   switch (code)
     {
@@ -822,13 +811,8 @@ reverse_condition (code)
    that the target will support them too...  */
 
 enum rtx_code
    that the target will support them too...  */
 
 enum rtx_code
-reverse_condition_maybe_unordered (code)
-     enum rtx_code code;
+reverse_condition_maybe_unordered (enum rtx_code code)
 {
 {
-  /* Non-IEEE formats don't have unordered conditions.  */
-  if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
-    return reverse_condition (code);
-
   switch (code)
     {
     case EQ:
   switch (code)
     {
     case EQ:
@@ -869,8 +853,7 @@ reverse_condition_maybe_unordered (code)
    This IS safe for IEEE floating-point.  */
 
 enum rtx_code
    This IS safe for IEEE floating-point.  */
 
 enum rtx_code
-swap_condition (code)
-     enum rtx_code code;
+swap_condition (enum rtx_code code)
 {
   switch (code)
     {
 {
   switch (code)
     {
@@ -917,8 +900,7 @@ swap_condition (code)
    CODE is returned.  */
 
 enum rtx_code
    CODE is returned.  */
 
 enum rtx_code
-unsigned_condition (code)
-     enum rtx_code code;
+unsigned_condition (enum rtx_code code)
 {
   switch (code)
     {
 {
   switch (code)
     {
@@ -947,8 +929,7 @@ unsigned_condition (code)
 /* Similarly, return the signed version of a comparison.  */
 
 enum rtx_code
 /* Similarly, return the signed version of a comparison.  */
 
 enum rtx_code
-signed_condition (code)
-     enum rtx_code code;
+signed_condition (enum rtx_code code)
 {
   switch (code)
     {
 {
   switch (code)
     {
@@ -974,12 +955,11 @@ signed_condition (code)
     }
 }
 \f
     }
 }
 \f
-/* Return non-zero if CODE1 is more strict than CODE2, i.e., if the
+/* Return nonzero if CODE1 is more strict than CODE2, i.e., if the
    truth of CODE1 implies the truth of CODE2.  */
 
 int
    truth of CODE1 implies the truth of CODE2.  */
 
 int
-comparison_dominates_p (code1, code2)
-     enum rtx_code code1, code2;
+comparison_dominates_p (enum rtx_code code1, enum rtx_code code2)
 {
   /* UNKNOWN comparison codes can happen as a result of trying to revert
      comparison codes.
 {
   /* UNKNOWN comparison codes can happen as a result of trying to revert
      comparison codes.
@@ -1060,8 +1040,7 @@ comparison_dominates_p (code1, code2)
 /* Return 1 if INSN is an unconditional jump and nothing else.  */
 
 int
 /* Return 1 if INSN is an unconditional jump and nothing else.  */
 
 int
-simplejump_p (insn)
-     rtx insn;
+simplejump_p (rtx insn)
 {
   return (GET_CODE (insn) == JUMP_INSN
          && GET_CODE (PATTERN (insn)) == SET
 {
   return (GET_CODE (insn) == JUMP_INSN
          && GET_CODE (PATTERN (insn)) == SET
@@ -1072,14 +1051,13 @@ simplejump_p (insn)
 /* Return nonzero if INSN is a (possibly) conditional jump
    and nothing more.
 
 /* Return nonzero if INSN is a (possibly) conditional jump
    and nothing more.
 
-   Use this function is deprecated, since we need to support combined
+   Use of this function is deprecated, since we need to support combined
    branch and compare insns.  Use any_condjump_p instead whenever possible.  */
 
 int
    branch and compare insns.  Use any_condjump_p instead whenever possible.  */
 
 int
-condjump_p (insn)
-     rtx insn;
+condjump_p (rtx insn)
 {
 {
-  register rtx x = PATTERN (insn);
+  rtx x = PATTERN (insn);
 
   if (GET_CODE (x) != SET
       || GET_CODE (SET_DEST (x)) != PC)
 
   if (GET_CODE (x) != SET
       || GET_CODE (SET_DEST (x)) != PC)
@@ -1107,10 +1085,9 @@ condjump_p (insn)
    branch and compare insns.  Use any_condjump_p instead whenever possible.  */
 
 int
    branch and compare insns.  Use any_condjump_p instead whenever possible.  */
 
 int
-condjump_in_parallel_p (insn)
-     rtx insn;
+condjump_in_parallel_p (rtx insn)
 {
 {
-  register rtx x = PATTERN (insn);
+  rtx x = PATTERN (insn);
 
   if (GET_CODE (x) != PARALLEL)
     return 0;
 
   if (GET_CODE (x) != PARALLEL)
     return 0;
@@ -1139,8 +1116,7 @@ condjump_in_parallel_p (insn)
 /* Return set of PC, otherwise NULL.  */
 
 rtx
 /* Return set of PC, otherwise NULL.  */
 
 rtx
-pc_set (insn)
-     rtx insn;
+pc_set (rtx insn)
 {
   rtx pat;
   if (GET_CODE (insn) != JUMP_INSN)
 {
   rtx pat;
   if (GET_CODE (insn) != JUMP_INSN)
@@ -1161,8 +1137,7 @@ pc_set (insn)
    possibly bundled inside a PARALLEL.  */
 
 int
    possibly bundled inside a PARALLEL.  */
 
 int
-any_uncondjump_p (insn)
-     rtx insn;
+any_uncondjump_p (rtx insn)
 {
   rtx x = pc_set (insn);
   if (!x)
 {
   rtx x = pc_set (insn);
   if (!x)
@@ -1180,8 +1155,7 @@ any_uncondjump_p (insn)
    Note that unlike condjump_p it returns false for unconditional jumps.  */
 
 int
    Note that unlike condjump_p it returns false for unconditional jumps.  */
 
 int
-any_condjump_p (insn)
-     rtx insn;
+any_condjump_p (rtx insn)
 {
   rtx x = pc_set (insn);
   enum rtx_code a, b;
 {
   rtx x = pc_set (insn);
   enum rtx_code a, b;
@@ -1201,8 +1175,7 @@ any_condjump_p (insn)
 /* Return the label of a conditional jump.  */
 
 rtx
 /* Return the label of a conditional jump.  */
 
 rtx
-condjump_label (insn)
-     rtx insn;
+condjump_label (rtx insn)
 {
   rtx x = pc_set (insn);
 
 {
   rtx x = pc_set (insn);
 
@@ -1223,17 +1196,16 @@ condjump_label (insn)
 /* Return true if INSN is a (possibly conditional) return insn.  */
 
 static int
 /* Return true if INSN is a (possibly conditional) return insn.  */
 
 static int
-returnjump_p_1 (loc, data)
-     rtx *loc;
-     void *data ATTRIBUTE_UNUSED;
+returnjump_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
 {
   rtx x = *loc;
 {
   rtx x = *loc;
-  return x && GET_CODE (x) == RETURN;
+
+  return x && (GET_CODE (x) == RETURN
+              || (GET_CODE (x) == SET && SET_IS_RETURN_P (x)));
 }
 
 int
 }
 
 int
-returnjump_p (insn)
-     rtx insn;
+returnjump_p (rtx insn)
 {
   if (GET_CODE (insn) != JUMP_INSN)
     return 0;
 {
   if (GET_CODE (insn) != JUMP_INSN)
     return 0;
@@ -1244,8 +1216,7 @@ returnjump_p (insn)
    nothing more.  */
 
 int
    nothing more.  */
 
 int
-onlyjump_p (insn)
-     rtx insn;
+onlyjump_p (rtx insn)
 {
   rtx set;
 
 {
   rtx set;
 
@@ -1265,15 +1236,35 @@ onlyjump_p (insn)
 
 #ifdef HAVE_cc0
 
 
 #ifdef HAVE_cc0
 
+/* Return nonzero if X is an RTX that only sets the condition codes
+   and has no side effects.  */
+
+int
+only_sets_cc0_p (rtx x)
+{
+  if (! x)
+    return 0;
+
+  if (INSN_P (x))
+    x = PATTERN (x);
+
+  return sets_cc0_p (x) == 1 && ! side_effects_p (x);
+}
+
 /* Return 1 if X is an RTX that does nothing but set the condition codes
    and CLOBBER or USE registers.
    Return -1 if X does explicitly set the condition codes,
    but also does other things.  */
 
 int
 /* Return 1 if X is an RTX that does nothing but set the condition codes
    and CLOBBER or USE registers.
    Return -1 if X does explicitly set the condition codes,
    but also does other things.  */
 
 int
-sets_cc0_p (x)
-     rtx x ATTRIBUTE_UNUSED;
+sets_cc0_p (rtx x)
 {
 {
+  if (! x)
+    return 0;
+
+  if (INSN_P (x))
+    x = PATTERN (x);
+
   if (GET_CODE (x) == SET && SET_DEST (x) == cc0_rtx)
     return 1;
   if (GET_CODE (x) == PARALLEL)
   if (GET_CODE (x) == SET && SET_DEST (x) == cc0_rtx)
     return 1;
   if (GET_CODE (x) == PARALLEL)
@@ -1305,13 +1296,12 @@ sets_cc0_p (x)
    a USE or CLOBBER.  */
 
 rtx
    a USE or CLOBBER.  */
 
 rtx
-follow_jumps (label)
-     rtx label;
+follow_jumps (rtx label)
 {
 {
-  register rtx insn;
-  register rtx next;
-  register rtx value = label;
-  register int depth;
+  rtx insn;
+  rtx next;
+  rtx value = label;
+  int depth;
 
   for (depth = 0;
        (depth < 10
 
   for (depth = 0;
        (depth < 10
@@ -1369,21 +1359,17 @@ follow_jumps (label)
    that loop-optimization is done with.  */
 
 void
    that loop-optimization is done with.  */
 
 void
-mark_jump_label (x, insn, in_mem)
-     register rtx x;
-     rtx insn;
-     int in_mem;
+mark_jump_label (rtx x, rtx insn, int in_mem)
 {
 {
-  register RTX_CODE code = GET_CODE (x);
-  register int i;
-  register const char *fmt;
+  RTX_CODE code = GET_CODE (x);
+  int i;
+  const char *fmt;
 
   switch (code)
     {
     case PC:
     case CC0:
     case REG:
 
   switch (code)
     {
     case PC:
     case CC0:
     case REG:
-    case SUBREG:
     case CONST_INT:
     case CONST_DOUBLE:
     case CLOBBER:
     case CONST_INT:
     case CONST_DOUBLE:
     case CLOBBER:
@@ -1466,7 +1452,7 @@ mark_jump_label (x, insn, in_mem)
        mark_jump_label (XEXP (x, i), insn, in_mem);
       else if (fmt[i] == 'E')
        {
        mark_jump_label (XEXP (x, i), insn, in_mem);
       else if (fmt[i] == 'E')
        {
-         register int j;
+         int j;
          for (j = 0; j < XVECLEN (x, i); j++)
            mark_jump_label (XVECEXP (x, i, j), insn, in_mem);
        }
          for (j = 0; j < XVECLEN (x, i); j++)
            mark_jump_label (XVECEXP (x, i, j), insn, in_mem);
        }
@@ -1478,10 +1464,9 @@ mark_jump_label (x, insn, in_mem)
    if that's what the previous thing was.  */
 
 void
    if that's what the previous thing was.  */
 
 void
-delete_jump (insn)
-     rtx insn;
+delete_jump (rtx insn)
 {
 {
-  register rtx set = single_set (insn);
+  rtx set = single_set (insn);
 
   if (set && GET_CODE (SET_DEST (set)) == PC)
     delete_computation (insn);
 
   if (set && GET_CODE (SET_DEST (set)) == PC)
     delete_computation (insn);
@@ -1490,8 +1475,7 @@ delete_jump (insn)
 /* Verify INSN is a BARRIER and delete it.  */
 
 void
 /* Verify INSN is a BARRIER and delete it.  */
 
 void
-delete_barrier (insn)
-     rtx insn;
+delete_barrier (rtx insn)
 {
   if (GET_CODE (insn) != BARRIER)
     abort ();
 {
   if (GET_CODE (insn) != BARRIER)
     abort ();
@@ -1504,9 +1488,7 @@ delete_barrier (insn)
    which is a REG_DEAD note associated with INSN.  */
 
 static void
    which is a REG_DEAD note associated with INSN.  */
 
 static void
-delete_prior_computation (note, insn)
-     rtx note;
-     rtx insn;
+delete_prior_computation (rtx note, rtx insn)
 {
   rtx our_prev;
   rtx reg = XEXP (note, 0);
 {
   rtx our_prev;
   rtx reg = XEXP (note, 0);
@@ -1521,12 +1503,14 @@ delete_prior_computation (note, insn)
       /* If we reach a CALL which is not calling a const function
         or the callee pops the arguments, then give up.  */
       if (GET_CODE (our_prev) == CALL_INSN
       /* If we reach a CALL which is not calling a const function
         or the callee pops the arguments, then give up.  */
       if (GET_CODE (our_prev) == CALL_INSN
-         && (! CONST_CALL_P (our_prev)
+         && (! CONST_OR_PURE_CALL_P (our_prev)
              || GET_CODE (pat) != SET || GET_CODE (SET_SRC (pat)) != CALL))
        break;
 
       /* If we reach a SEQUENCE, it is too complex to try to
              || GET_CODE (pat) != SET || GET_CODE (SET_SRC (pat)) != CALL))
        break;
 
       /* If we reach a SEQUENCE, it is too complex to try to
-        do anything with it, so give up.  */
+        do anything with it, so give up.  We can be run during
+        and after reorg, so SEQUENCE rtl can legitimately show
+        up here.  */
       if (GET_CODE (pat) == SEQUENCE)
        break;
 
       if (GET_CODE (pat) == SEQUENCE)
        break;
 
@@ -1567,13 +1551,13 @@ delete_prior_computation (note, insn)
              int dest_endregno
                = (dest_regno
                   + (dest_regno < FIRST_PSEUDO_REGISTER
              int dest_endregno
                = (dest_regno
                   + (dest_regno < FIRST_PSEUDO_REGISTER
-                     ? HARD_REGNO_NREGS (dest_regno,
-                                         GET_MODE (SET_DEST (pat))) : 1));
+                     ? hard_regno_nregs[dest_regno]
+                                       [GET_MODE (SET_DEST (pat))] : 1));
              int regno = REGNO (reg);
              int endregno
                = (regno
                   + (regno < FIRST_PSEUDO_REGISTER
              int regno = REGNO (reg);
              int endregno
                = (regno
                   + (regno < FIRST_PSEUDO_REGISTER
-                     ? HARD_REGNO_NREGS (regno, GET_MODE (reg)) : 1));
+                     ? hard_regno_nregs[regno][GET_MODE (reg)] : 1));
 
              if (dest_regno >= regno
                  && dest_endregno <= endregno)
 
              if (dest_regno >= regno
                  && dest_endregno <= endregno)
@@ -1630,8 +1614,7 @@ delete_prior_computation (note, insn)
    delete the insn that set it.  */
 
 static void
    delete the insn that set it.  */
 
 static void
-delete_computation (insn)
-     rtx insn;
+delete_computation (rtx insn)
 {
   rtx note, next;
 
 {
   rtx note, next;
 
@@ -1671,24 +1654,23 @@ delete_computation (insn)
       delete_prior_computation (note, insn);
     }
 
       delete_prior_computation (note, insn);
     }
 
-  delete_insn (insn);
+  delete_related_insns (insn);
 }
 \f
 }
 \f
-/* Delete insn INSN from the chain of insns and update label ref counts.
-   May delete some following insns as a consequence; may even delete
-   a label elsewhere and insns that follow it.
+/* Delete insn INSN from the chain of insns and update label ref counts
+   and delete insns now unreachable.
+
+   Returns the first insn after INSN that was not deleted.
 
 
-   Returns the first insn after INSN that was not deleted.  */
+   Usage of this instruction is deprecated.  Use delete_insn instead and
+   subsequent cfg_cleanup pass to delete unreachable code if needed.  */
 
 rtx
 
 rtx
-delete_insn (insn)
-     register rtx insn;
+delete_related_insns (rtx insn)
 {
 {
-  register rtx next = NEXT_INSN (insn);
-  register rtx prev = PREV_INSN (insn);
-  register int was_code_label = (GET_CODE (insn) == CODE_LABEL);
-  register int dont_really_delete = 0;
+  int was_code_label = (GET_CODE (insn) == CODE_LABEL);
   rtx note;
   rtx note;
+  rtx next = NEXT_INSN (insn), prev = PREV_INSN (insn);
 
   while (next && INSN_DELETED_P (next))
     next = NEXT_INSN (next);
 
   while (next && INSN_DELETED_P (next))
     next = NEXT_INSN (next);
@@ -1697,58 +1679,13 @@ delete_insn (insn)
   if (INSN_DELETED_P (insn))
     return next;
 
   if (INSN_DELETED_P (insn))
     return next;
 
-  if (was_code_label)
-    remove_node_from_expr_list (insn, &nonlocal_goto_handler_labels);
-
-  /* Don't delete user-declared labels.  When optimizing, convert them
-     to special NOTEs instead.  When not optimizing, leave them alone.  */
-  if (was_code_label && LABEL_NAME (insn) != 0)
-    {
-      if (optimize)
-       {
-         const char *name = LABEL_NAME (insn);
-         PUT_CODE (insn, NOTE);
-         NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED_LABEL;
-         NOTE_SOURCE_FILE (insn) = name;
-       }
-
-      dont_really_delete = 1;
-    }
-  else
-    /* Mark this insn as deleted.  */
-    INSN_DELETED_P (insn) = 1;
+  delete_insn (insn);
 
   /* If instruction is followed by a barrier,
      delete the barrier too.  */
 
   if (next != 0 && GET_CODE (next) == BARRIER)
 
   /* If instruction is followed by a barrier,
      delete the barrier too.  */
 
   if (next != 0 && GET_CODE (next) == BARRIER)
-    {
-      INSN_DELETED_P (next) = 1;
-      next = NEXT_INSN (next);
-    }
-
-  /* Patch out INSN (and the barrier if any) */
-
-  if (! dont_really_delete)
-    {
-      if (prev)
-       {
-         NEXT_INSN (prev) = next;
-         if (GET_CODE (prev) == INSN && GET_CODE (PATTERN (prev)) == SEQUENCE)
-           NEXT_INSN (XVECEXP (PATTERN (prev), 0,
-                               XVECLEN (PATTERN (prev), 0) - 1)) = next;
-       }
-
-      if (next)
-       {
-         PREV_INSN (next) = prev;
-         if (GET_CODE (next) == INSN && GET_CODE (PATTERN (next)) == SEQUENCE)
-           PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = prev;
-       }
-
-      if (prev && NEXT_INSN (prev) == 0)
-       set_last_insn (prev);
-    }
+    delete_insn (next);
 
   /* If deleting a jump, decrement the count of the label,
      and delete the label if it is now unused.  */
 
   /* If deleting a jump, decrement the count of the label,
      and delete the label if it is now unused.  */
@@ -1757,12 +1694,12 @@ delete_insn (insn)
     {
       rtx lab = JUMP_LABEL (insn), lab_next;
 
     {
       rtx lab = JUMP_LABEL (insn), lab_next;
 
-      if (--LABEL_NUSES (lab) == 0)
+      if (LABEL_NUSES (lab) == 0)
        {
          /* This can delete NEXT or PREV,
             either directly if NEXT is JUMP_LABEL (INSN),
             or indirectly through more levels of jumps.  */
        {
          /* This can delete NEXT or PREV,
             either directly if NEXT is JUMP_LABEL (INSN),
             or indirectly through more levels of jumps.  */
-         delete_insn (lab);
+         delete_related_insns (lab);
 
          /* I feel a little doubtful about this loop,
             but I see no clean and sure alternative way
 
          /* I feel a little doubtful about this loop,
             but I see no clean and sure alternative way
@@ -1772,16 +1709,13 @@ delete_insn (insn)
            next = NEXT_INSN (next);
          return next;
        }
            next = NEXT_INSN (next);
          return next;
        }
-      else if ((lab_next = next_nonnote_insn (lab)) != NULL
-              && GET_CODE (lab_next) == JUMP_INSN
-              && (GET_CODE (PATTERN (lab_next)) == ADDR_VEC
-                  || GET_CODE (PATTERN (lab_next)) == ADDR_DIFF_VEC))
+      else if (tablejump_p (insn, NULL, &lab_next))
        {
          /* If we're deleting the tablejump, delete the dispatch table.
        {
          /* If we're deleting the tablejump, delete the dispatch table.
-            We may not be able to kill the label immediately preceeding
+            We may not be able to kill the label immediately preceding
             just yet, as it might be referenced in code leading up to
             the tablejump.  */
             just yet, as it might be referenced in code leading up to
             the tablejump.  */
-         delete_insn (lab_next);
+         delete_related_insns (lab_next);
        }
     }
 
        }
     }
 
@@ -1796,8 +1730,8 @@ delete_insn (insn)
       int len = XVECLEN (pat, diff_vec_p);
 
       for (i = 0; i < len; i++)
       int len = XVECLEN (pat, diff_vec_p);
 
       for (i = 0; i < len; i++)
-       if (--LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0)) == 0)
-         delete_insn (XEXP (XVECEXP (pat, diff_vec_p, i), 0));
+       if (LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0)) == 0)
+         delete_related_insns (XEXP (XVECEXP (pat, diff_vec_p, i), 0));
       while (next && INSN_DELETED_P (next))
        next = NEXT_INSN (next);
       return next;
       while (next && INSN_DELETED_P (next))
        next = NEXT_INSN (next);
       return next;
@@ -1809,8 +1743,8 @@ delete_insn (insn)
       if (REG_NOTE_KIND (note) == REG_LABEL
          /* This could also be a NOTE_INSN_DELETED_LABEL note.  */
          && GET_CODE (XEXP (note, 0)) == CODE_LABEL)
       if (REG_NOTE_KIND (note) == REG_LABEL
          /* This could also be a NOTE_INSN_DELETED_LABEL note.  */
          && GET_CODE (XEXP (note, 0)) == CODE_LABEL)
-       if (--LABEL_NUSES (XEXP (note, 0)) == 0)
-         delete_insn (XEXP (note, 0));
+       if (LABEL_NUSES (XEXP (note, 0)) == 0)
+         delete_related_insns (XEXP (note, 0));
 
   while (prev && (INSN_DELETED_P (prev) || GET_CODE (prev) == NOTE))
     prev = PREV_INSN (prev);
 
   while (prev && (INSN_DELETED_P (prev) || GET_CODE (prev) == NOTE))
     prev = PREV_INSN (prev);
@@ -1824,13 +1758,13 @@ delete_insn (insn)
       && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
       && (GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC
          || GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_DIFF_VEC))
       && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
       && (GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC
          || GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_DIFF_VEC))
-    next = delete_insn (NEXT_INSN (insn));
+    next = delete_related_insns (NEXT_INSN (insn));
 
   /* If INSN was a label, delete insns following it if now unreachable.  */
 
   if (was_code_label && prev && GET_CODE (prev) == BARRIER)
     {
 
   /* If INSN was a label, delete insns following it if now unreachable.  */
 
   if (was_code_label && prev && GET_CODE (prev) == BARRIER)
     {
-      register RTX_CODE code;
+      RTX_CODE code;
       while (next != 0
             && (GET_RTX_CLASS (code = GET_CODE (next)) == 'i'
                 || code == NOTE || code == BARRIER
       while (next != 0
             && (GET_RTX_CLASS (code = GET_CODE (next)) == 'i'
                 || code == NOTE || code == BARRIER
@@ -1847,24 +1781,12 @@ delete_insn (insn)
               deletion of unreachable code, after a different label.
               As long as the value from this recursive call is correct,
               this invocation functions correctly.  */
               deletion of unreachable code, after a different label.
               As long as the value from this recursive call is correct,
               this invocation functions correctly.  */
-           next = delete_insn (next);
+           next = delete_related_insns (next);
        }
     }
 
   return next;
 }
        }
     }
 
   return next;
 }
-
-/* Advance from INSN till reaching something not deleted
-   then return that.  May return INSN itself.  */
-
-rtx
-next_nondeleted_insn (insn)
-     rtx insn;
-{
-  while (INSN_DELETED_P (insn))
-    insn = NEXT_INSN (insn);
-  return insn;
-}
 \f
 /* Delete a range of insns from FROM to TO, inclusive.
    This is for the sake of peephole optimization, so assume
 \f
 /* Delete a range of insns from FROM to TO, inclusive.
    This is for the sake of peephole optimization, so assume
@@ -1872,15 +1794,14 @@ next_nondeleted_insn (insn)
    peephole insn that will replace them.  */
 
 void
    peephole insn that will replace them.  */
 
 void
-delete_for_peephole (from, to)
-     register rtx from, to;
+delete_for_peephole (rtx from, rtx to)
 {
 {
-  register rtx insn = from;
+  rtx insn = from;
 
   while (1)
     {
 
   while (1)
     {
-      register rtx next = NEXT_INSN (insn);
-      register rtx prev = PREV_INSN (insn);
+      rtx next = NEXT_INSN (insn);
+      rtx prev = PREV_INSN (insn);
 
       if (GET_CODE (insn) != NOTE)
        {
 
       if (GET_CODE (insn) != NOTE)
        {
@@ -1907,36 +1828,49 @@ delete_for_peephole (from, to)
      is also an unconditional jump in that case.  */
 }
 \f
      is also an unconditional jump in that case.  */
 }
 \f
-/* We have determined that INSN is never reached, and are about to
-   delete it.  Print a warning if the user asked for one.
+/* We have determined that AVOIDED_INSN is never reached, and are
+   about to delete it.  If the insn chain between AVOIDED_INSN and
+   FINISH contains more than one line from the current function, and
+   contains at least one operation, print a warning if the user asked
+   for it.  If FINISH is NULL, look between AVOIDED_INSN and a LABEL.
 
 
-   To try to make this warning more useful, this should only be called
-   once per basic block not reached, and it only warns when the basic
-   block contains more than one line from the current function, and
-   contains at least one operation.  CSE and inlining can duplicate insns,
-   so it's possible to get spurious warnings from this.  */
+   CSE and inlining can duplicate insns, so it's possible to get
+   spurious warnings from this.  */
 
 void
 
 void
-never_reached_warning (avoided_insn)
-     rtx avoided_insn;
+never_reached_warning (rtx avoided_insn, rtx finish)
 {
   rtx insn;
   rtx a_line_note = NULL;
 {
   rtx insn;
   rtx a_line_note = NULL;
-  int two_avoided_lines = 0;
-  int contains_insn = 0;
+  int two_avoided_lines = 0, contains_insn = 0, reached_end = 0;
 
 
-  if (! warn_notreached)
+  if (!warn_notreached)
     return;
 
     return;
 
-  /* Scan forwards, looking at LINE_NUMBER notes, until
-     we hit a LABEL or we run out of insns.  */
+  /* Back up to the first of any NOTEs preceding avoided_insn; flow passes
+     us the head of a block, a NOTE_INSN_BASIC_BLOCK, which often follows
+     the line note.  */
+  insn = avoided_insn;
+  while (1)
+    {
+      rtx prev = PREV_INSN (insn);
+      if (prev == NULL_RTX
+         || GET_CODE (prev) != NOTE)
+       break;
+      insn = prev;
+    }
+
+  /* Scan forwards, looking at LINE_NUMBER notes, until we hit a LABEL
+     in case FINISH is NULL, otherwise until we run out of insns.  */
 
 
-  for (insn = avoided_insn; insn != NULL; insn = NEXT_INSN (insn))
+  for (; insn != NULL; insn = NEXT_INSN (insn))
     {
     {
-      if (GET_CODE (insn) == CODE_LABEL)
+      if ((finish == NULL && GET_CODE (insn) == CODE_LABEL)
+         || GET_CODE (insn) == BARRIER)
        break;
        break;
-      else if (GET_CODE (insn) == NOTE         /* A line number note?  */
-              && NOTE_LINE_NUMBER (insn) >= 0)
+
+      if (GET_CODE (insn) == NOTE              /* A line number note?  */
+         && NOTE_LINE_NUMBER (insn) >= 0)
        {
          if (a_line_note == NULL)
            a_line_note = insn;
        {
          if (a_line_note == NULL)
            a_line_note = insn;
@@ -1945,27 +1879,34 @@ never_reached_warning (avoided_insn)
                                  != NOTE_LINE_NUMBER (insn));
        }
       else if (INSN_P (insn))
                                  != NOTE_LINE_NUMBER (insn));
        }
       else if (INSN_P (insn))
-       contains_insn = 1;
+       {
+         if (reached_end)
+           break;
+         contains_insn = 1;
+       }
+
+      if (insn == finish)
+       reached_end = 1;
     }
   if (two_avoided_lines && contains_insn)
     }
   if (two_avoided_lines && contains_insn)
-    warning_with_file_and_line (NOTE_SOURCE_FILE (a_line_note),
-                               NOTE_LINE_NUMBER (a_line_note),
-                               "will never be executed");
+    {
+      location_t locus;
+      locus.file = NOTE_SOURCE_FILE (a_line_note);
+      locus.line = NOTE_LINE_NUMBER (a_line_note);
+      warning ("%Hwill never be executed", &locus);
+    }
 }
 \f
 /* Throughout LOC, redirect OLABEL to NLABEL.  Treat null OLABEL or
    NLABEL as a return.  Accrue modifications into the change group.  */
 
 static void
 }
 \f
 /* Throughout LOC, redirect OLABEL to NLABEL.  Treat null OLABEL or
    NLABEL as a return.  Accrue modifications into the change group.  */
 
 static void
-redirect_exp_1 (loc, olabel, nlabel, insn)
-     rtx *loc;
-     rtx olabel, nlabel;
-     rtx insn;
+redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx insn)
 {
 {
-  register rtx x = *loc;
-  register RTX_CODE code = GET_CODE (x);
-  register int i;
-  register const char *fmt;
+  rtx x = *loc;
+  RTX_CODE code = GET_CODE (x);
+  int i;
+  const char *fmt;
 
   if (code == LABEL_REF)
     {
 
   if (code == LABEL_REF)
     {
@@ -2005,7 +1946,7 @@ redirect_exp_1 (loc, olabel, nlabel, insn)
        redirect_exp_1 (&XEXP (x, i), olabel, nlabel, insn);
       else if (fmt[i] == 'E')
        {
        redirect_exp_1 (&XEXP (x, i), olabel, nlabel, insn);
       else if (fmt[i] == 'E')
        {
-         register int j;
+         int j;
          for (j = 0; j < XVECLEN (x, i); j++)
            redirect_exp_1 (&XVECEXP (x, i, j), olabel, nlabel, insn);
        }
          for (j = 0; j < XVECLEN (x, i); j++)
            redirect_exp_1 (&XVECEXP (x, i, j), olabel, nlabel, insn);
        }
@@ -2015,9 +1956,7 @@ redirect_exp_1 (loc, olabel, nlabel, insn)
 /* Similar, but apply the change group and report success or failure.  */
 
 static int
 /* Similar, but apply the change group and report success or failure.  */
 
 static int
-redirect_exp (olabel, nlabel, insn)
-     rtx olabel, nlabel;
-     rtx insn;
+redirect_exp (rtx olabel, rtx nlabel, rtx insn)
 {
   rtx *loc;
 
 {
   rtx *loc;
 
@@ -2038,8 +1977,7 @@ redirect_exp (olabel, nlabel, insn)
    not see how to do that.  */
 
 int
    not see how to do that.  */
 
 int
-redirect_jump_1 (jump, nlabel)
-     rtx jump, nlabel;
+redirect_jump_1 (rtx jump, rtx nlabel)
 {
   int ochanges = num_validated_changes ();
   rtx *loc;
 {
   int ochanges = num_validated_changes ();
   rtx *loc;
@@ -2064,11 +2002,10 @@ redirect_jump_1 (jump, nlabel)
    (this can only occur for NLABEL == 0).  */
 
 int
    (this can only occur for NLABEL == 0).  */
 
 int
-redirect_jump (jump, nlabel, delete_unused)
-     rtx jump, nlabel;
-     int delete_unused;
+redirect_jump (rtx jump, rtx nlabel, int delete_unused)
 {
 {
-  register rtx olabel = JUMP_LABEL (jump);
+  rtx olabel = JUMP_LABEL (jump);
+  rtx note;
 
   if (nlabel == olabel)
     return 1;
 
   if (nlabel == olabel)
     return 1;
@@ -2080,6 +2017,29 @@ redirect_jump (jump, nlabel, delete_unused)
   if (nlabel)
     ++LABEL_NUSES (nlabel);
 
   if (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 && olabel)
+       {
+         rtx dest = XEXP (note, 0);
+
+         if (GET_CODE (dest) == IF_THEN_ELSE)
+           {
+             if (GET_CODE (XEXP (dest, 1)) == LABEL_REF
+                 && XEXP (XEXP (dest, 1), 0) == olabel)
+               XEXP (XEXP (dest, 1), 0) = nlabel;
+             if (GET_CODE (XEXP (dest, 2)) == LABEL_REF
+                 && XEXP (XEXP (dest, 2), 0) == olabel)
+               XEXP (XEXP (dest, 2), 0) = nlabel;
+           }
+         else
+           remove_note (jump, note);
+       }
+      else
+        remove_note (jump, note);
+    }
+
   /* If we're eliding the jump over exception cleanups at the end of a
      function, move the function end note so that -Wreturn-type works.  */
   if (olabel && nlabel
   /* If we're eliding the jump over exception cleanups at the end of a
      function, move the function end note so that -Wreturn-type works.  */
   if (olabel && nlabel
@@ -2088,8 +2048,10 @@ redirect_jump (jump, nlabel, delete_unused)
       && NOTE_LINE_NUMBER (NEXT_INSN (olabel)) == NOTE_INSN_FUNCTION_END)
     emit_note_after (NOTE_INSN_FUNCTION_END, nlabel);
 
       && NOTE_LINE_NUMBER (NEXT_INSN (olabel)) == NOTE_INSN_FUNCTION_END)
     emit_note_after (NOTE_INSN_FUNCTION_END, nlabel);
 
-  if (olabel && --LABEL_NUSES (olabel) == 0 && delete_unused)
-    delete_insn (olabel);
+  if (olabel && --LABEL_NUSES (olabel) == 0 && delete_unused
+      /* Undefined labels will remain outside the insn stream.  */
+      && INSN_UID (olabel))
+    delete_related_insns (olabel);
 
   return 1;
 }
 
   return 1;
 }
@@ -2098,10 +2060,9 @@ redirect_jump (jump, nlabel, delete_unused)
    Accrue the modifications into the change group.  */
 
 static void
    Accrue the modifications into the change group.  */
 
 static void
-invert_exp_1 (insn)
-     rtx insn;
+invert_exp_1 (rtx insn)
 {
 {
-  register RTX_CODE code;
+  RTX_CODE code;
   rtx x = pc_set (insn);
 
   if (!x)
   rtx x = pc_set (insn);
 
   if (!x)
@@ -2112,8 +2073,8 @@ invert_exp_1 (insn)
 
   if (code == IF_THEN_ELSE)
     {
 
   if (code == IF_THEN_ELSE)
     {
-      register rtx comp = XEXP (x, 0);
-      register rtx tem;
+      rtx comp = XEXP (x, 0);
+      rtx tem;
       enum rtx_code reversed_code;
 
       /* We can do this in two ways:  The preferable way, which can only
       enum rtx_code reversed_code;
 
       /* We can do this in two ways:  The preferable way, which can only
@@ -2147,8 +2108,7 @@ invert_exp_1 (insn)
    matches a pattern.  */
 
 static int
    matches a pattern.  */
 
 static int
-invert_exp (insn)
-     rtx insn;
+invert_exp (rtx insn)
 {
   invert_exp_1 (insn);
   if (num_validated_changes () == 0)
 {
   invert_exp_1 (insn);
   if (num_validated_changes () == 0)
@@ -2163,8 +2123,7 @@ invert_exp (insn)
    inversion and redirection.  */
 
 int
    inversion and redirection.  */
 
 int
-invert_jump_1 (jump, nlabel)
-     rtx jump, nlabel;
+invert_jump_1 (rtx jump, rtx nlabel)
 {
   int ochanges;
 
 {
   int ochanges;
 
@@ -2180,9 +2139,7 @@ invert_jump_1 (jump, nlabel)
    NLABEL instead of where it jumps now.  Return true if successful.  */
 
 int
    NLABEL instead of where it jumps now.  Return true if successful.  */
 
 int
-invert_jump (jump, nlabel, delete_unused)
-     rtx jump, nlabel;
-     int delete_unused;
+invert_jump (rtx jump, rtx nlabel, int delete_unused)
 {
   /* We have to either invert the condition and change the label or
      do neither.  Either operation could fail.  We first try to invert
 {
   /* We have to either invert the condition and change the label or
      do neither.  Either operation could fail.  We first try to invert
@@ -2194,6 +2151,11 @@ invert_jump (jump, nlabel, delete_unused)
 
   if (redirect_jump (jump, nlabel, delete_unused))
     {
 
   if (redirect_jump (jump, nlabel, delete_unused))
     {
+      /* Remove REG_EQUAL note if we have one.  */
+      rtx note = find_reg_note (jump, REG_EQUAL, NULL_RTX);
+      if (note)
+       remove_note (jump, note);
+
       invert_br_probabilities (jump);
 
       return 1;
       invert_br_probabilities (jump);
 
       return 1;
@@ -2221,12 +2183,11 @@ invert_jump (jump, nlabel, delete_unused)
    case when the PLUS is inside a MEM.  */
 
 int
    case when the PLUS is inside a MEM.  */
 
 int
-rtx_renumbered_equal_p (x, y)
-     rtx x, y;
+rtx_renumbered_equal_p (rtx x, rtx y)
 {
 {
-  register int i;
-  register RTX_CODE code = GET_CODE (x);
-  register const char *fmt;
+  int i;
+  RTX_CODE code = GET_CODE (x);
+  const char *fmt;
 
   if (x == y)
     return 1;
 
   if (x == y)
     return 1;
@@ -2302,10 +2263,8 @@ rtx_renumbered_equal_p (x, y)
     case CC0:
     case ADDR_VEC:
     case ADDR_DIFF_VEC:
     case CC0:
     case ADDR_VEC:
     case ADDR_DIFF_VEC:
-      return 0;
-
     case CONST_INT:
     case CONST_INT:
-      return INTVAL (x) == INTVAL (y);
+      return 0;
 
     case LABEL_REF:
       /* We can't assume nonlocal labels have their following insns yet.  */
 
     case LABEL_REF:
       /* We can't assume nonlocal labels have their following insns yet.  */
@@ -2355,7 +2314,7 @@ rtx_renumbered_equal_p (x, y)
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
-      register int j;
+      int j;
       switch (fmt[i])
        {
        case 'w':
       switch (fmt[i])
        {
        case 'w':
@@ -2386,7 +2345,7 @@ rtx_renumbered_equal_p (x, y)
        case 'u':
          if (XEXP (x, i) != XEXP (y, i))
            return 0;
        case 'u':
          if (XEXP (x, i) != XEXP (y, i))
            return 0;
-         /* fall through.  */
+         /* Fall through.  */
        case '0':
          break;
 
        case '0':
          break;
 
@@ -2411,8 +2370,7 @@ rtx_renumbered_equal_p (x, y)
    return -1.  Any rtx is valid for X.  */
 
 int
    return -1.  Any rtx is valid for X.  */
 
 int
-true_regnum (x)
-     rtx x;
+true_regnum (rtx x)
 {
   if (GET_CODE (x) == REG)
     {
 {
   if (GET_CODE (x) == REG)
     {
@@ -2430,469 +2388,14 @@ true_regnum (x)
     }
   return -1;
 }
     }
   return -1;
 }
-\f
-/* Optimize code of the form:
-
-       for (x = a[i]; x; ...)
-         ...
-       for (x = a[i]; x; ...)
-         ...
-      foo:
-
-   Loop optimize will change the above code into
-
-       if (x = a[i])
-         for (;;)
-            { ...; if (! (x = ...)) break; }
-       if (x = a[i])
-         for (;;)
-            { ...; if (! (x = ...)) break; }
-      foo:
-
-   In general, if the first test fails, the program can branch
-   directly to `foo' and skip the second try which is doomed to fail.
-   We run this after loop optimization and before flow analysis.  */
-
-/* When comparing the insn patterns, we track the fact that different
-   pseudo-register numbers may have been used in each computation.
-   The following array stores an equivalence -- same_regs[I] == J means
-   that pseudo register I was used in the first set of tests in a context
-   where J was used in the second set.  We also count the number of such
-   pending equivalences.  If nonzero, the expressions really aren't the
-   same.  */
-
-static int *same_regs;
-
-static int num_same_regs;
-
-/* Track any registers modified between the target of the first jump and
-   the second jump.  They never compare equal.  */
-
-static char *modified_regs;
-
-/* Record if memory was modified.  */
-
-static int modified_mem;
-
-/* Called via note_stores on each insn between the target of the first
-   branch and the second branch.  It marks any changed registers.  */
-
-static void
-mark_modified_reg (dest, x, data)
-     rtx dest;
-     rtx x;
-     void *data ATTRIBUTE_UNUSED;
-{
-  int regno;
-  unsigned int i;
-
-  if (GET_CODE (dest) == SUBREG)
-    dest = SUBREG_REG (dest);
-
-  if (GET_CODE (dest) == MEM)
-    modified_mem = 1;
-
-  if (GET_CODE (dest) != REG)
-    return;
-
-  regno = REGNO (dest);
-  if (regno >= FIRST_PSEUDO_REGISTER)
-    modified_regs[regno] = 1;
-  /* Don't consider a hard condition code register as modified,
-     if it is only being set.  thread_jumps will check if it is set
-     to the same value.  */
-  else if (GET_MODE_CLASS (GET_MODE (dest)) != MODE_CC
-          || GET_CODE (x) != SET
-          || ! rtx_equal_p (dest, SET_DEST (x))
-          || HARD_REGNO_NREGS (regno, GET_MODE (dest)) != 1)
-    for (i = 0; i < HARD_REGNO_NREGS (regno, GET_MODE (dest)); i++)
-      modified_regs[regno + i] = 1;
-}
-
-/* F is the first insn in the chain of insns.  */
 
 
-void
-thread_jumps (f, max_reg, flag_before_loop)
-     rtx f;
-     int max_reg;
-     int flag_before_loop;
+/* Return regno of the register REG and handle subregs too.  */
+unsigned int
+reg_or_subregno (rtx reg)
 {
 {
-  /* Basic algorithm is to find a conditional branch,
-     the label it may branch to, and the branch after
-     that label.  If the two branches test the same condition,
-     walk back from both branch paths until the insn patterns
-     differ, or code labels are hit.  If we make it back to
-     the target of the first branch, then we know that the first branch
-     will either always succeed or always fail depending on the relative
-     senses of the two branches.  So adjust the first branch accordingly
-     in this case.  */
-
-  rtx label, b1, b2, t1, t2;
-  enum rtx_code code1, code2;
-  rtx b1op0, b1op1, b2op0, b2op1;
-  int changed = 1;
-  int i;
-  int *all_reset;
-  enum rtx_code reversed_code1, reversed_code2;
-
-  /* Allocate register tables and quick-reset table.  */
-  modified_regs = (char *) xmalloc (max_reg * sizeof (char));
-  same_regs = (int *) xmalloc (max_reg * sizeof (int));
-  all_reset = (int *) xmalloc (max_reg * sizeof (int));
-  for (i = 0; i < max_reg; i++)
-    all_reset[i] = -1;
-
-  while (changed)
-    {
-      changed = 0;
-
-      for (b1 = f; b1; b1 = NEXT_INSN (b1))
-       {
-         rtx set;
-         rtx set2;
-
-         /* Get to a candidate branch insn.  */
-         if (GET_CODE (b1) != JUMP_INSN
-             || ! any_condjump_p (b1) || JUMP_LABEL (b1) == 0)
-           continue;
-
-         memset (modified_regs, 0, max_reg * sizeof (char));
-         modified_mem = 0;
-
-         memcpy (same_regs, all_reset, max_reg * sizeof (int));
-         num_same_regs = 0;
-
-         label = JUMP_LABEL (b1);
-
-         /* Look for a branch after the target.  Record any registers and
-            memory modified between the target and the branch.  Stop when we
-            get to a label since we can't know what was changed there.  */
-         for (b2 = NEXT_INSN (label); b2; b2 = NEXT_INSN (b2))
-           {
-             if (GET_CODE (b2) == CODE_LABEL)
-               break;
-
-             else if (GET_CODE (b2) == JUMP_INSN)
-               {
-                 /* If this is an unconditional jump and is the only use of
-                    its target label, we can follow it.  */
-                 if (any_uncondjump_p (b2)
-                     && onlyjump_p (b2)
-                     && JUMP_LABEL (b2) != 0
-                     && LABEL_NUSES (JUMP_LABEL (b2)) == 1)
-                   {
-                     b2 = JUMP_LABEL (b2);
-                     continue;
-                   }
-                 else
-                   break;
-               }
-
-             if (GET_CODE (b2) != CALL_INSN && GET_CODE (b2) != INSN)
-               continue;
-
-             if (GET_CODE (b2) == CALL_INSN)
-               {
-                 modified_mem = 1;
-                 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-                   if (call_used_regs[i] && ! fixed_regs[i]
-                       && i != STACK_POINTER_REGNUM
-                       && i != FRAME_POINTER_REGNUM
-                       && i != HARD_FRAME_POINTER_REGNUM
-                       && i != ARG_POINTER_REGNUM)
-                     modified_regs[i] = 1;
-               }
-
-             note_stores (PATTERN (b2), mark_modified_reg, NULL);
-           }
-
-         /* Check the next candidate branch insn from the label
-            of the first.  */
-         if (b2 == 0
-             || GET_CODE (b2) != JUMP_INSN
-             || b2 == b1
-             || !any_condjump_p (b2)
-             || !onlyjump_p (b2))
-           continue;
-         set = pc_set (b1);
-         set2 = pc_set (b2);
-
-         /* Get the comparison codes and operands, reversing the
-            codes if appropriate.  If we don't have comparison codes,
-            we can't do anything.  */
-         b1op0 = XEXP (XEXP (SET_SRC (set), 0), 0);
-         b1op1 = XEXP (XEXP (SET_SRC (set), 0), 1);
-         code1 = GET_CODE (XEXP (SET_SRC (set), 0));
-         reversed_code1 = code1;
-         if (XEXP (SET_SRC (set), 1) == pc_rtx)
-           code1 = reversed_comparison_code (XEXP (SET_SRC (set), 0), b1);
-         else
-           reversed_code1 = reversed_comparison_code (XEXP (SET_SRC (set), 0), b1);
-
-         b2op0 = XEXP (XEXP (SET_SRC (set2), 0), 0);
-         b2op1 = XEXP (XEXP (SET_SRC (set2), 0), 1);
-         code2 = GET_CODE (XEXP (SET_SRC (set2), 0));
-         reversed_code2 = code2;
-         if (XEXP (SET_SRC (set2), 1) == pc_rtx)
-           code2 = reversed_comparison_code (XEXP (SET_SRC (set2), 0), b2);
-         else
-           reversed_code2 = reversed_comparison_code (XEXP (SET_SRC (set2), 0), b2);
-
-         /* If they test the same things and knowing that B1 branches
-            tells us whether or not B2 branches, check if we
-            can thread the branch.  */
-         if (rtx_equal_for_thread_p (b1op0, b2op0, b2)
-             && rtx_equal_for_thread_p (b1op1, b2op1, b2)
-             && (comparison_dominates_p (code1, code2)
-                 || comparison_dominates_p (code1, reversed_code2)))
-
-           {
-             t1 = prev_nonnote_insn (b1);
-             t2 = prev_nonnote_insn (b2);
-
-             while (t1 != 0 && t2 != 0)
-               {
-                 if (t2 == label)
-                   {
-                     /* We have reached the target of the first branch.
-                        If there are no pending register equivalents,
-                        we know that this branch will either always
-                        succeed (if the senses of the two branches are
-                        the same) or always fail (if not).  */
-                     rtx new_label;
-
-                     if (num_same_regs != 0)
-                       break;
-
-                     if (comparison_dominates_p (code1, code2))
-                       new_label = JUMP_LABEL (b2);
-                     else
-                       new_label = get_label_after (b2);
-
-                     if (JUMP_LABEL (b1) != new_label)
-                       {
-                         rtx prev = PREV_INSN (new_label);
-
-                         if (flag_before_loop
-                             && GET_CODE (prev) == NOTE
-                             && NOTE_LINE_NUMBER (prev) == NOTE_INSN_LOOP_BEG)
-                           {
-                             /* Don't thread to the loop label.  If a loop
-                                label is reused, loop optimization will
-                                be disabled for that loop.  */
-                             new_label = gen_label_rtx ();
-                             emit_label_after (new_label, PREV_INSN (prev));
-                           }
-                         changed |= redirect_jump (b1, new_label, 1);
-                       }
-                     break;
-                   }
-
-                 /* If either of these is not a normal insn (it might be
-                    a JUMP_INSN, CALL_INSN, or CODE_LABEL) we fail.  (NOTEs
-                    have already been skipped above.)  Similarly, fail
-                    if the insns are different.  */
-                 if (GET_CODE (t1) != INSN || GET_CODE (t2) != INSN
-                     || recog_memoized (t1) != recog_memoized (t2)
-                     || ! rtx_equal_for_thread_p (PATTERN (t1),
-                                                  PATTERN (t2), t2))
-                   break;
-
-                 t1 = prev_nonnote_insn (t1);
-                 t2 = prev_nonnote_insn (t2);
-               }
-           }
-       }
-    }
-
-  /* Clean up.  */
-  free (modified_regs);
-  free (same_regs);
-  free (all_reset);
-}
-\f
-/* This is like RTX_EQUAL_P except that it knows about our handling of
-   possibly equivalent registers and knows to consider volatile and
-   modified objects as not equal.
-
-   YINSN is the insn containing Y.  */
-
-int
-rtx_equal_for_thread_p (x, y, yinsn)
-     rtx x, y;
-     rtx yinsn;
-{
-  register int i;
-  register int j;
-  register enum rtx_code code;
-  register const char *fmt;
-
-  code = GET_CODE (x);
-  /* Rtx's of different codes cannot be equal.  */
-  if (code != GET_CODE (y))
-    return 0;
-
-  /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.
-     (REG:SI x) and (REG:HI x) are NOT equivalent.  */
-
-  if (GET_MODE (x) != GET_MODE (y))
-    return 0;
-
-  /* For floating-point, consider everything unequal.  This is a bit
-     pessimistic, but this pass would only rarely do anything for FP
-     anyway.  */
-  if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
-      && FLOAT_MODE_P (GET_MODE (x)) && ! flag_unsafe_math_optimizations)
-    return 0;
-
-  /* For commutative operations, the RTX match if the operand match in any
-     order.  Also handle the simple binary and unary cases without a loop.  */
-  if (code == EQ || code == NE || GET_RTX_CLASS (code) == 'c')
-    return ((rtx_equal_for_thread_p (XEXP (x, 0), XEXP (y, 0), yinsn)
-            && rtx_equal_for_thread_p (XEXP (x, 1), XEXP (y, 1), yinsn))
-           || (rtx_equal_for_thread_p (XEXP (x, 0), XEXP (y, 1), yinsn)
-               && rtx_equal_for_thread_p (XEXP (x, 1), XEXP (y, 0), yinsn)));
-  else if (GET_RTX_CLASS (code) == '<' || GET_RTX_CLASS (code) == '2')
-    return (rtx_equal_for_thread_p (XEXP (x, 0), XEXP (y, 0), yinsn)
-           && rtx_equal_for_thread_p (XEXP (x, 1), XEXP (y, 1), yinsn));
-  else if (GET_RTX_CLASS (code) == '1')
-    return rtx_equal_for_thread_p (XEXP (x, 0), XEXP (y, 0), yinsn);
-
-  /* Handle special-cases first.  */
-  switch (code)
-    {
-    case REG:
-      if (REGNO (x) == REGNO (y) && ! modified_regs[REGNO (x)])
-        return 1;
-
-      /* If neither is user variable or hard register, check for possible
-        equivalence.  */
-      if (REG_USERVAR_P (x) || REG_USERVAR_P (y)
-         || REGNO (x) < FIRST_PSEUDO_REGISTER
-         || REGNO (y) < FIRST_PSEUDO_REGISTER)
-       return 0;
-
-      if (same_regs[REGNO (x)] == -1)
-       {
-         same_regs[REGNO (x)] = REGNO (y);
-         num_same_regs++;
-
-         /* If this is the first time we are seeing a register on the `Y'
-            side, see if it is the last use.  If not, we can't thread the
-            jump, so mark it as not equivalent.  */
-         if (REGNO_LAST_UID (REGNO (y)) != INSN_UID (yinsn))
-           return 0;
-
-         return 1;
-       }
-      else
-       return (same_regs[REGNO (x)] == (int) REGNO (y));
-
-      break;
-
-    case MEM:
-      /* If memory modified or either volatile, not equivalent.
-        Else, check address.  */
-      if (modified_mem || MEM_VOLATILE_P (x) || MEM_VOLATILE_P (y))
-       return 0;
-
-      return rtx_equal_for_thread_p (XEXP (x, 0), XEXP (y, 0), yinsn);
-
-    case ASM_INPUT:
-      if (MEM_VOLATILE_P (x) || MEM_VOLATILE_P (y))
-       return 0;
-
-      break;
-
-    case SET:
-      /* Cancel a pending `same_regs' if setting equivalenced registers.
-        Then process source.  */
-      if (GET_CODE (SET_DEST (x)) == REG
-          && GET_CODE (SET_DEST (y)) == REG)
-       {
-         if (same_regs[REGNO (SET_DEST (x))] == (int) REGNO (SET_DEST (y)))
-           {
-             same_regs[REGNO (SET_DEST (x))] = -1;
-             num_same_regs--;
-           }
-         else if (REGNO (SET_DEST (x)) != REGNO (SET_DEST (y)))
-           return 0;
-       }
-      else
-       {
-         if (rtx_equal_for_thread_p (SET_DEST (x), SET_DEST (y), yinsn) == 0)
-           return 0;
-       }
-
-      return rtx_equal_for_thread_p (SET_SRC (x), SET_SRC (y), yinsn);
-
-    case LABEL_REF:
-      return XEXP (x, 0) == XEXP (y, 0);
-
-    case SYMBOL_REF:
-      return XSTR (x, 0) == XSTR (y, 0);
-
-    default:
-      break;
-    }
-
-  if (x == y)
-    return 1;
-
-  fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    {
-      switch (fmt[i])
-       {
-       case 'w':
-         if (XWINT (x, i) != XWINT (y, i))
-           return 0;
-         break;
-
-       case 'n':
-       case 'i':
-         if (XINT (x, i) != XINT (y, i))
-           return 0;
-         break;
-
-       case 'V':
-       case 'E':
-         /* Two vectors must have the same length.  */
-         if (XVECLEN (x, i) != XVECLEN (y, i))
-           return 0;
-
-         /* And the corresponding elements must match.  */
-         for (j = 0; j < XVECLEN (x, i); j++)
-           if (rtx_equal_for_thread_p (XVECEXP (x, i, j),
-                                       XVECEXP (y, i, j), yinsn) == 0)
-             return 0;
-         break;
-
-       case 'e':
-         if (rtx_equal_for_thread_p (XEXP (x, i), XEXP (y, i), yinsn) == 0)
-           return 0;
-         break;
-
-       case 'S':
-       case 's':
-         if (strcmp (XSTR (x, i), XSTR (y, i)))
-           return 0;
-         break;
-
-       case 'u':
-         /* These are just backpointers, so they don't matter.  */
-         break;
-
-       case '0':
-       case 't':
-         break;
-
-         /* It is believed that rtx's at this level will never
-            contain anything but integers and other rtx's,
-            except for within LABEL_REFs and SYMBOL_REFs.  */
-       default:
-         abort ();
-       }
-    }
-  return 1;
+  if (REG_P (reg))
+    return REGNO (reg);
+  if (GET_CODE (reg) == SUBREG)
+    return REGNO (SUBREG_REG (reg));
+  abort ();
 }
 }