alias.c [...] (init_alias_analysis, [...]): Use memset () instead of bzero ().
[gcc.git] / gcc / jump.c
index baffdf03b7bbe6184d6f838e51bc9183f7489490..4c9c5ea2faed1eace6fd16ede1cd38825c6ecb58 100644 (file)
@@ -19,7 +19,6 @@ 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.  */
 
-
 /* This is the jump-optimization pass of the compiler.
    It is run two or three times: once before cse, sometimes once after cse,
    and once after reload (before final).
@@ -96,10 +95,6 @@ static rtx *jump_chain;
 
 static int max_jump_chain;
 
-/* Set nonzero by jump_optimize if control can fall through
-   to the end of the function.  */
-int can_reach_end;
-
 /* Indicates whether death notes are significant in cross jump analysis.
    Normally they are not significant, because of A and B jump to C,
    and R dies in A, it must die in B.  But this might not be true after
@@ -113,7 +108,6 @@ static void delete_barrier_successors       PARAMS ((rtx));
 static void mark_all_labels            PARAMS ((rtx, int));
 static rtx delete_unreferenced_labels  PARAMS ((rtx));
 static void delete_noop_moves          PARAMS ((rtx));
-static int calculate_can_reach_end     PARAMS ((rtx, int));
 static int duplicate_loop_exit_test    PARAMS ((rtx));
 static void find_cross_jump            PARAMS ((rtx, rtx, int, rtx *, rtx *));
 static void do_cross_jump              PARAMS ((rtx, rtx, rtx));
@@ -122,7 +116,9 @@ static int tension_vector_labels    PARAMS ((rtx, int));
 static void mark_jump_label            PARAMS ((rtx, rtx, int, int));
 static void delete_computation         PARAMS ((rtx));
 static void redirect_exp_1             PARAMS ((rtx *, rtx, rtx, rtx));
-static void invert_exp_1               PARAMS ((rtx, rtx));
+static int redirect_exp                        PARAMS ((rtx, rtx, rtx));
+static void invert_exp_1               PARAMS ((rtx));
+static int invert_exp                  PARAMS ((rtx));
 static void delete_from_jump_chain     PARAMS ((rtx));
 static int delete_labelref_insn                PARAMS ((rtx, rtx, int));
 static void mark_modified_reg          PARAMS ((rtx, rtx, void *));
@@ -154,6 +150,7 @@ rebuild_jump_labels (f)
 }
 
 /* Alternate entry into the jump optimizer.  Do only trivial optimizations.  */
+
 void
 jump_optimize_minimal (f)
      rtx f;
@@ -231,11 +228,13 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
 
   mark_all_labels (f, cross_jump);
 
-  /* Keep track of labels used from static data;
-     they cannot ever be deleted.  */
+  /* Keep track of labels used from static data; we don't track them
+     closely enough to delete them here, so make sure their reference
+     count doesn't drop to zero.  */
 
   for (insn = forced_labels; insn; insn = XEXP (insn, 1))
-    LABEL_NUSES (XEXP (insn, 0))++;
+    if (GET_CODE (XEXP (insn, 0)) == CODE_LABEL)
+      LABEL_NUSES (XEXP (insn, 0))++;
 
   check_exception_handler_labels ();
 
@@ -243,7 +242,8 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
      regions; they cannot usually be deleted.  */
 
   for (insn = exception_handler_labels; insn; insn = XEXP (insn, 1))
-    LABEL_NUSES (XEXP (insn, 0))++;
+    if (GET_CODE (XEXP (insn, 0)) == CODE_LABEL)
+      LABEL_NUSES (XEXP (insn, 0))++;
 
   /* Quit now if we just wanted to rebuild the JUMP_LABEL and REG_LABEL
      notes and recompute LABEL_NUSES.  */
@@ -275,7 +275,7 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
            && REGNO_FIRST_UID (REGNO (SET_DEST (set))) == INSN_UID (insn)
            /* We use regno_last_note_uid so as not to delete the setting
               of a reg that's used in notes.  A subsequent optimization
-              might arrange to use that reg for real.  */             
+              might arrange to use that reg for real.  */
            && REGNO_LAST_NOTE_UID (REGNO (SET_DEST (set))) == INSN_UID (insn)
            && ! side_effects_p (SET_SRC (set))
            && ! find_reg_note (insn, REG_RETVAL, 0)
@@ -300,8 +300,9 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
          rtx temp, temp1, temp2 = NULL_RTX;
          rtx temp4 ATTRIBUTE_UNUSED;
          rtx nlabel;
-         int this_is_simplejump, this_is_condjump;
-         int this_is_condjump_in_parallel;
+         int this_is_any_uncondjump;
+         int this_is_any_condjump;
+         int this_is_onlyjump;
 
          next = NEXT_INSN (insn);
 
@@ -312,7 +313,8 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
          if (after_regscan && GET_CODE (insn) == NOTE
              && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
              && (temp1 = next_nonnote_insn (insn)) != 0
-             && simplejump_p (temp1))
+             && any_uncondjump_p (temp1)
+             && onlyjump_p (temp1))
            {
              temp = PREV_INSN (insn);
              if (duplicate_loop_exit_test (insn))
@@ -326,9 +328,9 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
          if (GET_CODE (insn) != JUMP_INSN)
            continue;
 
-         this_is_simplejump = simplejump_p (insn);
-         this_is_condjump = condjump_p (insn);
-         this_is_condjump_in_parallel = condjump_in_parallel_p (insn);
+         this_is_any_condjump = any_condjump_p (insn);
+         this_is_any_uncondjump = any_uncondjump_p (insn);
+         this_is_onlyjump = onlyjump_p (insn);
 
          /* Tension the labels in dispatch tables.  */
 
@@ -340,7 +342,7 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
          /* See if this jump goes to another jump and redirect if so.  */
          nlabel = follow_jumps (JUMP_LABEL (insn));
          if (nlabel != JUMP_LABEL (insn))
-           changed |= redirect_jump (insn, nlabel);
+           changed |= redirect_jump (insn, nlabel, 1);
 
          if (! optimize || minimal)
            continue;
@@ -367,7 +369,7 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
                  && dispatch != 0
                  && GET_CODE (dispatch) == JUMP_INSN
                  && JUMP_LABEL (dispatch) != 0
-                 /* Don't mess with a casesi insn. 
+                 /* Don't mess with a casesi insn.
                     XXX according to the comment before computed_jump_p(),
                     all casesi insns should be a parallel of the jump
                     and a USE of a LABEL_REF.  */
@@ -381,28 +383,29 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
                }
            }
 
-         /* If a jump references the end of the function, try to turn
-            it into a RETURN insn, possibly a conditional one.  */
-         if (JUMP_LABEL (insn) != 0
-             && (next_active_insn (JUMP_LABEL (insn)) == 0
-                 || GET_CODE (PATTERN (next_active_insn (JUMP_LABEL (insn))))
-                     == RETURN))
-           changed |= redirect_jump (insn, NULL_RTX);
-
          reallabelprev = prev_active_insn (JUMP_LABEL (insn));
 
          /* Detect jump to following insn.  */
-         if (reallabelprev == insn && this_is_condjump)
+         if (reallabelprev == insn
+             && (this_is_any_condjump || this_is_any_uncondjump)
+             && this_is_onlyjump)
            {
              next = next_real_insn (JUMP_LABEL (insn));
              delete_jump (insn);
+
+             /* Remove the "inactive" but "real" insns (i.e. uses and
+                clobbers) in between here and there.  */
+             temp = insn;
+             while ((temp = next_real_insn (temp)) != next)
+               delete_insn (temp);
+
              changed = 1;
              continue;
            }
 
          /* Detect a conditional jump going to the same place
             as an immediately following unconditional jump.  */
-         else if (this_is_condjump
+         else if (this_is_any_condjump && this_is_onlyjump
                   && (temp = next_active_insn (insn)) != 0
                   && simplejump_p (temp)
                   && (next_active_insn (JUMP_LABEL (insn))
@@ -414,7 +417,7 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
                for (temp2 = insn; temp2 != temp; temp2 = NEXT_INSN (temp2))
                  if (GET_CODE (temp2) == NOTE && NOTE_LINE_NUMBER (temp2) > 0)
                    break;
-                 
+
              if (temp2 == temp)
                {
                  delete_jump (insn);
@@ -425,13 +428,13 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
 
          /* Detect a conditional jump jumping over an unconditional jump.  */
 
-         else if ((this_is_condjump || this_is_condjump_in_parallel)
-                  && ! this_is_simplejump
+         else if (this_is_any_condjump
                   && reallabelprev != 0
                   && GET_CODE (reallabelprev) == JUMP_INSN
                   && prev_active_insn (reallabelprev) == insn
                   && no_labels_between_p (insn, reallabelprev)
-                  && simplejump_p (reallabelprev))
+                  && any_uncondjump_p (reallabelprev)
+                  && onlyjump_p (reallabelprev))
            {
              /* When we invert the unconditional jump, we will be
                 decrementing the usage count of its old label.
@@ -443,7 +446,7 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
              if (prev_label)
                ++LABEL_NUSES (prev_label);
 
-             if (invert_jump (insn, JUMP_LABEL (reallabelprev)))
+             if (invert_jump (insn, JUMP_LABEL (reallabelprev), 1))
                {
                  /* It is very likely that if there are USE insns before
                     this jump, they hold REG_DEAD notes.  These REG_DEAD
@@ -482,7 +485,7 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
             being branch to already has the identical USE or if code
             never falls through to that label.  */
 
-         else if (this_is_simplejump
+         else if (this_is_any_uncondjump
                   && (temp = prev_nonnote_insn (insn)) != 0
                   && GET_CODE (temp) == INSN
                   && GET_CODE (PATTERN (temp)) == USE
@@ -506,7 +509,7 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
                }
 
              delete_insn (temp);
-             redirect_jump (insn, get_label_before (temp1));
+             redirect_jump (insn, get_label_before (temp1), 1);
              reallabelprev = prev_real_insn (temp1);
              changed = 1;
              next = NEXT_INSN (insn);
@@ -515,7 +518,7 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
 #ifdef HAVE_trap
          /* Detect a conditional jump jumping over an unconditional trap.  */
          if (HAVE_trap
-             && this_is_condjump && ! this_is_simplejump
+             && this_is_any_condjump && this_is_onlyjump
              && reallabelprev != 0
              && GET_CODE (reallabelprev) == INSN
              && GET_CODE (PATTERN (reallabelprev)) == TRAP_IF
@@ -539,21 +542,22 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
                }
            }
          /* Detect a jump jumping to an unconditional trap.  */
-         else if (HAVE_trap && this_is_condjump
+         else if (HAVE_trap && this_is_onlyjump
                   && (temp = next_active_insn (JUMP_LABEL (insn)))
                   && GET_CODE (temp) == INSN
                   && GET_CODE (PATTERN (temp)) == TRAP_IF
-                  && (this_is_simplejump
-                      || (temp2 = get_condition (insn, &temp4))))
+                  && (this_is_any_uncondjump
+                      || (this_is_any_condjump
+                          && (temp2 = get_condition (insn, &temp4)))))
            {
              rtx tc = TRAP_CONDITION (PATTERN (temp));
 
              if (tc == const_true_rtx
-                 || (! this_is_simplejump && rtx_equal_p (temp2, tc)))
+                 || (! this_is_any_uncondjump && rtx_equal_p (temp2, tc)))
                {
                  rtx new;
                  /* Replace an unconditional jump to a trap with a trap.  */
-                 if (this_is_simplejump)
+                 if (this_is_any_uncondjump)
                    {
                      emit_barrier_after (emit_insn_before (gen_trap (), insn));
                      delete_jump (insn);
@@ -574,11 +578,11 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
              /* If the trap condition and jump condition are mutually
                 exclusive, redirect the jump to the following insn.  */
              else if (GET_RTX_CLASS (GET_CODE (tc)) == '<'
-                      && ! this_is_simplejump
+                      && this_is_any_condjump
                       && swap_condition (GET_CODE (temp2)) == GET_CODE (tc)
                       && rtx_equal_p (XEXP (tc, 0), XEXP (temp2, 0))
                       && rtx_equal_p (XEXP (tc, 1), XEXP (temp2, 1))
-                      && redirect_jump (insn, get_label_after (temp)))
+                      && redirect_jump (insn, get_label_after (temp), 1))
                {
                  changed = 1;
                  continue;
@@ -734,13 +738,6 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
        }
   }
 
-  /* CAN_REACH_END is persistent for each function.  Once set it should
-     not be cleared.  This is especially true for the case where we
-     delete the NOTE_FUNCTION_END note.  CAN_REACH_END is cleared by
-     the front-end before compiling each function.  */
-  if (! minimal && calculate_can_reach_end (last_insn, optimize != 0))
-    can_reach_end = 1;
-
 end:
   /* Clean up.  */
   free (jump_chain);
@@ -782,7 +779,7 @@ init_label_info (f)
   return largest_uid;
 }
 
-/* Delete insns following barriers, up to next label. 
+/* Delete insns following barriers, up to next label.
 
    Also delete no-op jumps created by gcse.  */
 
@@ -791,6 +788,7 @@ delete_barrier_successors (f)
      rtx f;
 {
   rtx insn;
+  rtx set;
 
   for (insn = f; insn;)
     {
@@ -815,9 +813,10 @@ delete_barrier_successors (f)
         gcse.  We eliminate such insns now to avoid having them
         cause problems later.  */
       else if (GET_CODE (insn) == JUMP_INSN
-              && GET_CODE (PATTERN (insn)) == SET
-              && SET_SRC (PATTERN (insn)) == pc_rtx
-              && SET_DEST (PATTERN (insn)) == pc_rtx)
+              && (set = pc_set (insn)) != NULL
+              && SET_SRC (set) == pc_rtx
+              && SET_DEST (set) == pc_rtx
+              && onlyjump_p (insn))
        insn = delete_insn (insn);
 
       else
@@ -844,7 +843,7 @@ mark_all_labels (f, cross_jump)
   rtx insn;
 
   for (insn = f; insn; insn = NEXT_INSN (insn))
-    if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+    if (INSN_P (insn))
       {
        if (GET_CODE (insn) == CALL_INSN
            && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
@@ -854,7 +853,7 @@ mark_all_labels (f, cross_jump)
            mark_all_labels (XEXP (PATTERN (insn), 2), cross_jump);
            continue;
          }
-       
+
        mark_jump_label (PATTERN (insn), insn, cross_jump, 0);
        if (! INSN_DELETED_P (insn) && GET_CODE (insn) == JUMP_INSN)
          {
@@ -883,11 +882,11 @@ delete_unreferenced_labels (f)
   rtx final = NULL_RTX;
   rtx insn;
 
-  for (insn = f; insn; )
+  for (insn = f; insn;)
     {
       if (GET_CODE (insn) == CODE_LABEL
-          && LABEL_NUSES (insn) == 0
-          && LABEL_ALTERNATE_NAME (insn) == NULL)
+         && LABEL_NUSES (insn) == 0
+         && LABEL_ALTERNATE_NAME (insn) == NULL)
        insn = delete_insn (insn);
       else
        {
@@ -908,7 +907,7 @@ delete_noop_moves (f)
 {
   rtx insn, next;
 
-  for (insn = f; insn; )
+  for (insn = f; insn;)
     {
       next = NEXT_INSN (insn);
 
@@ -1032,7 +1031,7 @@ delete_noop_moves (f)
                      || dreg != sreg)
                    break;
                }
-                 
+
              if (i < 0)
                delete_insn (insn);
            }
@@ -1051,66 +1050,6 @@ delete_noop_moves (f)
     }
 }
 
-/* See if there is still a NOTE_INSN_FUNCTION_END in this function.
-   If so indicate that this function can drop off the end by returning
-   1, else return 0.
-
-   CHECK_DELETED indicates whether we must check if the note being
-   searched for has the deleted flag set.
-
-   DELETE_FINAL_NOTE indicates whether we should delete the note
-   if we find it.  */
-
-static int
-calculate_can_reach_end (last, delete_final_note)
-     rtx last;
-     int delete_final_note;
-{
-  rtx insn = last;
-  int n_labels = 1;
-
-  while (insn != NULL_RTX)
-    {
-      int ok = 0;
-
-      /* One label can follow the end-note: the return label.  */
-      if (GET_CODE (insn) == CODE_LABEL && n_labels-- > 0)
-       ok = 1;
-      /* Ordinary insns can follow it if returning a structure.  */
-      else if (GET_CODE (insn) == INSN)
-       ok = 1;
-      /* If machine uses explicit RETURN insns, no epilogue,
-        then one of them follows the note.  */
-      else if (GET_CODE (insn) == JUMP_INSN
-              && GET_CODE (PATTERN (insn)) == RETURN)
-       ok = 1;
-      /* A barrier can follow the return insn.  */
-      else if (GET_CODE (insn) == BARRIER)
-       ok = 1;
-      /* Other kinds of notes can follow also.  */
-      else if (GET_CODE (insn) == NOTE
-              && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END)
-       ok = 1;
-
-      if (ok != 1)
-       break;
-
-      insn = PREV_INSN (insn);
-    }
-
-  /* See if we backed up to the appropriate type of note.  */
-  if (insn != NULL_RTX
-      && GET_CODE (insn) == NOTE
-      && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_END)
-    {
-      if (delete_final_note)
-       delete_insn (insn);
-      return 1;
-    }
-
-  return 0;
-}
-
 /* 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,
@@ -1250,28 +1189,38 @@ duplicate_loop_exit_test (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, 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)
-             REG_NOTES (copy)
-               = copy_insn_1 (gen_rtx_EXPR_LIST (REG_NOTE_KIND (link),
-                                              XEXP (link, 0),
-                                              REG_NOTES (copy)));
+             {
+               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)));
+             }
+
          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);
+         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, 0);
@@ -1281,9 +1230,9 @@ duplicate_loop_exit_test (loop_start)
              if (reg_map)
                replace_regs (REG_NOTES (copy), reg_map, max_reg, 1);
            }
-         
+
          /* If this is a simple jump, add it to the jump chain.  */
-         
+
          if (INSN_UID (copy) < max_jump_chain && JUMP_LABEL (copy)
              && simplejump_p (copy))
            {
@@ -1292,7 +1241,7 @@ duplicate_loop_exit_test (loop_start)
              jump_chain[INSN_UID (JUMP_LABEL (copy))] = copy;
            }
          break;
-         
+
        default:
          abort ();
        }
@@ -1337,7 +1286,7 @@ duplicate_loop_exit_test (loop_start)
   emit_note_before (NOTE_INSN_LOOP_VTOP, exitcode);
 
   delete_insn (next_nonnote_insn (loop_start));
-  
+
   /* Clean up.  */
   if (reg_map)
     free (reg_map);
@@ -1345,8 +1294,8 @@ duplicate_loop_exit_test (loop_start)
   return 1;
 }
 \f
-/* Move all block-beg, block-end, loop-beg, loop-cont, loop-vtop, and
-   loop-end notes between START and END out before START.  Assume that
+/* Move all block-beg, block-end, loop-beg, loop-cont, loop-vtop, loop-end,
+   eh-beg, eh-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.  */
@@ -1367,7 +1316,9 @@ squeeze_notes (start, end)
              || 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_LOOP_VTOP
+             || NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
+             || NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END))
        {
          if (insn == start)
            start = next;
@@ -1455,7 +1406,7 @@ find_cross_jump (e1, e2, minimum, f1, f2)
 
       p1 = PATTERN (i1);
       p2 = PATTERN (i2);
-       
+
       /* If this is a CALL_INSN, compare register usage information.
         If we don't check this on stack register machines, the two
         CALL_INSNs might be merged leaving reg-stack.c with mismatching
@@ -1613,7 +1564,7 @@ do_cross_jump (insn, newjpos, newlpos)
        }
     }
   else
-    redirect_jump (insn, label);
+    redirect_jump (insn, label, 1);
 
   /* Delete the matching insns before the jump.  Also, remove any REG_EQUAL
      or REG_EQUIV note in the NEWLPOS stream that isn't also present in
@@ -1690,26 +1641,29 @@ jump_back_p (insn, target)
 {
   rtx cinsn, ctarget;
   enum rtx_code codei, codet;
+  rtx set, tset;
 
-  if (simplejump_p (insn) || ! condjump_p (insn)
-      || simplejump_p (target)
+  if (! any_condjump_p (insn)
+      || any_uncondjump_p (target)
       || target != prev_real_insn (JUMP_LABEL (insn)))
     return 0;
+  set = pc_set (insn);
+  tset = pc_set (target);
 
-  cinsn = XEXP (SET_SRC (PATTERN (insn)), 0);
-  ctarget = XEXP (SET_SRC (PATTERN (target)), 0);
+  cinsn = XEXP (SET_SRC (set), 0);
+  ctarget = XEXP (SET_SRC (tset), 0);
 
   codei = GET_CODE (cinsn);
   codet = GET_CODE (ctarget);
 
-  if (XEXP (SET_SRC (PATTERN (insn)), 1) == pc_rtx)
+  if (XEXP (SET_SRC (set), 1) == pc_rtx)
     {
       if (! can_reverse_comparison_p (cinsn, insn))
        return 0;
       codei = reverse_condition (codei);
     }
 
-  if (XEXP (SET_SRC (PATTERN (target)), 2) == pc_rtx)
+  if (XEXP (SET_SRC (tset), 2) == pc_rtx)
     {
       if (! can_reverse_comparison_p (ctarget, target))
        return 0;
@@ -1750,7 +1704,7 @@ can_reverse_comparison_p (comparison, insn)
   arg0 = XEXP (comparison, 0);
 
   /* Make sure ARG0 is one of the actual objects being compared.  If we
-     can't do this, we can't be sure the comparison can be reversed. 
+     can't do this, we can't be sure the comparison can be reversed.
 
      Handle cc0 and a MODE_CC register.  */
   if ((GET_CODE (arg0) == REG && GET_MODE_CLASS (GET_MODE (arg0)) == MODE_CC)
@@ -1759,8 +1713,7 @@ can_reverse_comparison_p (comparison, insn)
 #endif
       )
     {
-      rtx prev = prev_nonnote_insn (insn);
-      rtx set;
+      rtx prev, set;
 
       /* First see if the condition code mode alone if enough to say we can
         reverse the condition.  If not, then search backwards for a set of
@@ -1772,7 +1725,10 @@ can_reverse_comparison_p (comparison, insn)
          && REVERSIBLE_CC_MODE (GET_MODE (arg0)))
        return 1;
 #endif
-       
+
+      if (! insn)
+       return 0;
+
       for (prev = prev_nonnote_insn (insn);
           prev != 0 && GET_CODE (prev) != CODE_LABEL;
           prev = prev_nonnote_insn (prev))
@@ -1800,7 +1756,7 @@ can_reverse_comparison_p (comparison, insn)
 
    WATCH OUT!  reverse_condition is not safe to use on a jump that might
    be acting on the results of an IEEE floating point comparison, because
-   of the special treatment of non-signaling nans in comparisons.  
+   of the special treatment of non-signaling nans in comparisons.
    Use can_reverse_comparison_p to be sure.  */
 
 enum rtx_code
@@ -2065,7 +2021,7 @@ comparison_dominates_p (code1, code2)
       if (code2 == NE)
        return 1;
       break;
-      
+
     default:
       break;
     }
@@ -2086,7 +2042,10 @@ simplejump_p (insn)
 }
 
 /* Return nonzero if INSN is a (possibly) conditional jump
-   and nothing more.  */
+   and nothing more.
+
+   Use 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)
@@ -2101,19 +2060,23 @@ condjump_p (insn)
   x = SET_SRC (x);
   if (GET_CODE (x) == LABEL_REF)
     return 1;
-  else return (GET_CODE (x) == IF_THEN_ELSE
-              && ((GET_CODE (XEXP (x, 2)) == PC
-                   && (GET_CODE (XEXP (x, 1)) == LABEL_REF
-                       || GET_CODE (XEXP (x, 1)) == RETURN))
-                  || (GET_CODE (XEXP (x, 1)) == PC
-                      && (GET_CODE (XEXP (x, 2)) == LABEL_REF
-                          || GET_CODE (XEXP (x, 2)) == RETURN))));
+  else
+    return (GET_CODE (x) == IF_THEN_ELSE
+           && ((GET_CODE (XEXP (x, 2)) == PC
+                && (GET_CODE (XEXP (x, 1)) == LABEL_REF
+                    || GET_CODE (XEXP (x, 1)) == RETURN))
+               || (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
-   PARALLEL.  */
+   PARALLEL.
+
+   Use this function is deprecated, since we need to support combined
+   branch and compare insns.  Use any_condjump_p instead whenever possible.  */
 
 int
 condjump_in_parallel_p (insn)
@@ -2145,19 +2108,77 @@ condjump_in_parallel_p (insn)
   return 0;
 }
 
+/* Return set of PC, otherwise NULL.  */
+
+rtx
+pc_set (insn)
+     rtx insn;
+{
+  rtx pat;
+  if (GET_CODE (insn) != JUMP_INSN)
+    return NULL_RTX;
+  pat = PATTERN (insn);
+
+  /* The set is allowed to appear either as the insn pattern or
+     the first set in a PARALLEL.  */
+  if (GET_CODE (pat) == PARALLEL)
+    pat = XVECEXP (pat, 0, 0);
+  if (GET_CODE (pat) == SET && GET_CODE (SET_DEST (pat)) == PC)
+    return pat;
+
+  return NULL_RTX;
+}
+
+/* Return true when insn is an unconditional direct jump,
+   possibly bundled inside a PARALLEL.  */
+
+int
+any_uncondjump_p (insn)
+     rtx insn;
+{
+  rtx x = pc_set (insn);
+  if (!x)
+    return 0;
+  if (GET_CODE (SET_SRC (x)) != LABEL_REF)
+    return 0;
+  return 1;
+}
+
+/* Return true when insn is a conditional jump.  This function works for
+   instructions containing PC sets in PARALLELs.  The instruction may have
+   various other effects so before removing the jump you must verify
+   onlyjump_p.
+
+   Note that unlike condjump_p it returns false for unconditional jumps.  */
+
+int
+any_condjump_p (insn)
+     rtx insn;
+{
+  rtx x = pc_set (insn);
+  enum rtx_code a, b;
+
+  if (!x)
+    return 0;
+  if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE)
+    return 0;
+
+  a = GET_CODE (XEXP (SET_SRC (x), 1));
+  b = GET_CODE (XEXP (SET_SRC (x), 2));
+
+  return ((b == PC && (a == LABEL_REF || a == RETURN))
+         || (a == PC && (b == LABEL_REF || b == RETURN)));
+}
+
 /* Return the label of a conditional jump.  */
 
 rtx
 condjump_label (insn)
      rtx insn;
 {
-  register rtx x = PATTERN (insn);
+  rtx x = pc_set (insn);
 
-  if (GET_CODE (x) == PARALLEL)
-    x = XVECEXP (x, 0, 0);
-  if (GET_CODE (x) != SET)
-    return NULL_RTX;
-  if (GET_CODE (SET_DEST (x)) != PC)
+  if (!x)
     return NULL_RTX;
   x = SET_SRC (x);
   if (GET_CODE (x) == LABEL_REF)
@@ -2186,6 +2207,8 @@ int
 returnjump_p (insn)
      rtx insn;
 {
+  if (GET_CODE (insn) != JUMP_INSN)
+    return 0;
   return for_each_rtx (&PATTERN (insn), returnjump_p_1, NULL);
 }
 
@@ -2266,7 +2289,8 @@ follow_jumps (label)
        (depth < 10
        && (insn = next_active_insn (value)) != 0
        && GET_CODE (insn) == JUMP_INSN
-       && ((JUMP_LABEL (insn) != 0 && simplejump_p (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);
@@ -2375,11 +2399,11 @@ mark_jump_label (x, insn, cross_jump, in_mem)
 
     case SYMBOL_REF:
       if (!in_mem)
-        return;
+       return;
 
       /* If this is a constant-pool reference, see if it is a label.  */
       if (CONSTANT_POOL_ADDRESS_P (x))
-        mark_jump_label (get_pool_constant (x), insn, cross_jump, in_mem);
+       mark_jump_label (get_pool_constant (x), insn, cross_jump, in_mem);
       break;
 
     case LABEL_REF:
@@ -2389,6 +2413,12 @@ mark_jump_label (x, insn, cross_jump, in_mem)
        rtx note;
        rtx next;
 
+       /* Ignore remaining references to unreachable labels that
+          have been deleted.  */
+       if (GET_CODE (label) == NOTE
+           && NOTE_LINE_NUMBER (label) == NOTE_INSN_DELETED_LABEL)
+         break;
+
        if (GET_CODE (label) != CODE_LABEL)
          abort ();
 
@@ -2413,7 +2443,8 @@ mark_jump_label (x, insn, cross_jump, in_mem)
                         || NOTE_LINE_NUMBER (next) == NOTE_INSN_FUNCTION_END
                         /* ??? Optional.  Disables some optimizations, but
                            makes gcov output more accurate with -O.  */
-                        || (flag_test_coverage && NOTE_LINE_NUMBER (next) > 0)))
+                        || (flag_test_coverage
+                            && NOTE_LINE_NUMBER (next) > 0)))
              break;
          }
 
@@ -2449,7 +2480,7 @@ mark_jump_label (x, insn, cross_jump, in_mem)
                   is no longer valid because of the more accurate cfg
                   we build in find_basic_blocks -- it no longer pessimizes
                   code when it finds a REG_LABEL note.  */
-               REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_LABEL, label,
+               REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, label,
                                                      REG_NOTES (insn));
              }
          }
@@ -2465,11 +2496,11 @@ mark_jump_label (x, insn, cross_jump, in_mem)
          int eltnum = code == ADDR_DIFF_VEC ? 1 : 0;
 
          for (i = 0; i < XVECLEN (x, eltnum); i++)
-           mark_jump_label (XVECEXP (x, eltnum, i), NULL_RTX, 
-                    cross_jump, in_mem);
+           mark_jump_label (XVECEXP (x, eltnum, i), NULL_RTX,
+                            cross_jump, in_mem);
        }
       return;
-      
+
     default:
       break;
     }
@@ -2580,12 +2611,15 @@ delete_prior_computation (note, insn)
            {
              int dest_regno = REGNO (SET_DEST (pat));
              int dest_endregno
-                   = dest_regno + (dest_regno < FIRST_PSEUDO_REGISTER 
+               = (dest_regno
+                  + (dest_regno < FIRST_PSEUDO_REGISTER
                      ? HARD_REGNO_NREGS (dest_regno,
-                               GET_MODE (SET_DEST (pat))) : 1);
+                                         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);
+             int endregno
+               = (regno
+                  + (regno < FIRST_PSEUDO_REGISTER
+                     ? HARD_REGNO_NREGS (regno, GET_MODE (reg)) : 1));
 
              if (dest_regno >= regno
                  && dest_endregno <= endregno)
@@ -2601,7 +2635,8 @@ delete_prior_computation (note, insn)
                  int i;
 
                  REG_NOTES (our_prev)
-                   = gen_rtx_EXPR_LIST (REG_UNUSED, reg, 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))
@@ -2687,24 +2722,25 @@ delete_computation (insn)
   set = single_set (insn);
   if (set && GET_CODE (SET_DEST (set)) == REG)
     {
-    int dest_regno = REGNO (SET_DEST (set));
-    int dest_endregno
-         = dest_regno + (dest_regno < FIRST_PSEUDO_REGISTER 
-           ? HARD_REGNO_NREGS (dest_regno,
-                               GET_MODE (SET_DEST (set))) : 1);
-    int i;
-
-    for (i = dest_regno; i < dest_endregno; i++)
-      {
-       if (! refers_to_regno_p (i, i + 1, SET_SRC (set), NULL_PTR)
-           || find_regno_note (insn, REG_DEAD, i))
-         continue;
-
-       note = gen_rtx_EXPR_LIST (REG_DEAD, (i < FIRST_PSEUDO_REGISTER
-                                            ? gen_rtx_REG (reg_raw_mode[i], i)
-                                            : SET_DEST (set)), NULL_RTX);
-       delete_prior_computation (note, insn);
-      }
+      int dest_regno = REGNO (SET_DEST (set));
+      int dest_endregno
+       = dest_regno + (dest_regno < FIRST_PSEUDO_REGISTER
+                       ? HARD_REGNO_NREGS (dest_regno,
+                                           GET_MODE (SET_DEST (set))) : 1);
+      int i;
+
+      for (i = dest_regno; i < dest_endregno; i++)
+       {
+         if (! refers_to_regno_p (i, i + 1, SET_SRC (set), NULL_PTR)
+             || find_regno_note (insn, REG_DEAD, i))
+           continue;
+
+         note = gen_rtx_EXPR_LIST (REG_DEAD,
+                                   (i < FIRST_PSEUDO_REGISTER
+                                    ? gen_rtx_REG (reg_raw_mode[i], i)
+                                    : SET_DEST (set)), NULL_RTX);
+         delete_prior_computation (note, insn);
+       }
     }
 
   for (note = REG_NOTES (insn); note; note = next)
@@ -2755,9 +2791,10 @@ delete_insn (insn)
        dont_really_delete = 1;
       else if (! dont_really_delete)
        {
+         const char *name = LABEL_NAME (insn);
          PUT_CODE (insn, NOTE);
          NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED_LABEL;
-         NOTE_SOURCE_FILE (insn) = 0;
+         NOTE_SOURCE_FILE (insn) = name;
          dont_really_delete = 1;
        }
     }
@@ -2966,19 +3003,19 @@ never_reached_warning (avoided_insn)
   rtx a_line_note = NULL;
   int two_avoided_lines = 0;
   int contains_insn = 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 (GET_CODE (insn) == CODE_LABEL)
-        break;
-       else if (GET_CODE (insn) == NOTE                /* A line number note? */ 
-               && NOTE_LINE_NUMBER (insn) >= 0)
+      if (GET_CODE (insn) == CODE_LABEL)
+       break;
+      else if (GET_CODE (insn) == NOTE         /* A line number note?  */
+              && NOTE_LINE_NUMBER (insn) >= 0)
        {
          if (a_line_note == NULL)
            a_line_note = insn;
@@ -2986,8 +3023,8 @@ never_reached_warning (avoided_insn)
            two_avoided_lines |= (NOTE_LINE_NUMBER (a_line_note)
                                  != NOTE_LINE_NUMBER (insn));
        }
-       else if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
-        contains_insn = 1;
+      else if (INSN_P (insn))
+       contains_insn = 1;
     }
   if (two_avoided_lines && contains_insn)
     warning_with_file_and_line (NOTE_SOURCE_FILE (a_line_note),
@@ -3017,7 +3054,7 @@ redirect_exp_1 (loc, olabel, nlabel, insn)
          if (nlabel)
            n = gen_rtx_LABEL_REF (VOIDmode, nlabel);
          else
-           n = gen_rtx_RETURN (VOIDmode); 
+           n = gen_rtx_RETURN (VOIDmode);
 
          validate_change (insn, loc, n, 1);
          return;
@@ -3056,12 +3093,18 @@ redirect_exp_1 (loc, olabel, nlabel, insn)
 
 /* Similar, but apply the change group and report success or failure.  */
 
-int
-redirect_exp (loc, olabel, nlabel, insn)
-     rtx *loc;
+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;
@@ -3078,7 +3121,14 @@ redirect_jump_1 (jump, nlabel)
      rtx jump, nlabel;
 {
   int ochanges = num_validated_changes ();
-  redirect_exp_1 (&PATTERN (jump), JUMP_LABEL (jump), nlabel, jump);
+  rtx *loc;
+
+  if (GET_CODE (PATTERN (jump)) == PARALLEL)
+    loc = &XVECEXP (PATTERN (jump), 0, 0);
+  else
+    loc = &PATTERN (jump);
+
+  redirect_exp_1 (loc, JUMP_LABEL (jump), nlabel, jump);
   return num_validated_changes () > ochanges;
 }
 
@@ -3093,15 +3143,16 @@ redirect_jump_1 (jump, nlabel)
    (this can only occur for NLABEL == 0).  */
 
 int
-redirect_jump (jump, nlabel)
+redirect_jump (jump, nlabel, delete_unused)
      rtx jump, nlabel;
+     int delete_unused;
 {
   register rtx olabel = JUMP_LABEL (jump);
 
   if (nlabel == olabel)
     return 1;
 
-  if (! redirect_exp (&PATTERN (jump), olabel, nlabel, jump))
+  if (! redirect_exp (olabel, nlabel, jump))
     return 0;
 
   /* If this is an unconditional branch, delete it from the jump_chain of
@@ -3127,28 +3178,31 @@ redirect_jump (jump, 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 && NEXT_INSN (olabel)
+  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);
 
-  if (olabel && --LABEL_NUSES (olabel) == 0)
+  if (olabel && --LABEL_NUSES (olabel) == 0 && delete_unused)
     delete_insn (olabel);
 
   return 1;
 }
 
-/* Invert the jump condition of rtx X contained in jump insn, INSN.  
+/* Invert the jump condition of rtx X contained in jump insn, INSN.
    Accrue the modifications into the change group.  */
 
 static void
-invert_exp_1 (x, insn)
-     rtx x;
+invert_exp_1 (insn)
      rtx insn;
 {
   register RTX_CODE code;
-  register int i;
-  register const char *fmt;
+  rtx x = pc_set (insn);
+
+  if (!x)
+    abort ();
+  x = SET_SRC (x);
 
   code = GET_CODE (x);
 
@@ -3171,38 +3225,25 @@ invert_exp_1 (x, insn)
                           1);
          return;
        }
-                                      
+
       tem = XEXP (x, 1);
       validate_change (insn, &XEXP (x, 1), XEXP (x, 2), 1);
       validate_change (insn, &XEXP (x, 2), tem, 1);
-      return;
-    }
-
-  fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    {
-      if (fmt[i] == 'e')
-       invert_exp_1 (XEXP (x, i), insn);
-      else if (fmt[i] == 'E')
-       {
-         register int j;
-         for (j = 0; j < XVECLEN (x, i); j++)
-           invert_exp_1 (XVECEXP (x, i, j), insn);
-       }
     }
+  else
+    abort ();
 }
 
-/* Invert the jump condition of rtx X contained in jump insn, INSN. 
+/* 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.  */
 
-int
-invert_exp (x, insn)
-     rtx x;
+static int
+invert_exp (insn)
      rtx insn;
 {
-  invert_exp_1 (x, insn);
+  invert_exp_1 (insn);
   if (num_validated_changes () == 0)
     return 0;
 
@@ -3221,7 +3262,7 @@ invert_jump_1 (jump, nlabel)
   int ochanges;
 
   ochanges = num_validated_changes ();
-  invert_exp_1 (PATTERN (jump), jump);
+  invert_exp_1 (jump);
   if (num_validated_changes () == ochanges)
     return 0;
 
@@ -3232,18 +3273,19 @@ invert_jump_1 (jump, nlabel)
    NLABEL instead of where it jumps now.  Return true if successful.  */
 
 int
-invert_jump (jump, nlabel)
+invert_jump (jump, nlabel, delete_unused)
      rtx jump, 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 (PATTERN (jump), jump))
+  if (! invert_exp (jump))
     return 0;
 
-  if (redirect_jump (jump, nlabel))
+  if (redirect_jump (jump, nlabel, delete_unused))
     {
       /* An inverted jump means that a probability taken becomes a
         probability not taken.  Subtract the branch probability from the
@@ -3256,7 +3298,7 @@ invert_jump (jump, nlabel)
       return 1;
     }
 
-  if (! invert_exp (PATTERN (jump), jump))
+  if (! invert_exp (jump))
     /* This should just be putting it back the way it was.  */
     abort ();
 
@@ -3280,7 +3322,8 @@ delete_from_jump_chain (jump)
   /* Handle return insns.  */
   else if (jump_chain && GET_CODE (PATTERN (jump)) == RETURN)
     index = 0;
-  else return;
+  else
+    return;
 
   if (jump_chain[index] == jump)
     jump_chain[index] = jump_chain[INSN_UID (jump)];
@@ -3391,7 +3434,7 @@ rtx_renumbered_equal_p (x, y)
   register int i;
   register RTX_CODE code = GET_CODE (x);
   register const char *fmt;
-      
+
   if (x == y)
     return 1;
 
@@ -3451,7 +3494,7 @@ rtx_renumbered_equal_p (x, y)
       return reg_x >= 0 && reg_x == reg_y && word_x == word_y;
     }
 
-  /* Now we have disposed of all the cases 
+  /* Now we have disposed of all the cases
      in which different rtx codes can match.  */
   if (code != GET_CODE (y))
     return 0;
@@ -3605,7 +3648,7 @@ true_regnum (x)
    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
@@ -3627,7 +3670,7 @@ static char *modified_regs;
 
 static int modified_mem;
 
-/* Called via note_stores on each insn between the target of the first 
+/* 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
@@ -3657,7 +3700,7 @@ mark_modified_reg (dest, x, data)
 }
 
 /* F is the first insn in the chain of insns.  */
-   
+
 void
 thread_jumps (f, max_reg, flag_before_loop)
      rtx f;
@@ -3673,7 +3716,7 @@ thread_jumps (f, max_reg, flag_before_loop)
      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;
@@ -3687,20 +3730,22 @@ thread_jumps (f, max_reg, flag_before_loop)
   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
-             || ! condjump_p (b1) || simplejump_p (b1)
-             || JUMP_LABEL (b1) == 0)
+             || ! any_condjump_p (b1) || JUMP_LABEL (b1) == 0)
            continue;
 
-         bzero (modified_regs, max_reg * sizeof (char));
+         memset (modified_regs, 0, max_reg * sizeof (char));
          modified_mem = 0;
 
          bcopy ((char *) all_reset, (char *) same_regs,
@@ -3721,7 +3766,8 @@ thread_jumps (f, max_reg, flag_before_loop)
                {
                  /* If this is an unconditional jump and is the only use of
                     its target label, we can follow it.  */
-                 if (simplejump_p (b2)
+                 if (any_uncondjump_p (b2)
+                     && onlyjump_p (b2)
                      && JUMP_LABEL (b2) != 0
                      && LABEL_NUSES (JUMP_LABEL (b2)) == 1)
                    {
@@ -3755,23 +3801,25 @@ thread_jumps (f, max_reg, flag_before_loop)
          if (b2 == 0
              || GET_CODE (b2) != JUMP_INSN
              || b2 == b1
-             || ! condjump_p (b2)
-             || simplejump_p (b2))
+             || !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 (PATTERN (b1)), 0), 0);
-         b1op1 = XEXP (XEXP (SET_SRC (PATTERN (b1)), 0), 1);
-         code1 = GET_CODE (XEXP (SET_SRC (PATTERN (b1)), 0));
-         if (XEXP (SET_SRC (PATTERN (b1)), 1) == pc_rtx)
+         b1op0 = XEXP (XEXP (SET_SRC (set), 0), 0);
+         b1op1 = XEXP (XEXP (SET_SRC (set), 0), 1);
+         code1 = GET_CODE (XEXP (SET_SRC (set), 0));
+         if (XEXP (SET_SRC (set), 1) == pc_rtx)
            code1 = reverse_condition (code1);
 
-         b2op0 = XEXP (XEXP (SET_SRC (PATTERN (b2)), 0), 0);
-         b2op1 = XEXP (XEXP (SET_SRC (PATTERN (b2)), 0), 1);
-         code2 = GET_CODE (XEXP (SET_SRC (PATTERN (b2)), 0));
-         if (XEXP (SET_SRC (PATTERN (b2)), 1) == pc_rtx)
+         b2op0 = XEXP (XEXP (SET_SRC (set2), 0), 0);
+         b2op1 = XEXP (XEXP (SET_SRC (set2), 0), 1);
+         code2 = GET_CODE (XEXP (SET_SRC (set2), 0));
+         if (XEXP (SET_SRC (set2), 1) == pc_rtx)
            code2 = reverse_condition (code2);
 
          /* If they test the same things and knowing that B1 branches
@@ -3780,15 +3828,14 @@ thread_jumps (f, max_reg, flag_before_loop)
          if (rtx_equal_for_thread_p (b1op0, b2op0, b2)
              && rtx_equal_for_thread_p (b1op1, b2op1, b2)
              && (comparison_dominates_p (code1, code2)
-                 || (can_reverse_comparison_p (XEXP (SET_SRC (PATTERN (b1)),
-                                                     0),
-                                               b1)
-                     && comparison_dominates_p (code1, reverse_condition (code2)))))
+                 || (can_reverse_comparison_p (XEXP (SET_SRC (set), 0), b1)
+                     && comparison_dominates_p (code1,
+                                                reverse_condition (code2)))))
 
            {
              t1 = prev_nonnote_insn (b1);
              t2 = prev_nonnote_insn (b2);
-             
+
              while (t1 != 0 && t2 != 0)
                {
                  if (t2 == label)
@@ -3804,7 +3851,7 @@ thread_jumps (f, max_reg, flag_before_loop)
                        break;
 
                      if (comparison_dominates_p (code1, code2))
-                       new_label = JUMP_LABEL (b2);
+                       new_label = JUMP_LABEL (b2);
                      else
                        new_label = get_label_after (b2);
 
@@ -3822,11 +3869,11 @@ thread_jumps (f, max_reg, flag_before_loop)
                              new_label = gen_label_rtx ();
                              emit_label_after (new_label, PREV_INSN (prev));
                            }
-                         changed |= redirect_jump (b1, new_label);
+                         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
@@ -3836,7 +3883,7 @@ thread_jumps (f, max_reg, flag_before_loop)
                      || ! rtx_equal_for_thread_p (PATTERN (t1),
                                                   PATTERN (t2), t2))
                    break;
-                   
+
                  t1 = prev_nonnote_insn (t1);
                  t2 = prev_nonnote_insn (t2);
                }
@@ -3853,7 +3900,7 @@ thread_jumps (f, max_reg, flag_before_loop)
 /* 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
@@ -3917,7 +3964,7 @@ rtx_equal_for_thread_p (x, y, yinsn)
          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 
+            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;
@@ -3949,7 +3996,7 @@ rtx_equal_for_thread_p (x, y, yinsn)
       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)))
+         if (same_regs[REGNO (SET_DEST (x))] == (int) REGNO (SET_DEST (y)))
            {
              same_regs[REGNO (SET_DEST (x))] = -1;
              num_same_regs--;
@@ -3958,8 +4005,10 @@ rtx_equal_for_thread_p (x, y, yinsn)
            return 0;
        }
       else
-       if (rtx_equal_for_thread_p (SET_DEST (x), SET_DEST (y), yinsn) == 0)
-         return 0;
+       {
+         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);
 
@@ -3968,7 +4017,7 @@ rtx_equal_for_thread_p (x, y, yinsn)
 
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
-      
+
     default:
       break;
     }
@@ -4001,7 +4050,7 @@ rtx_equal_for_thread_p (x, y, yinsn)
          /* 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)
+                                       XVECEXP (y, i, j), yinsn) == 0)
              return 0;
          break;