OSDN Git Service

* config/xtensa/xtensa.c (xtensa_expand_builtin): Use CALL_EXPR_FN.
[pf3gnuchains/gcc-fork.git] / gcc / jump.c
index 86b3a94..e61e2fb 100644 (file)
@@ -1,6 +1,7 @@
 /* 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, 2005
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -16,11 +17,11 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 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.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, 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
+   of the compiler.  Now it contains basically a set of utility functions to
    operate with jumps.
 
    Each CODE_LABEL has a count of the times it is used
@@ -31,11 +32,13 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    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"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "tm_p.h"
 #include "flags.h"
@@ -48,9 +51,13 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "expr.h"
 #include "real.h"
 #include "except.h"
+#include "diagnostic.h"
 #include "toplev.h"
 #include "reload.h"
 #include "predict.h"
+#include "timevar.h"
+#include "tree-pass.h"
+#include "target.h"
 
 /* Optimize jump y; x: ... y: jumpif... x?
    Don't know if it is worth bothering with.  */
@@ -59,29 +66,22 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    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 init_label_info (rtx);
+static void mark_all_labels (rtx);
+static void redirect_exp_1 (rtx *, rtx, rtx, rtx);
+static int invert_exp_1 (rtx, rtx);
+static int returnjump_p_1 (rtx *, 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)
 {
   rtx insn;
-  int max_uid = 0;
-
-  max_uid = init_label_info (f) + 1;
 
+  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
@@ -89,15 +89,9 @@ rebuild_jump_labels (f)
      count doesn't drop to zero.  */
 
   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)
+    if (LABEL_P (XEXP (insn, 0)))
       LABEL_NUSES (XEXP (insn, 0))++;
+  timevar_pop (TV_REBUILD_JUMP);
 }
 \f
 /* Some old code expects exactly one BARRIER as the NEXT_INSN of a
@@ -108,157 +102,83 @@ rebuild_jump_labels (f)
    This simple pass moves barriers and removes duplicates so that the
    old code is happy.
  */
-void
-cleanup_barriers ()
+unsigned int
+cleanup_barriers (void)
 {
   rtx insn, next, prev;
   for (insn = get_insns (); insn; insn = next)
     {
       next = NEXT_INSN (insn);
-      if (GET_CODE (insn) == BARRIER)
+      if (BARRIER_P (insn))
        {
          prev = prev_nonnote_insn (insn);
-         if (GET_CODE (prev) == BARRIER)
-           delete_barrier (insn);
+         if (BARRIER_P (prev))
+           delete_insn (insn);
          else if (prev != PREV_INSN (insn))
            reorder_insns (insn, insn, prev);
        }
     }
-}
-\f
-void
-copy_loop_headers (f)
-     rtx f;
-{
-  rtx insn, next;
-  /* Now iterate optimizing jumps until nothing changes over one pass.  */
-  for (insn = f; insn; insn = next)
-    {
-      rtx temp, temp1;
-
-      next = NEXT_INSN (insn);
-
-      /* See if this is a NOTE_INSN_LOOP_BEG followed by an unconditional
-        jump.  Try to optimize by duplicating the loop exit test if so.
-        This is only safe immediately after regscan, because it uses
-        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
-         && any_uncondjump_p (temp1) && onlyjump_p (temp1))
-       {
-         temp = PREV_INSN (insn);
-         if (duplicate_loop_exit_test (insn))
-           {
-             next = NEXT_INSN (temp);
-           }
-       }
-    }
+  return 0;
 }
 
-void
-purge_line_number_notes (f)
-     rtx f;
+struct tree_opt_pass pass_cleanup_barriers =
 {
-  rtx last_note = 0;
-  rtx insn;
-  /* Delete extraneous line number notes.
-     Note that two consecutive notes for different lines are not really
-     extraneous.  There should be some indication where that line belonged,
-     even if it became empty.  */
+  "barriers",                           /* name */
+  NULL,                                 /* gate */
+  cleanup_barriers,                     /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  0,                                    /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  TODO_dump_func,                       /* todo_flags_finish */
+  0                                     /* letter */
+};
 
-  for (insn = f; insn; insn = NEXT_INSN (insn))
-    if (GET_CODE (insn) == NOTE)
-      {
-       if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
-         /* Any previous line note was for the prologue; gdb wants a new
-            note after the prologue even if it is for the same line.  */
-         last_note = NULL_RTX;
-       else if (NOTE_LINE_NUMBER (insn) >= 0)
-         {
-           /* Delete this note if it is identical to previous note.  */
-           if (last_note
-               && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last_note)
-               && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last_note))
-             {
-               delete_related_insns (insn);
-               continue;
-             }
-
-           last_note = insn;
-         }
-      }
-}
 \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.  */
-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))
-    {
-      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 (LABEL_P (insn))
+      LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
+    else if (JUMP_P (insn))
+      JUMP_LABEL (insn) = 0;
+    else if (NONJUMP_INSN_P (insn) || CALL_P (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_all_labels (f)
-     rtx f;
+mark_all_labels (rtx f)
 {
   rtx insn;
 
   for (insn = f; insn; insn = NEXT_INSN (insn))
     if (INSN_P (insn))
       {
-       if (GET_CODE (insn) == CALL_INSN
-           && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
-         {
-           mark_all_labels (XEXP (PATTERN (insn), 0));
-           mark_all_labels (XEXP (PATTERN (insn), 1));
-           mark_all_labels (XEXP (PATTERN (insn), 2));
-
-           /* Canonicalize the tail recursion label attached to the
-              CALL_PLACEHOLDER insn.  */
-           if (XEXP (PATTERN (insn), 3))
-             {
-               rtx label_ref = gen_rtx_LABEL_REF (VOIDmode,
-                                                  XEXP (PATTERN (insn), 3));
-               mark_jump_label (label_ref, insn, 0);
-               XEXP (PATTERN (insn), 3) = XEXP (label_ref, 0);
-             }
-
-           continue;
-         }
-
        mark_jump_label (PATTERN (insn), insn, 0);
-       if (! INSN_DELETED_P (insn) && GET_CODE (insn) == JUMP_INSN)
+       if (! INSN_DELETED_P (insn) && JUMP_P (insn))
          {
            /* When we know the LABEL_REF contained in a REG used in
               an indirect jump, we'll have a REG_LABEL note so that
@@ -270,7 +190,7 @@ mark_all_labels (f)
                  {
                    /* But a LABEL_REF around the REG_LABEL note, so
                       that we can canonicalize it.  */
-                   rtx label_ref = gen_rtx_LABEL_REF (VOIDmode,
+                   rtx label_ref = gen_rtx_LABEL_REF (Pmode,
                                                       XEXP (label_note, 0));
 
                    mark_jump_label (label_ref, insn, 0);
@@ -280,273 +200,41 @@ mark_all_labels (f)
              }
          }
       }
-}
-
-/* LOOP_START is a NOTE_INSN_LOOP_BEG note that is followed by an unconditional
-   jump.  Assume that this unconditional jump is to the exit test code.  If
-   the code is sufficiently simple, make a copy of it before INSN,
-   followed by a jump to the exit of the loop.  Then delete the unconditional
-   jump after INSN.
-
-   Return 1 if we made the change, else 0.
-
-   This is only safe immediately after a regscan pass because it uses the
-   values of regno_first_uid and regno_last_uid.  */
-
-static int
-duplicate_loop_exit_test (loop_start)
-     rtx loop_start;
-{
-  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 lastexit;
-  int max_reg = max_reg_num ();
-  rtx *reg_map = 0;
-  rtx loop_pre_header_label;
-
-  /* Scan the exit code.  We do not perform this optimization if any insn:
-
-         is a CALL_INSN
-        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
-     ASM_OPERANDS can confuse asm_noperands in some cases.
-
-     Also, don't do this if the exit code is more than 20 insns.  */
-
-  for (insn = exitcode;
-       insn
-       && ! (GET_CODE (insn) == NOTE
-            && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END);
-       insn = NEXT_INSN (insn))
+  
+  /* If we are in cfglayout mode, there may be non-insns between the
+     basic blocks.  If those non-insns represent tablejump data, they
+     contain label references that we must record.  */
+  if (current_ir_type () == IR_RTL_CFGLAYOUT)
     {
-      switch (GET_CODE (insn))
+      basic_block bb;
+      rtx insn;
+      FOR_EACH_BB (bb)
        {
-       case CODE_LABEL:
-       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
-                 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END))
-           /* If we were to duplicate this code, we would not move
-              the BLOCK notes, and so debugging the moved code would
-              be difficult.  Thus, we only move the code with -O2 or
-              higher.  */
-           return 0;
-
-         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))
-           return 0;
-         break;
-       default:
-         break;
-       }
-    }
-
-  /* Unless INSN is zero, we can do the optimization.  */
-  if (insn == 0)
-    return 0;
-
-  lastexit = insn;
-
-  /* See if any insn sets a register only used in the loop exit code and
-     not a user variable.  If so, replace it with a new register.  */
-  for (insn = exitcode; insn != lastexit; insn = NEXT_INSN (insn))
-    if (GET_CODE (insn) == INSN
-       && (set = single_set (insn)) != 0
-       && ((reg = SET_DEST (set), GET_CODE (reg) == REG)
-           || (GET_CODE (reg) == SUBREG
-               && (reg = SUBREG_REG (reg), GET_CODE (reg) == REG)))
-       && REGNO (reg) >= FIRST_PSEUDO_REGISTER
-       && REGNO_FIRST_UID (REGNO (reg)) == INSN_UID (insn))
-      {
-       for (p = NEXT_INSN (insn); p != lastexit; p = NEXT_INSN (p))
-         if (REGNO_LAST_UID (REGNO (reg)) == INSN_UID (p))
-           break;
-
-       if (p != lastexit)
-         {
-           /* 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_LOOP_TEST_P (reg) = 1;
-
-           reg_map[REGNO (reg)] = gen_reg_rtx (GET_MODE (reg));
-         }
-      }
-  loop_pre_header_label = gen_label_rtx ();
-
-  /* Now copy each insn.  */
-  for (insn = exitcode; insn != lastexit; insn = NEXT_INSN (insn))
-    {
-      switch (GET_CODE (insn))
-       {
-       case BARRIER:
-         copy = emit_barrier_before (loop_start);
-         break;
-       case NOTE:
-         /* Only copy line-number notes.  */
-         if (NOTE_LINE_NUMBER (insn) >= 0)
-           {
-             copy = emit_note_before (NOTE_LINE_NUMBER (insn), loop_start);
-             NOTE_SOURCE_FILE (copy) = NOTE_SOURCE_FILE (insn);
-           }
-         break;
-
-       case INSN:
-         copy = emit_insn_before (copy_insn (PATTERN (insn)), loop_start);
-         if (reg_map)
-           replace_regs (PATTERN (copy), reg_map, max_reg, 1);
-
-         mark_jump_label (PATTERN (copy), copy, 0);
-
-         /* Copy all REG_NOTES except REG_LABEL since mark_jump_label will
-            make them.  */
-         for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
-           if (REG_NOTE_KIND (link) != REG_LABEL)
+         for (insn = bb->il.rtl->header; insn; insn = NEXT_INSN (insn))
+           if (INSN_P (insn))
              {
-               if (GET_CODE (link) == EXPR_LIST)
-                 REG_NOTES (copy)
-                   = copy_insn_1 (gen_rtx_EXPR_LIST (REG_NOTE_KIND (link),
-                                                     XEXP (link, 0),
-                                                     REG_NOTES (copy)));
-               else
-                 REG_NOTES (copy)
-                   = copy_insn_1 (gen_rtx_INSN_LIST (REG_NOTE_KIND (link),
-                                                     XEXP (link, 0),
-                                                     REG_NOTES (copy)));
+               gcc_assert (JUMP_TABLE_DATA_P (insn));
+               mark_jump_label (PATTERN (insn), insn, 0);
              }
 
-         if (reg_map && REG_NOTES (copy))
-           replace_regs (REG_NOTES (copy), reg_map, max_reg, 1);
-         break;
-
-       case JUMP_INSN:
-         copy = emit_jump_insn_before (copy_insn (PATTERN (insn)),
-                                       loop_start);
-         if (reg_map)
-           replace_regs (PATTERN (copy), reg_map, max_reg, 1);
-         mark_jump_label (PATTERN (copy), copy, 0);
-         if (REG_NOTES (insn))
-           {
-             REG_NOTES (copy) = copy_insn_1 (REG_NOTES (insn));
-             if (reg_map)
-               replace_regs (REG_NOTES (copy), reg_map, max_reg, 1);
-           }
-
-         /* Predict conditional jump that do make loop looping as taken.
-            Other jumps are probably exit conditions, so predict
-            them as untaken.  */
-         if (any_condjump_p (copy))
-           {
-             rtx label = JUMP_LABEL (copy);
-             if (label)
-               {
-                 /* The jump_insn after loop_start should be followed
-                    by barrier and loopback label.  */
-                 if (prev_nonnote_insn (label)
-                     && (prev_nonnote_insn (prev_nonnote_insn (label))
-                         == next_nonnote_insn (loop_start)))
-                   {
-                     predict_insn_def (copy, PRED_LOOP_HEADER, TAKEN);
-                     /* To keep pre-header, we need to redirect all loop
-                        entrances before the LOOP_BEG note.  */
-                     redirect_jump (copy, loop_pre_header_label, 0);
-                   }
-                 else
-                   predict_insn_def (copy, PRED_LOOP_HEADER, NOT_TAKEN);
-               }
-           }
-         break;
-
-       default:
-         abort ();
+         for (insn = bb->il.rtl->footer; insn; insn = NEXT_INSN (insn))
+           if (INSN_P (insn))
+             {
+               gcc_assert (JUMP_TABLE_DATA_P (insn));
+               mark_jump_label (PATTERN (insn), insn, 0);
+             }
        }
-
-      /* Record the first insn we copied.  We need it so that we can
-        scan the copied insns for new pseudo registers.  */
-      if (! first_copy)
-       first_copy = copy;
     }
-
-  /* Now clean up by emitting a jump to the end label and deleting the jump
-     at the start of the loop.  */
-  if (! copy || GET_CODE (copy) != BARRIER)
-    {
-      copy = emit_jump_insn_before (gen_jump (get_label_after (insn)),
-                                   loop_start);
-
-      /* Record the first insn we copied.  We need it so that we can
-        scan the copied insns for new pseudo registers.   This may not
-        be strictly necessary since we should have copied at least one
-        insn above.  But I am going to be safe.  */
-      if (! first_copy)
-       first_copy = copy;
-
-      mark_jump_label (PATTERN (copy), copy, 0);
-      emit_barrier_before (loop_start);
-    }
-
-  emit_label_before (loop_pre_header_label, loop_start);
-
-  /* Now scan from the first insn we copied to the last insn we copied
-     (copy) for new pseudo registers.  Do this after the code to jump to
-     the end label since that might create a new pseudo too.  */
-  reg_scan_update (first_copy, copy, max_reg);
-
-  /* Mark the exit code as the virtual top of the converted loop.  */
-  emit_note_before (NOTE_INSN_LOOP_VTOP, exitcode);
-
-  delete_related_insns (next_nonnote_insn (loop_start));
-
-  /* Clean up.  */
-  if (reg_map)
-    free (reg_map);
-
-  return 1;
 }
 \f
-/* Move all block-beg, block-end, loop-beg, loop-cont, loop-vtop, loop-end,
-   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.  */
+/* Move all block-beg, block-end and loop-beg 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.  */
 
 bool
-squeeze_notes (startp, endp)
-     rtx* startp;
-     rtx* endp;
+squeeze_notes (rtx* startp, rtx* endp)
 {
   rtx start = *startp;
   rtx end = *endp;
@@ -559,14 +247,14 @@ squeeze_notes (startp, endp)
   for (insn = start; insn != past_end; insn = next)
     {
       next = NEXT_INSN (insn);
-      if (GET_CODE (insn) == NOTE
+      if (NOTE_P (insn)
          && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END
-             || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
-             || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
-             || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END
-             || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_CONT
-             || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_VTOP))
+             || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG))
        {
+         /* BLOCK_BEG or BLOCK_END notes only exist in the `final' pass.  */
+         gcc_assert (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_BEG
+                     && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_END);
+
          if (insn == start)
            start = next;
          else
@@ -595,50 +283,6 @@ squeeze_notes (startp, endp)
   return false;
 }
 \f
-/* Return the label before INSN, or put a new label there.  */
-
-rtx
-get_label_before (insn)
-     rtx insn;
-{
-  rtx label;
-
-  /* Find an existing label at this point
-     or make a new one if there is none.  */
-  label = prev_nonnote_insn (insn);
-
-  if (label == 0 || GET_CODE (label) != CODE_LABEL)
-    {
-      rtx prev = PREV_INSN (insn);
-
-      label = gen_label_rtx ();
-      emit_label_after (label, prev);
-      LABEL_NUSES (label) = 0;
-    }
-  return label;
-}
-
-/* Return the label after INSN, or put a new label there.  */
-
-rtx
-get_label_after (insn)
-     rtx insn;
-{
-  rtx label;
-
-  /* Find an existing label at this point
-     or make a new one if there is none.  */
-  label = next_nonnote_insn (insn);
-
-  if (label == 0 || GET_CODE (label) != CODE_LABEL)
-    {
-      label = gen_label_rtx ();
-      emit_label_after (label, insn);
-      LABEL_NUSES (label) = 0;
-    }
-  return label;
-}
-\f
 /* Given a comparison (CODE ARG0 ARG1), inside an insn, INSN, return a code
    of reversed comparison if it is possible to do so.  Otherwise return UNKNOWN.
    UNKNOWN may be returned in case we are having CC_MODE compare and we don't
@@ -646,24 +290,22 @@ 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
-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;
 
   /* If this is not actually a comparison, we can't reverse it.  */
-  if (GET_RTX_CLASS (code) != '<')
+  if (GET_RTX_CLASS (code) != RTX_COMPARE
+      && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
     return UNKNOWN;
 
   mode = GET_MODE (arg0);
   if (mode == VOIDmode)
     mode = GET_MODE (arg1);
 
-  /* First see if machine description supply us way to reverse the comparison.
-     Give it priority over everything else to allow machine description to do
-     tricks.  */
-#ifdef REVERSIBLE_CC_MODE
+  /* First see if machine description supplies us way to reverse the
+     comparison.  Give it priority over everything else to allow
+     machine description to do tricks.  */
   if (GET_MODE_CLASS (mode) == MODE_CC
       && REVERSIBLE_CC_MODE (mode))
     {
@@ -672,7 +314,6 @@ reversed_comparison_code_parts (code, arg0, arg1, insn)
 #endif
       return reverse_condition (code);
     }
-#endif
 
   /* Try a few special cases based on the comparison code.  */
   switch (code)
@@ -684,7 +325,7 @@ reversed_comparison_code_parts (code, arg0, arg1, insn)
     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
+        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:
@@ -704,11 +345,7 @@ reversed_comparison_code_parts (code, arg0, arg1, insn)
       break;
     }
 
-  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.
@@ -719,7 +356,7 @@ reversed_comparison_code_parts (code, arg0, arg1, insn)
        return UNKNOWN;
 
       for (prev = prev_nonnote_insn (insn);
-          prev != 0 && GET_CODE (prev) != CODE_LABEL;
+          prev != 0 && !LABEL_P (prev);
           prev = prev_nonnote_insn (prev))
        {
          rtx set = set_of (arg0, prev);
@@ -763,18 +400,31 @@ reversed_comparison_code_parts (code, arg0, arg1, insn)
   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
-reversed_comparison_code (comparison, insn)
-     rtx comparison, insn;
+reversed_comparison_code (rtx comparison, rtx insn)
 {
-  if (GET_RTX_CLASS (GET_CODE (comparison)) != '<')
+  if (!COMPARISON_P (comparison))
     return UNKNOWN;
   return reversed_comparison_code_parts (GET_CODE (comparison),
                                         XEXP (comparison, 0),
                                         XEXP (comparison, 1), insn);
 }
+
+/* Return comparison with reversed code of EXP.
+   Return NULL_RTX in case we fail to do the reversal.  */
+rtx
+reversed_comparison (rtx exp, enum machine_mode mode)
+{
+  enum rtx_code reversed_code = reversed_comparison_code (exp, NULL_RTX);
+  if (reversed_code == UNKNOWN)
+    return NULL_RTX;
+  else
+    return simplify_gen_relational (reversed_code, mode, VOIDmode,
+                                    XEXP (exp, 0), XEXP (exp, 1));
+}
+
 \f
 /* Given an rtx-code for a comparison, return the code for the negated
    comparison.  If no such code exists, return UNKNOWN.
@@ -785,8 +435,7 @@ reversed_comparison_code (comparison, insn)
    Use reversed_comparison_code instead.  */
 
 enum rtx_code
-reverse_condition (code)
-     enum rtx_code code;
+reverse_condition (enum rtx_code code)
 {
   switch (code)
     {
@@ -824,7 +473,7 @@ reverse_condition (code)
       return UNKNOWN;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -833,8 +482,7 @@ reverse_condition (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)
 {
   switch (code)
     {
@@ -868,7 +516,7 @@ reverse_condition_maybe_unordered (code)
       return LTGT;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -876,8 +524,7 @@ reverse_condition_maybe_unordered (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)
     {
@@ -915,7 +562,7 @@ swap_condition (code)
       return UNLE;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -924,8 +571,7 @@ swap_condition (code)
    CODE is returned.  */
 
 enum rtx_code
-unsigned_condition (code)
-     enum rtx_code code;
+unsigned_condition (enum rtx_code code)
 {
   switch (code)
     {
@@ -947,15 +593,14 @@ unsigned_condition (code)
       return LEU;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
 /* 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)
     {
@@ -977,16 +622,15 @@ signed_condition (code)
       return LE;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 \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
-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.
@@ -1067,10 +711,9 @@ comparison_dominates_p (code1, code2)
 /* 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
+  return (JUMP_P (insn)
          && GET_CODE (PATTERN (insn)) == SET
          && GET_CODE (SET_DEST (PATTERN (insn))) == PC
          && GET_CODE (SET_SRC (PATTERN (insn))) == LABEL_REF);
@@ -1079,12 +722,11 @@ simplejump_p (insn)
 /* 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
-condjump_p (insn)
-     rtx insn;
+condjump_p (rtx insn)
 {
   rtx x = PATTERN (insn);
 
@@ -1103,8 +745,6 @@ condjump_p (insn)
                || (GET_CODE (XEXP (x, 1)) == PC
                    && (GET_CODE (XEXP (x, 2)) == LABEL_REF
                        || GET_CODE (XEXP (x, 2)) == RETURN))));
-
-  return 0;
 }
 
 /* Return nonzero if INSN is a (possibly) conditional jump inside a
@@ -1114,8 +754,7 @@ condjump_p (insn)
    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)
 {
   rtx x = PATTERN (insn);
 
@@ -1146,11 +785,10 @@ condjump_in_parallel_p (insn)
 /* Return set of PC, otherwise NULL.  */
 
 rtx
-pc_set (insn)
-     rtx insn;
+pc_set (rtx insn)
 {
   rtx pat;
-  if (GET_CODE (insn) != JUMP_INSN)
+  if (!JUMP_P (insn))
     return NULL_RTX;
   pat = PATTERN (insn);
 
@@ -1168,14 +806,15 @@ pc_set (insn)
    possibly bundled inside a PARALLEL.  */
 
 int
-any_uncondjump_p (insn)
-     rtx insn;
+any_uncondjump_p (rtx insn)
 {
   rtx x = pc_set (insn);
   if (!x)
     return 0;
   if (GET_CODE (SET_SRC (x)) != LABEL_REF)
     return 0;
+  if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
+    return 0;
   return 1;
 }
 
@@ -1187,8 +826,7 @@ any_uncondjump_p (insn)
    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;
@@ -1208,8 +846,7 @@ any_condjump_p (insn)
 /* Return the label of a conditional jump.  */
 
 rtx
-condjump_label (insn)
-     rtx insn;
+condjump_label (rtx insn)
 {
   rtx x = pc_set (insn);
 
@@ -1230,9 +867,7 @@ condjump_label (insn)
 /* 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;
 
@@ -1241,10 +876,9 @@ returnjump_p_1 (loc, data)
 }
 
 int
-returnjump_p (insn)
-     rtx insn;
+returnjump_p (rtx insn)
 {
-  if (GET_CODE (insn) != JUMP_INSN)
+  if (!JUMP_P (insn))
     return 0;
   return for_each_rtx (&PATTERN (insn), returnjump_p_1, NULL);
 }
@@ -1253,12 +887,11 @@ returnjump_p (insn)
    nothing more.  */
 
 int
-onlyjump_p (insn)
-     rtx insn;
+onlyjump_p (rtx insn)
 {
   rtx set;
 
-  if (GET_CODE (insn) != JUMP_INSN)
+  if (!JUMP_P (insn))
     return 0;
 
   set = single_set (insn);
@@ -1274,14 +907,12 @@ onlyjump_p (insn)
 
 #ifdef HAVE_cc0
 
-/* Return non-zero if X is an RTX that only sets the condition codes
+/* Return nonzero if X is an RTX that only sets the condition codes
    and has no side effects.  */
 
 int
-only_sets_cc0_p (x)
-     rtx x;
+only_sets_cc0_p (rtx x)
 {
-
   if (! x)
     return 0;
 
@@ -1297,10 +928,8 @@ only_sets_cc0_p (x)
    but also does other things.  */
 
 int
-sets_cc0_p (x)
-     rtx x;
+sets_cc0_p (rtx x)
 {
-
   if (! x)
     return 0;
 
@@ -1328,66 +957,6 @@ sets_cc0_p (x)
 }
 #endif
 \f
-/* Follow any unconditional jump at LABEL;
-   return the ultimate label reached by any such chain of jumps.
-   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.
-
-   If RELOAD_COMPLETED is 0, we do not chain across a NOTE_INSN_LOOP_BEG or
-   a USE or CLOBBER.  */
-
-rtx
-follow_jumps (label)
-     rtx label;
-{
-  rtx insn;
-  rtx next;
-  rtx value = label;
-  int depth;
-
-  for (depth = 0;
-       (depth < 10
-       && (insn = next_active_insn (value)) != 0
-       && GET_CODE (insn) == JUMP_INSN
-       && ((JUMP_LABEL (insn) != 0 && any_uncondjump_p (insn)
-            && onlyjump_p (insn))
-           || GET_CODE (PATTERN (insn)) == RETURN)
-       && (next = NEXT_INSN (insn))
-       && GET_CODE (next) == BARRIER);
-       depth++)
-    {
-      /* Don't chain through the insn that jumps into a loop
-        from outside the loop,
-        since that would create multiple loop entry jumps
-        and prevent loop optimization.  */
-      rtx tem;
-      if (!reload_completed)
-       for (tem = value; tem != insn; tem = NEXT_INSN (tem))
-         if (GET_CODE (tem) == NOTE
-             && (NOTE_LINE_NUMBER (tem) == NOTE_INSN_LOOP_BEG
-                 /* ??? Optional.  Disables some optimizations, but makes
-                    gcov output more accurate with -O.  */
-                 || (flag_test_coverage && NOTE_LINE_NUMBER (tem) > 0)))
-           return value;
-
-      /* If we have found a cycle, make the insn jump to itself.  */
-      if (JUMP_LABEL (insn) == 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))
-       break;
-
-      value = JUMP_LABEL (insn);
-    }
-  if (depth == 10)
-    return label;
-  return value;
-}
-
-\f
 /* Find all CODE_LABELs referred to in X, and increment their use counts.
    If INSN is a JUMP_INSN and there is at least one CODE_LABEL referenced
    in INSN, then store one of them in JUMP_LABEL (INSN).
@@ -1402,10 +971,7 @@ follow_jumps (label)
    that loop-optimization is done with.  */
 
 void
-mark_jump_label (x, insn, in_mem)
-     rtx x;
-     rtx insn;
-     int in_mem;
+mark_jump_label (rtx x, rtx insn, int in_mem)
 {
   RTX_CODE code = GET_CODE (x);
   int i;
@@ -1416,7 +982,6 @@ mark_jump_label (x, insn, in_mem)
     case PC:
     case CC0:
     case REG:
-    case SUBREG:
     case CONST_INT:
     case CONST_DOUBLE:
     case CLOBBER:
@@ -1427,6 +992,12 @@ mark_jump_label (x, insn, in_mem)
       in_mem = 1;
       break;
 
+    case SEQUENCE:
+      for (i = 0; i < XVECLEN (x, 0); i++)
+       mark_jump_label (PATTERN (XVECEXP (x, 0, i)),
+                        XVECEXP (x, 0, i), 0);
+      return;
+
     case SYMBOL_REF:
       if (!in_mem)
        return;
@@ -1442,12 +1013,11 @@ mark_jump_label (x, insn, in_mem)
 
        /* Ignore remaining references to unreachable labels that
           have been deleted.  */
-       if (GET_CODE (label) == NOTE
+       if (NOTE_P (label)
            && NOTE_LINE_NUMBER (label) == NOTE_INSN_DELETED_LABEL)
          break;
 
-       if (GET_CODE (label) != CODE_LABEL)
-         abort ();
+       gcc_assert (LABEL_P (label));
 
        /* Ignore references to labels of containing functions.  */
        if (LABEL_REF_NONLOCAL_P (x))
@@ -1459,7 +1029,7 @@ mark_jump_label (x, insn, in_mem)
 
        if (insn)
          {
-           if (GET_CODE (insn) == JUMP_INSN)
+           if (JUMP_P (insn))
              JUMP_LABEL (insn) = label;
            else
              {
@@ -1506,220 +1076,19 @@ mark_jump_label (x, insn, in_mem)
     }
 }
 
-/* If all INSN does is set the pc, delete it,
-   and delete the insn that set the condition codes for it
-   if that's what the previous thing was.  */
-
-void
-delete_jump (insn)
-     rtx insn;
-{
-  rtx set = single_set (insn);
-
-  if (set && GET_CODE (SET_DEST (set)) == PC)
-    delete_computation (insn);
-}
-
-/* Verify INSN is a BARRIER and delete it.  */
-
-void
-delete_barrier (insn)
-     rtx insn;
-{
-  if (GET_CODE (insn) != BARRIER)
-    abort ();
-
-  delete_insn (insn);
-}
-
-/* Recursively delete prior insns that compute the value (used only by INSN
-   which the caller is deleting) stored in the register mentioned by NOTE
-   which is a REG_DEAD note associated with INSN.  */
-
-static void
-delete_prior_computation (note, insn)
-     rtx note;
-     rtx insn;
-{
-  rtx our_prev;
-  rtx reg = XEXP (note, 0);
-
-  for (our_prev = prev_nonnote_insn (insn);
-       our_prev && (GET_CODE (our_prev) == INSN
-                   || GET_CODE (our_prev) == CALL_INSN);
-       our_prev = prev_nonnote_insn (our_prev))
-    {
-      rtx pat = PATTERN (our_prev);
-
-      /* 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_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
-        do anything with it, so give up.  */
-      if (GET_CODE (pat) == SEQUENCE)
-       break;
-
-      if (GET_CODE (pat) == USE
-         && GET_CODE (XEXP (pat, 0)) == INSN)
-       /* reorg creates USEs that look like this.  We leave them
-          alone because reorg needs them for its own purposes.  */
-       break;
-
-      if (reg_set_p (reg, pat))
-       {
-         if (side_effects_p (pat) && GET_CODE (our_prev) != CALL_INSN)
-           break;
-
-         if (GET_CODE (pat) == PARALLEL)
-           {
-             /* If we find a SET of something else, we can't
-                delete the insn.  */
-
-             int i;
-
-             for (i = 0; i < XVECLEN (pat, 0); i++)
-               {
-                 rtx part = XVECEXP (pat, 0, i);
-
-                 if (GET_CODE (part) == SET
-                     && SET_DEST (part) != reg)
-                   break;
-               }
-
-             if (i == XVECLEN (pat, 0))
-               delete_computation (our_prev);
-           }
-         else if (GET_CODE (pat) == SET
-                  && GET_CODE (SET_DEST (pat)) == REG)
-           {
-             int dest_regno = REGNO (SET_DEST (pat));
-             int dest_endregno
-               = (dest_regno
-                  + (dest_regno < FIRST_PSEUDO_REGISTER
-                     ? HARD_REGNO_NREGS (dest_regno,
-                                         GET_MODE (SET_DEST (pat))) : 1));
-             int regno = REGNO (reg);
-             int endregno
-               = (regno
-                  + (regno < FIRST_PSEUDO_REGISTER
-                     ? HARD_REGNO_NREGS (regno, GET_MODE (reg)) : 1));
-
-             if (dest_regno >= regno
-                 && dest_endregno <= endregno)
-               delete_computation (our_prev);
-
-             /* We may have a multi-word hard register and some, but not
-                all, of the words of the register are needed in subsequent
-                insns.  Write REG_UNUSED notes for those parts that were not
-                needed.  */
-             else if (dest_regno <= regno
-                      && dest_endregno >= endregno)
-               {
-                 int i;
-
-                 REG_NOTES (our_prev)
-                   = gen_rtx_EXPR_LIST (REG_UNUSED, reg,
-                                        REG_NOTES (our_prev));
-
-                 for (i = dest_regno; i < dest_endregno; i++)
-                   if (! find_regno_note (our_prev, REG_UNUSED, i))
-                     break;
-
-                 if (i == dest_endregno)
-                   delete_computation (our_prev);
-               }
-           }
-
-         break;
-       }
-
-      /* If PAT references the register that dies here, it is an
-        additional use.  Hence any prior SET isn't dead.  However, this
-        insn becomes the new place for the REG_DEAD note.  */
-      if (reg_overlap_mentioned_p (reg, pat))
-       {
-         XEXP (note, 1) = REG_NOTES (our_prev);
-         REG_NOTES (our_prev) = note;
-         break;
-       }
-    }
-}
-
-/* Delete INSN and recursively delete insns that compute values used only
-   by INSN.  This uses the REG_DEAD notes computed during flow analysis.
-   If we are running before flow.c, we need do nothing since flow.c will
-   delete dead code.  We also can't know if the registers being used are
-   dead or not at this point.
-
-   Otherwise, look at all our REG_DEAD notes.  If a previous insn does
-   nothing other than set a register that dies in this insn, we can delete
-   that insn as well.
-
-   On machines with CC0, if CC0 is used in this insn, we may be able to
-   delete the insn that set it.  */
-
-static void
-delete_computation (insn)
-     rtx insn;
-{
-  rtx note, next;
-
-#ifdef HAVE_cc0
-  if (reg_referenced_p (cc0_rtx, PATTERN (insn)))
-    {
-      rtx prev = prev_nonnote_insn (insn);
-      /* We assume that at this stage
-        CC's are always set explicitly
-        and always immediately before the jump that
-        will use them.  So if the previous insn
-        exists to set the CC's, delete it
-        (unless it performs auto-increments, etc.).  */
-      if (prev && GET_CODE (prev) == INSN
-         && sets_cc0_p (PATTERN (prev)))
-       {
-         if (sets_cc0_p (PATTERN (prev)) > 0
-             && ! side_effects_p (PATTERN (prev)))
-           delete_computation (prev);
-         else
-           /* Otherwise, show that cc0 won't be used.  */
-           REG_NOTES (prev) = gen_rtx_EXPR_LIST (REG_UNUSED,
-                                                 cc0_rtx, REG_NOTES (prev));
-       }
-    }
-#endif
-
-  for (note = REG_NOTES (insn); note; note = next)
-    {
-      next = XEXP (note, 1);
-
-      if (REG_NOTE_KIND (note) != REG_DEAD
-         /* Verify that the REG_NOTE is legitimate.  */
-         || GET_CODE (XEXP (note, 0)) != REG)
-       continue;
-
-      delete_prior_computation (note, insn);
-    }
-
-  delete_related_insns (insn);
-}
 \f
 /* Delete insn INSN from the chain of insns and update label ref counts
-   and delete insns now unreachable. 
+   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
-delete_related_insns (insn)
-     rtx insn;
+delete_related_insns (rtx insn)
 {
-  int was_code_label = (GET_CODE (insn) == CODE_LABEL);
+  int was_code_label = (LABEL_P (insn));
   rtx note;
   rtx next = NEXT_INSN (insn), prev = PREV_INSN (insn);
 
@@ -1735,13 +1104,13 @@ delete_related_insns (insn)
   /* If instruction is followed by a barrier,
      delete the barrier too.  */
 
-  if (next != 0 && GET_CODE (next) == BARRIER)
+  if (next != 0 && BARRIER_P (next))
     delete_insn (next);
 
   /* If deleting a jump, decrement the count of the label,
      and delete the label if it is now unused.  */
 
-  if (GET_CODE (insn) == JUMP_INSN && JUMP_LABEL (insn))
+  if (JUMP_P (insn) && JUMP_LABEL (insn))
     {
       rtx lab = JUMP_LABEL (insn), lab_next;
 
@@ -1760,10 +1129,7 @@ delete_related_insns (insn)
            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.
             We may not be able to kill the label immediately preceding
@@ -1775,7 +1141,7 @@ delete_related_insns (insn)
 
   /* Likewise if we're deleting a dispatch table.  */
 
-  if (GET_CODE (insn) == JUMP_INSN
+  if (JUMP_P (insn)
       && (GET_CODE (PATTERN (insn)) == ADDR_VEC
          || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
     {
@@ -1792,15 +1158,15 @@ delete_related_insns (insn)
     }
 
   /* Likewise for an ordinary INSN / CALL_INSN with a REG_LABEL note.  */
-  if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
+  if (NONJUMP_INSN_P (insn) || CALL_P (insn))
     for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
       if (REG_NOTE_KIND (note) == REG_LABEL
          /* This could also be a NOTE_INSN_DELETED_LABEL note.  */
-         && GET_CODE (XEXP (note, 0)) == CODE_LABEL)
+         && LABEL_P (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))
+  while (prev && (INSN_DELETED_P (prev) || NOTE_P (prev)))
     prev = PREV_INSN (prev);
 
   /* If INSN was a label and a dispatch table follows it,
@@ -1809,50 +1175,37 @@ delete_related_insns (insn)
 
   if (was_code_label
       && NEXT_INSN (insn) != 0
-      && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
+      && JUMP_P (NEXT_INSN (insn))
       && (GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC
          || GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_DIFF_VEC))
     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 (was_code_label && prev && BARRIER_P (prev))
     {
-      RTX_CODE code;
-      while (next != 0
-            && (GET_RTX_CLASS (code = GET_CODE (next)) == 'i'
-                || code == NOTE || code == BARRIER
-                || (code == CODE_LABEL && INSN_DELETED_P (next))))
+      enum rtx_code code;
+      while (next)
        {
-         if (code == NOTE
-             && NOTE_LINE_NUMBER (next) != NOTE_INSN_FUNCTION_END)
+         code = GET_CODE (next);
+         if (code == NOTE)
            next = NEXT_INSN (next);
          /* Keep going past other deleted labels to delete what follows.  */
          else if (code == CODE_LABEL && INSN_DELETED_P (next))
            next = NEXT_INSN (next);
-         else
+         else if (code == BARRIER || INSN_P (next))
            /* Note: if this deletes a jump, it can cause more
               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_related_insns (next);
+         else
+           break;
        }
     }
 
   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
@@ -1860,8 +1213,7 @@ next_nondeleted_insn (insn)
    peephole insn that will replace them.  */
 
 void
-delete_for_peephole (from, to)
-     rtx from, to;
+delete_for_peephole (rtx from, rtx to)
 {
   rtx insn = from;
 
@@ -1870,7 +1222,7 @@ delete_for_peephole (from, to)
       rtx next = NEXT_INSN (insn);
       rtx prev = PREV_INSN (insn);
 
-      if (GET_CODE (insn) != NOTE)
+      if (!NOTE_P (insn))
        {
          INSN_DELETED_P (insn) = 1;
 
@@ -1895,67 +1247,11 @@ delete_for_peephole (from, to)
      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.
-
-   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.  */
-
-void
-never_reached_warning (avoided_insn, finish)
-     rtx avoided_insn, finish;
-{
-  rtx insn;
-  rtx a_line_note = NULL;
-  int two_avoided_lines = 0, contains_insn = 0, reached_end = 0;
-
-  if (! warn_notreached)
-    return;
-
-  /* Scan forwards, looking at LINE_NUMBER notes, until
-     we hit a LABEL or we run out of insns.  */
-
-  for (insn = avoided_insn; insn != NULL; insn = NEXT_INSN (insn))
-    {
-      if (finish == NULL && GET_CODE (insn) == CODE_LABEL)
-       break;
-
-      if (GET_CODE (insn) == NOTE              /* A line number note?  */
-         && NOTE_LINE_NUMBER (insn) >= 0)
-       {
-         if (a_line_note == NULL)
-           a_line_note = insn;
-         else
-           two_avoided_lines |= (NOTE_LINE_NUMBER (a_line_note)
-                                 != NOTE_LINE_NUMBER (insn));
-       }
-      else if (INSN_P (insn))
-       {
-         if (reached_end)
-           break;
-         contains_insn = 1;
-       }
-
-      if (insn == finish)
-       reached_end = 1;
-    }
-  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");
-}
-\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)
 {
   rtx x = *loc;
   RTX_CODE code = GET_CODE (x);
@@ -1968,7 +1264,7 @@ redirect_exp_1 (loc, olabel, nlabel, insn)
        {
          rtx n;
          if (nlabel)
-           n = gen_rtx_LABEL_REF (VOIDmode, nlabel);
+           n = gen_rtx_LABEL_REF (Pmode, nlabel);
          else
            n = gen_rtx_RETURN (VOIDmode);
 
@@ -1978,7 +1274,10 @@ redirect_exp_1 (loc, olabel, nlabel, insn)
     }
   else if (code == RETURN && olabel == 0)
     {
-      x = gen_rtx_LABEL_REF (VOIDmode, nlabel);
+      if (nlabel)
+       x = gen_rtx_LABEL_REF (Pmode, nlabel);
+      else
+       x = gen_rtx_RETURN (VOIDmode);
       if (loc == &PATTERN (insn))
        x = gen_rtx_SET (VOIDmode, pc_rtx, x);
       validate_change (insn, loc, x, 1);
@@ -2007,34 +1306,12 @@ redirect_exp_1 (loc, olabel, nlabel, insn)
     }
 }
 
-/* Similar, but apply the change group and report success or failure.  */
-
-static int
-redirect_exp (olabel, nlabel, insn)
-     rtx olabel, nlabel;
-     rtx insn;
-{
-  rtx *loc;
-
-  if (GET_CODE (PATTERN (insn)) == PARALLEL)
-    loc = &XVECEXP (PATTERN (insn), 0, 0);
-  else
-    loc = &PATTERN (insn);
-
-  redirect_exp_1 (loc, olabel, nlabel, insn);
-  if (num_validated_changes () == 0)
-    return 0;
-
-  return apply_change_group ();
-}
-
 /* Make JUMP go to NLABEL instead of where it jumps now.  Accrue
    the modifications into the change group.  Return false if we did
    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;
@@ -2059,53 +1336,64 @@ redirect_jump_1 (jump, nlabel)
    (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)
 {
   rtx olabel = JUMP_LABEL (jump);
 
   if (nlabel == olabel)
     return 1;
 
-  if (! redirect_exp (olabel, nlabel, jump))
+  if (! redirect_jump_1 (jump, nlabel) || ! apply_change_group ())
     return 0;
 
+  redirect_jump_2 (jump, olabel, nlabel, delete_unused, 0);
+  return 1;
+}
+
+/* Fix up JUMP_LABEL and label ref counts after OLABEL has been replaced with
+   NLABEL in JUMP.  
+   If DELETE_UNUSED is positive, delete related insn to OLABEL if its ref
+   count has dropped to zero.  */
+void
+redirect_jump_2 (rtx jump, rtx olabel, rtx nlabel, int delete_unused,
+                int invert)
+{
+  rtx note;
+
+  /* Negative DELETE_UNUSED used to be used to signalize behavior on
+     moving FUNCTION_END note.  Just sanity check that no user still worry
+     about this.  */
+  gcc_assert (delete_unused >= 0);
   JUMP_LABEL (jump) = nlabel;
   if (nlabel)
     ++LABEL_NUSES (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
-      && NEXT_INSN (olabel)
-      && GET_CODE (NEXT_INSN (olabel)) == NOTE
-      && NOTE_LINE_NUMBER (NEXT_INSN (olabel)) == NOTE_INSN_FUNCTION_END)
-    emit_note_after (NOTE_INSN_FUNCTION_END, 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)))
+       remove_note (jump, note);
+      else
+       {
+         redirect_exp_1 (&XEXP (note, 0), olabel, nlabel, jump);
+         confirm_change_group ();
+       }
+    }
 
-  if (olabel && --LABEL_NUSES (olabel) == 0 && delete_unused
+  if (olabel && --LABEL_NUSES (olabel) == 0 && delete_unused > 0
       /* Undefined labels will remain outside the insn stream.  */
       && INSN_UID (olabel))
     delete_related_insns (olabel);
-
-  return 1;
+  if (invert)
+    invert_br_probabilities (jump);
 }
 
-/* Invert the jump condition of rtx X contained in jump insn, INSN.
-   Accrue the modifications into the change group.  */
-
-static void
-invert_exp_1 (insn)
-     rtx insn;
+/* Invert the jump condition X contained in jump insn INSN.  Accrue the
+   modifications into the change group.  Return nonzero for success.  */
+static int
+invert_exp_1 (rtx x, rtx insn)
 {
-  RTX_CODE code;
-  rtx x = pc_set (insn);
-
-  if (!x)
-    abort ();
-  x = SET_SRC (x);
-
-  code = GET_CODE (x);
+  RTX_CODE code = GET_CODE (x);
 
   if (code == IF_THEN_ELSE)
     {
@@ -2127,31 +1415,16 @@ invert_exp_1 (insn)
                                           GET_MODE (comp), XEXP (comp, 0),
                                           XEXP (comp, 1)),
                           1);
-         return;
+         return 1;
        }
 
       tem = XEXP (x, 1);
       validate_change (insn, &XEXP (x, 1), XEXP (x, 2), 1);
       validate_change (insn, &XEXP (x, 2), tem, 1);
+      return 1;
     }
   else
-    abort ();
-}
-
-/* Invert the jump condition of conditional jump insn, INSN.
-
-   Return 1 if we can do so, 0 if we cannot find a way to do so that
-   matches a pattern.  */
-
-static int
-invert_exp (insn)
-     rtx insn;
-{
-  invert_exp_1 (insn);
-  if (num_validated_changes () == 0)
     return 0;
-
-  return apply_change_group ();
 }
 
 /* Invert the condition of the jump JUMP, and make it jump to label
@@ -2160,46 +1433,39 @@ invert_exp (insn)
    inversion and redirection.  */
 
 int
-invert_jump_1 (jump, nlabel)
-     rtx jump, nlabel;
+invert_jump_1 (rtx jump, rtx nlabel)
 {
+  rtx x = pc_set (jump);
   int ochanges;
+  int ok;
 
   ochanges = num_validated_changes ();
-  invert_exp_1 (jump);
+  gcc_assert (x);
+  ok = invert_exp_1 (SET_SRC (x), jump);
+  gcc_assert (ok);
+  
   if (num_validated_changes () == ochanges)
     return 0;
 
-  return redirect_jump_1 (jump, nlabel);
+  /* redirect_jump_1 will fail of nlabel == olabel, and the current use is
+     in Pmode, so checking this is not merely an optimization.  */
+  return nlabel == JUMP_LABEL (jump) || redirect_jump_1 (jump, nlabel);
 }
 
 /* Invert the condition of the jump JUMP, and make it jump to label
    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
-     the jump. If that succeeds, we try changing the label.  If that fails,
-     we invert the jump back to what it was.  */
-
-  if (! invert_exp (jump))
-    return 0;
+  rtx olabel = JUMP_LABEL (jump);
 
-  if (redirect_jump (jump, nlabel, delete_unused))
+  if (invert_jump_1 (jump, nlabel) && apply_change_group ())
     {
-      invert_br_probabilities (jump);
-
+      redirect_jump_2 (jump, olabel, nlabel, delete_unused, 1);
       return 1;
     }
-
-  if (! invert_exp (jump))
-    /* This should just be putting it back the way it was.  */
-    abort ();
-
+  cancel_changes (0);
   return 0;
 }
 
@@ -2207,30 +1473,21 @@ invert_jump (jump, nlabel, delete_unused)
 /* Like rtx_equal_p except that it considers two REGs as equal
    if they renumber to the same value and considers two commutative
    operations to be the same if the order of the operands has been
-   reversed.
-
-   ??? Addition is not commutative on the PA due to the weird implicit
-   space register selection rules for memory addresses.  Therefore, we
-   don't consider a + b == b + a.
-
-   We could/should make this test a little tighter.  Possibly only
-   disabling it on the PA via some backend macro or only disabling this
-   case when the PLUS is inside a MEM.  */
+   reversed.  */
 
 int
-rtx_renumbered_equal_p (x, y)
-     rtx x, y;
+rtx_renumbered_equal_p (rtx x, rtx y)
 {
   int i;
-  RTX_CODE code = GET_CODE (x);
+  enum rtx_code code = GET_CODE (x);
   const char *fmt;
 
   if (x == y)
     return 1;
 
-  if ((code == REG || (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG))
-      && (GET_CODE (y) == REG || (GET_CODE (y) == SUBREG
-                                 && GET_CODE (SUBREG_REG (y)) == REG)))
+  if ((code == REG || (code == SUBREG && REG_P (SUBREG_REG (x))))
+      && (REG_P (y) || (GET_CODE (y) == SUBREG
+                                 && REG_P (SUBREG_REG (y)))))
     {
       int reg_x = -1, reg_y = -1;
       int byte_x = 0, byte_y = 0;
@@ -2299,10 +1556,9 @@ rtx_renumbered_equal_p (x, y)
     case CC0:
     case ADDR_VEC:
     case ADDR_DIFF_VEC:
-      return 0;
-
     case CONST_INT:
-      return INTVAL (x) == INTVAL (y);
+    case CONST_DOUBLE:
+      return 0;
 
     case LABEL_REF:
       /* We can't assume nonlocal labels have their following insns yet.  */
@@ -2331,19 +1587,16 @@ rtx_renumbered_equal_p (x, y)
     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.
-
-     ??? Don't consider PLUS a commutative operator; see comments above.  */
-  if ((code == EQ || code == NE || GET_RTX_CLASS (code) == 'c')
-      && code != PLUS)
+     order.  Also handle the simple binary and unary cases without a loop.  */
+  if (targetm.commutative_p (x, UNKNOWN))
     return ((rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0))
             && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 1)))
            || (rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 1))
                && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 0))));
-  else if (GET_RTX_CLASS (code) == '<' || GET_RTX_CLASS (code) == '2')
+  else if (NON_COMMUTATIVE_P (x))
     return (rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0))
            && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 1)));
-  else if (GET_RTX_CLASS (code) == '1')
+  else if (UNARY_P (x))
     return rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0));
 
   /* Compare the elements.  If any pair of corresponding elements
@@ -2383,7 +1636,7 @@ rtx_renumbered_equal_p (x, y)
        case 'u':
          if (XEXP (x, i) != XEXP (y, i))
            return 0;
-         /* fall through.  */
+         /* Fall through.  */
        case '0':
          break;
 
@@ -2396,7 +1649,7 @@ rtx_renumbered_equal_p (x, y)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
   return 1;
@@ -2408,10 +1661,9 @@ rtx_renumbered_equal_p (x, y)
    return -1.  Any rtx is valid for X.  */
 
 int
-true_regnum (x)
-     rtx x;
+true_regnum (rtx x)
 {
-  if (GET_CODE (x) == REG)
+  if (REG_P (x))
     {
       if (REGNO (x) >= FIRST_PSEUDO_REGISTER && reg_renumber[REGNO (x)] >= 0)
        return reg_renumber[REGNO (x)];
@@ -2420,10 +1672,24 @@ true_regnum (x)
   if (GET_CODE (x) == SUBREG)
     {
       int base = true_regnum (SUBREG_REG (x));
-      if (base >= 0 && base < FIRST_PSEUDO_REGISTER)
+      if (base >= 0
+         && base < FIRST_PSEUDO_REGISTER
+         && subreg_offset_representable_p (REGNO (SUBREG_REG (x)),
+                                           GET_MODE (SUBREG_REG (x)),
+                                           SUBREG_BYTE (x), GET_MODE (x)))
        return base + subreg_regno_offset (REGNO (SUBREG_REG (x)),
                                           GET_MODE (SUBREG_REG (x)),
                                           SUBREG_BYTE (x), GET_MODE (x));
     }
   return -1;
 }
+
+/* Return regno of the register REG and handle subregs too.  */
+unsigned int
+reg_or_subregno (rtx reg)
+{
+  if (GET_CODE (reg) == SUBREG)
+    reg = SUBREG_REG (reg);
+  gcc_assert (REG_P (reg));
+  return REGNO (reg);
+}