OSDN Git Service

(jump_optimize): Fix second error in last change.
[pf3gnuchains/gcc-fork.git] / gcc / jump.c
index 40258a5..27a382a 100644 (file)
@@ -1,5 +1,5 @@
 /* Optimize jump instructions, for GNU compiler.
-   Copyright (C) 1987, 88, 89, 91, 92, 93, 1994 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 89, 91-95, 1996 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -15,7 +15,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 /* This is the jump-optimization pass of the compiler.
@@ -55,10 +56,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "flags.h"
 #include "hard-reg-set.h"
 #include "regs.h"
-#include "expr.h"
 #include "insn-config.h"
 #include "insn-flags.h"
+#include "expr.h"
 #include "real.h"
+#include "except.h"
 
 /* ??? Eventually must record somehow the labels used by jumps
    from nested functions.  */
@@ -99,7 +101,7 @@ int can_reach_end;
    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
    stack register conversion, and we must compare death notes in that
-   case. */
+   case.  */
 
 static int cross_jump_death_matters = 0;
 
@@ -197,7 +199,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
      we make.  */
   max_jump_chain = max_uid * 14 / 10;
   jump_chain = (rtx *) alloca (max_jump_chain * sizeof (rtx));
-  bzero (jump_chain, max_jump_chain * sizeof (rtx));
+  bzero ((char *) jump_chain, max_jump_chain * sizeof (rtx));
 
   /* Mark the label each jump jumps to.
      Combine consecutive labels, and count uses of labels.
@@ -233,6 +235,16 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
   for (insn = forced_labels; insn; insn = XEXP (insn, 1))
     LABEL_NUSES (XEXP (insn, 0))++;
 
+  check_exception_handler_labels ();
+
+  /* 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))
+    LABEL_NUSES (XEXP (insn, 0))++;
+
+  exception_optimize ();
+
   /* Delete all labels already not referenced.
      Also find the last insn.  */
 
@@ -265,6 +277,8 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
                      then one of them follows the note.  */
                   || (GET_CODE (insn) == JUMP_INSN
                       && GET_CODE (PATTERN (insn)) == RETURN)
+                  /* A barrier can follow the return insn.  */
+                  || GET_CODE (insn) == BARRIER
                   /* Other kinds of notes can follow also.  */
                   || (GET_CODE (insn) == NOTE
                       && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END)))
@@ -435,28 +449,39 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
                                              sreg, NULL_PTR, dreg,
                                              GET_MODE (SET_SRC (body)));
 
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
-                   /* Deleting insn could lose a death-note for SREG or DREG
-                      so don't do it if final needs accurate death-notes.  */
-                   if (! PRESERVE_DEATH_INFO_REGNO_P (sreg)
-                       && ! PRESERVE_DEATH_INFO_REGNO_P (dreg))
-#endif
+                   if (tem != 0 &&
+                       GET_MODE (tem) == GET_MODE (SET_DEST (body)))
                      {
                        /* DREG may have been the target of a REG_DEAD note in
                           the insn which makes INSN redundant.  If so, reorg
                           would still think it is dead.  So search for such a
                           note and delete it if we find it.  */
-                       for (trial = prev_nonnote_insn (insn);
-                            trial && GET_CODE (trial) != CODE_LABEL;
-                            trial = prev_nonnote_insn (trial))
-                         if (find_regno_note (trial, REG_DEAD, dreg))
-                           {
-                             remove_death (dreg, trial);
-                             break;
-                           }
-
-                       if (tem != 0
-                           && GET_MODE (tem) == GET_MODE (SET_DEST (body)))
+                       if (! find_regno_note (insn, REG_UNUSED, dreg))
+                         for (trial = prev_nonnote_insn (insn);
+                              trial && GET_CODE (trial) != CODE_LABEL;
+                              trial = prev_nonnote_insn (trial))
+                           if (find_regno_note (trial, REG_DEAD, dreg))
+                             {
+                               remove_death (dreg, trial);
+                               break;
+                             }
+#ifdef PRESERVE_DEATH_INFO_REGNO_P
+                       /* Deleting insn could lose a death-note for SREG
+                          so don't do it if final needs accurate
+                          death-notes.  */
+                       if (PRESERVE_DEATH_INFO_REGNO_P (sreg)
+                           && (trial = find_regno_note (insn, REG_DEAD, sreg)))
+                         {
+                           /* Change this into a USE so that we won't emit
+                              code for it, but still can keep the note.  */
+                           PATTERN (insn)
+                             = gen_rtx (USE, VOIDmode, XEXP (trial, 0));
+                           /* Remove all reg notes but the REG_DEAD one.  */
+                           REG_NOTES (insn) = trial;
+                           XEXP (trial, 1) = NULL_RTX;
+                         }
+                       else
+#endif
                          delete_insn (insn);
                      }
                  }
@@ -496,7 +521,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
            else if (GET_CODE (body) == PARALLEL)
              {
                /* If each part is a set between two identical registers or
-                  a USE or CLOBBER, delete the insn. */
+                  a USE or CLOBBER, delete the insn.  */
                int i, sreg, dreg;
                rtx tem;
 
@@ -516,17 +541,16 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
                if (i < 0)
                  delete_insn (insn);
              }
-#if !BYTES_BIG_ENDIAN /* Not worth the hair to detect this
-                        in the big-endian case.  */
            /* Also delete insns to store bit fields if they are no-ops.  */
-           else if (GET_CODE (body) == SET
+           /* Not worth the hair to detect this in the big-endian case.  */
+           else if (! BYTES_BIG_ENDIAN
+                    && GET_CODE (body) == SET
                     && GET_CODE (SET_DEST (body)) == ZERO_EXTRACT
                     && XEXP (SET_DEST (body), 2) == const0_rtx
                     && XEXP (SET_DEST (body), 0) == SET_SRC (body)
                     && ! (GET_CODE (SET_SRC (body)) == MEM
                           && MEM_VOLATILE_P (SET_SRC (body))))
              delete_insn (insn);
-#endif /* not BYTES_BIG_ENDIAN */
          }
       insn = next;
     }
@@ -550,7 +574,8 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
               of a reg that's used in notes.  A subsequent optimization
               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)))
+           && ! side_effects_p (SET_SRC (set))
+           && ! find_reg_note (insn, REG_RETVAL, 0))
          delete_insn (insn);
       }
 
@@ -566,6 +591,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
          rtx temp, temp1, temp2, temp3, temp4, temp5, temp6;
          rtx nlabel;
          int this_is_simplejump, this_is_condjump, reversep;
+         int this_is_condjump_in_parallel;
 #if 0
          /* If NOT the first iteration, if this is the last jump pass
             (just before final), do the special peephole optimizations.
@@ -605,6 +631,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
 
          this_is_simplejump = simplejump_p (insn);
          this_is_condjump = condjump_p (insn);
+         this_is_condjump_in_parallel = condjump_in_parallel_p (insn);
 
          /* Tension the labels in dispatch tables.  */
 
@@ -658,6 +685,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
          /* Detect jump to following insn.  */
          if (reallabelprev == insn && condjump_p (insn))
            {
+             next = next_real_insn (JUMP_LABEL (insn));
              delete_jump (insn);
              changed = 1;
              continue;
@@ -676,7 +704,15 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
              && (temp1 = prev_nonnote_insn (JUMP_LABEL (insn))) != 0
              && (GET_CODE (temp1) == BARRIER
                  || (GET_CODE (temp1) == INSN
-                     && rtx_equal_p (PATTERN (temp), PATTERN (temp1)))))
+                     && rtx_equal_p (PATTERN (temp), PATTERN (temp1))))
+             /* Don't do this optimization if we have a loop containing only
+                the USE instruction, and the loop start label has a usage
+                count of 1.  This is because we will redo this optimization
+                everytime through the outer loop, and jump opt will never
+                exit.  */
+             && ! ((temp2 = prev_nonnote_insn (temp)) != 0
+                   && temp2 == JUMP_LABEL (insn)
+                   && LABEL_NUSES (temp2) == 1))
            {
              if (GET_CODE (temp1) == BARRIER)
                {
@@ -827,6 +863,98 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
                }
            }
 
+         /* Simplify   if (...) { x = a; goto l; } x = b; by converting it
+            to         x = a; if (...) goto l; x = b;
+            if A is sufficiently simple, the test doesn't involve X,
+            and nothing in the test modifies A or X.
+
+            If we have small register classes, we also can't do this if X
+            is a hard register.
+
+            If the "x = a;" insn has any REG_NOTES, we don't do this because
+            of the possibility that we are running after CSE and there is a
+            REG_EQUAL note that is only valid if the branch has already been
+            taken.  If we move the insn with the REG_EQUAL note, we may
+            fold the comparison to always be false in a later CSE pass.
+            (We could also delete the REG_NOTES when moving the insn, but it
+            seems simpler to not move it.)  An exception is that we can move
+            the insn if the only note is a REG_EQUAL or REG_EQUIV whose
+            value is the same as "a".
+
+            INSN is the goto.
+
+            We set:
+
+            TEMP to the jump insn preceding "x = a;"
+            TEMP1 to X
+            TEMP2 to the insn that sets "x = b;"
+            TEMP3 to the insn that sets "x = a;"
+            TEMP4 to the set of "x = a";  */
+
+         if (this_is_simplejump
+             && (temp2 = next_active_insn (insn)) != 0
+             && GET_CODE (temp2) == INSN
+             && (temp4 = single_set (temp2)) != 0
+             && GET_CODE (temp1 = SET_DEST (temp4)) == REG
+#ifdef SMALL_REGISTER_CLASSES
+             && REGNO (temp1) >= FIRST_PSEUDO_REGISTER
+#endif
+
+             && (temp3 = prev_active_insn (insn)) != 0
+             && GET_CODE (temp3) == INSN
+             && (temp4 = single_set (temp3)) != 0
+             && rtx_equal_p (SET_DEST (temp4), temp1)
+             && (GET_CODE (SET_SRC (temp4)) == REG
+                 || GET_CODE (SET_SRC (temp4)) == SUBREG
+                 || CONSTANT_P (SET_SRC (temp4)))
+             && (REG_NOTES (temp3) == 0
+                 || ((REG_NOTE_KIND (REG_NOTES (temp3)) == REG_EQUAL
+                      || REG_NOTE_KIND (REG_NOTES (temp3)) == REG_EQUIV)
+                     && XEXP (REG_NOTES (temp3), 1) == 0
+                     && rtx_equal_p (XEXP (REG_NOTES (temp3), 0),
+                                     SET_SRC (temp4))))
+             && (temp = prev_active_insn (temp3)) != 0
+             && condjump_p (temp) && ! simplejump_p (temp)
+             /* TEMP must skip over the "x = a;" insn */
+             && prev_real_insn (JUMP_LABEL (temp)) == insn
+             && no_labels_between_p (temp, insn))
+           {
+             rtx prev_label = JUMP_LABEL (temp);
+             rtx insert_after = prev_nonnote_insn (temp);
+
+#ifdef HAVE_cc0
+             /* We cannot insert anything between a set of cc and its use.  */
+             if (insert_after && GET_RTX_CLASS (GET_CODE (insert_after)) == 'i'
+                 && sets_cc0_p (PATTERN (insert_after)))
+               insert_after = prev_nonnote_insn (insert_after);
+#endif
+             ++LABEL_NUSES (prev_label);
+
+             if (insert_after
+                 && no_labels_between_p (insert_after, temp)
+                 && ! reg_referenced_between_p (temp1, insert_after, temp3)
+                 && ! reg_referenced_between_p (temp1, temp3,
+                                                NEXT_INSN (temp2))
+                 && ! reg_set_between_p (temp1, insert_after, temp)
+                 && (GET_CODE (SET_SRC (temp4)) == CONST_INT
+                     || ! reg_set_between_p (SET_SRC (temp4),
+                                             insert_after, temp))
+                 && invert_jump (temp, JUMP_LABEL (insn)))
+               {
+                 emit_insn_after_with_line_notes (PATTERN (temp3),
+                                                  insert_after, temp3);
+                 delete_insn (temp3);
+                 delete_insn (insn);
+                 /* Set NEXT to an insn that we know won't go away.  */
+                 next = temp2;
+                 changed = 1;
+               }
+             if (prev_label && --LABEL_NUSES (prev_label) == 0)
+               delete_insn (prev_label);
+             if (changed)
+               continue;
+           }
+
 #ifndef HAVE_cc0
          /* If we have if (...) x = exp;  and branches are expensive,
             EXP is a single insn, does not have any side effects, cannot
@@ -865,7 +993,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
              && GET_CODE (SET_SRC (temp1)) != CONST_INT
              && ! side_effects_p (SET_SRC (temp1))
              && ! may_trap_p (SET_SRC (temp1))
-             && rtx_cost (SET_SRC (temp1)) < 10)
+             && rtx_cost (SET_SRC (temp1), SET) < 10)
            {
              rtx new = gen_reg_rtx (GET_MODE (temp2));
 
@@ -904,12 +1032,12 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
 #endif
              && ! side_effects_p (SET_SRC (temp1))
              && ! may_trap_p (SET_SRC (temp1))
-             && rtx_cost (SET_SRC (temp1)) < 10
+             && rtx_cost (SET_SRC (temp1), SET) < 10
              && (temp4 = single_set (temp3)) != 0
              && rtx_equal_p (SET_DEST (temp4), temp2)
              && ! side_effects_p (SET_SRC (temp4))
              && ! may_trap_p (SET_SRC (temp4))
-             && rtx_cost (SET_SRC (temp4)) < 10)
+             && rtx_cost (SET_SRC (temp4), SET) < 10)
            {
              rtx new = gen_reg_rtx (GET_MODE (temp2));
 
@@ -929,7 +1057,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
 
          /* Finally, handle the case where two insns are used to 
             compute EXP but a temporary register is used.  Here we must
-            ensure that the temporary register is not used anywhere else. */
+            ensure that the temporary register is not used anywhere else.  */
 
          if (! reload_completed
              && after_regscan
@@ -956,7 +1084,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
              && regno_last_uid[REGNO (temp5)] == INSN_UID (temp3)
              && ! side_effects_p (SET_SRC (temp1))
              && ! may_trap_p (SET_SRC (temp1))
-             && rtx_cost (SET_SRC (temp1)) < 10
+             && rtx_cost (SET_SRC (temp1), SET) < 10
              && (temp4 = single_set (temp3)) != 0
              && (temp2 = SET_DEST (temp4), GET_CODE (temp2) == REG)
              && GET_MODE_CLASS (GET_MODE (temp2)) == MODE_INT
@@ -966,7 +1094,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
              && rtx_equal_p (SET_DEST (temp4), temp2)
              && ! side_effects_p (SET_SRC (temp4))
              && ! may_trap_p (SET_SRC (temp4))
-             && rtx_cost (SET_SRC (temp4)) < 10)
+             && rtx_cost (SET_SRC (temp4), SET) < 10)
            {
              rtx new = gen_reg_rtx (GET_MODE (temp2));
 
@@ -984,26 +1112,23 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
            }
 #endif /* HAVE_cc0 */
 
-         /* We deal with four cases:
+         /* Try to use a conditional move (if the target has them), or a
+            store-flag insn.  The general case is:
 
-            1) x = a; if (...) x = b; and either A or B is zero,
-            2) if (...) x = 0; and jumps are expensive,
-            3) x = a; if (...) x = b; and A and B are constants where all the
-               set bits in A are also set in B and jumps are expensive, and
-            4) x = a; if (...) x = b; and A and B non-zero, and jumps are
-               more expensive.
-            5) if (...) x = b; if jumps are even more expensive.
+            1) x = a; if (...) x = b; and
+            2) if (...) x = b;
 
-            In each of these try to use a store-flag insn to avoid the jump.
-            (If the jump would be faster, the machine should not have
-            defined the scc insns!).  These cases are often made by the
+            If the jump would be faster, the machine should not have defined
+            the movcc or scc insns!.  These cases are often made by the
             previous optimization.
 
+            The second case is treated as  x = x; if (...) x = b;.
+
             INSN here is the jump around the store.  We set:
 
             TEMP to the "x = b;" insn.
             TEMP1 to X.
-            TEMP2 to B (const0_rtx in the second case).
+            TEMP2 to B.
             TEMP3 to A (X in the second case).
             TEMP4 to the condition being tested.
             TEMP5 to the earliest insn used to find the condition.  */
@@ -1019,25 +1144,18 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
 #ifdef SMALL_REGISTER_CLASSES
              && REGNO (temp1) >= FIRST_PSEUDO_REGISTER
 #endif
-             && GET_MODE_CLASS (GET_MODE (temp1)) == MODE_INT
              && (GET_CODE (temp2 = SET_SRC (PATTERN (temp))) == REG
                  || GET_CODE (temp2) == SUBREG
+                 /* ??? How about floating point constants?  */
                  || GET_CODE (temp2) == CONST_INT)
              /* Allow either form, but prefer the former if both apply. 
                 There is no point in using the old value of TEMP1 if
                 it is a register, since cse will alias them.  It can
                 lose if the old value were a hard register since CSE
                 won't replace hard registers.  */
-             && (((temp3 = reg_set_last (temp1, insn)) != 0
-                  && GET_CODE (temp3) == CONST_INT)
-                 /* Make the latter case look like  x = x; if (...) x = 0;  */
-                 || (temp3 = temp1,
-                     ((BRANCH_COST >= 2
-                       && temp2 == const0_rtx)
-#ifdef HAVE_conditional_move
-                      || 1
-#endif
-                      || BRANCH_COST >= 3)))
+             && (((temp3 = reg_set_last (temp1, insn)) != 0)
+                 /* Make the latter case look like  x = x; if (...) x = b;  */
+                 || (temp3 = temp1, 1))
              /* INSN must either branch to the insn after TEMP or the insn
                 after TEMP must branch to the same place as INSN.  */
              && (reallabelprev == temp
@@ -1049,25 +1167,9 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
                 We could handle BLKmode if (1) emit_store_flag could
                 and (2) we could find the size reliably.  */
              && GET_MODE (XEXP (temp4, 0)) != BLKmode
-
-             /* If B is zero, OK; if A is zero, can only do (1) if we
-                can reverse the condition.  See if (3) applies possibly
-                by reversing the condition.  Prefer reversing to (4) when
-                branches are very expensive.  */
-             && ((reversep = 0, temp2 == const0_rtx)
-                 || (temp3 == const0_rtx
-                     && (reversep = can_reverse_comparison_p (temp4, insn)))
-                 || (BRANCH_COST >= 2
-                     && GET_CODE (temp2) == CONST_INT
-                     && GET_CODE (temp3) == CONST_INT
-                     && ((INTVAL (temp2) & INTVAL (temp3)) == INTVAL (temp2)
-                         || ((INTVAL (temp2) & INTVAL (temp3)) == INTVAL (temp3)
-                             && (reversep = can_reverse_comparison_p (temp4,
-                                                                      insn)))))
-#ifdef HAVE_conditional_move
-                 || 1
-#endif
-                 || BRANCH_COST >= 3)
+             /* Even if branches are cheap, the store_flag optimization
+                can win when the operation to be performed can be
+                expressed directly.  */
 #ifdef HAVE_cc0
              /* If the previous insn sets CC0 and something else, we can't
                 do this since we are going to delete that insn.  */
@@ -1080,139 +1182,258 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
 #endif
              )
            {
-             enum rtx_code code = GET_CODE (temp4);
-             rtx uval, cval, var = temp1;
-             int normalizep;
-             rtx target;
-
-             /* If necessary, reverse the condition.  */
-             if (reversep)
-               code = reverse_condition (code), uval = temp2, cval = temp3;
-             else
-               uval = temp3, cval = temp2;
-
-             /* See if we can do this with a store-flag insn. */
-             start_sequence ();
+#ifdef HAVE_conditional_move
+             /* First try a conditional move.  */
+             {
+               enum rtx_code code = GET_CODE (temp4);
+               rtx var = temp1;
+               rtx cond0, cond1, aval, bval;
+               rtx target;
+
+               /* Copy the compared variables into cond0 and cond1, so that
+                  any side effects performed in or after the old comparison,
+                  will not affect our compare which will come later.  */
+               /* ??? Is it possible to just use the comparison in the jump
+                  insn?  After all, we're going to delete it.  We'd have
+                  to modify emit_conditional_move to take a comparison rtx
+                  instead or write a new function.  */
+               cond0 = gen_reg_rtx (GET_MODE (XEXP (temp4, 0)));
+               /* We want the target to be able to simplify comparisons with
+                  zero (and maybe other constants as well), so don't create
+                  pseudos for them.  There's no need to either.  */
+               if (GET_CODE (XEXP (temp4, 1)) == CONST_INT
+                   || GET_CODE (XEXP (temp4, 1)) == CONST_DOUBLE)
+                 cond1 = XEXP (temp4, 1);
+               else
+                 cond1 = gen_reg_rtx (GET_MODE (XEXP (temp4, 1)));
 
-             /* If CVAL is non-zero, normalize to -1.  Otherwise,
-                if UVAL is the constant 1, it is best to just compute
-                the result directly.  If UVAL is constant and STORE_FLAG_VALUE
-                includes all of its bits, it is best to compute the flag
-                value unnormalized and `and' it with UVAL.  Otherwise,
-                normalize to -1 and `and' with UVAL.  */
-             normalizep = (cval != const0_rtx ? -1
-                           : (uval == const1_rtx ? 1
-                              : (GET_CODE (uval) == CONST_INT
-                                 && (INTVAL (uval) & ~STORE_FLAG_VALUE) == 0)
-                              ? 0 : -1));
-
-             /* We will be putting the store-flag insn immediately in
-                front of the comparison that was originally being done,
-                so we know all the variables in TEMP4 will be valid.
-                However, this might be in front of the assignment of
-                A to VAR.  If it is, it would clobber the store-flag
-                we will be emitting.
-
-                Therefore, emit into a temporary which will be copied to
-                VAR immediately after TEMP.  */
-
-             target = emit_store_flag (gen_reg_rtx (GET_MODE (var)), code,
-                                       XEXP (temp4, 0), XEXP (temp4, 1),
-                                       VOIDmode,
-                                       (code == LTU || code == LEU 
-                                        || code == GEU || code == GTU),
-                                       normalizep);
-             if (target)
-               {
-                 rtx before = insn;
-                 rtx seq;
+               aval = temp3;
+               bval = temp2;
 
-                 /* Put the store-flag insns in front of the first insn
-                    used to compute the condition to ensure that we
-                    use the same values of them as the current 
-                    comparison.  However, the remainder of the insns we
-                    generate will be placed directly in front of the
-                    jump insn, in case any of the pseudos we use
-                    are modified earlier.  */
+               start_sequence ();
+               target = emit_conditional_move (var, code,
+                                               cond0, cond1, VOIDmode,
+                                               aval, bval, GET_MODE (var),
+                                               (code == LTU || code == GEU
+                                                || code == LEU || code == GTU));
 
-                 seq = get_insns ();
+               if (target)
+                 {
+                   rtx seq1,seq2;
+
+                   /* Save the conditional move sequence but don't emit it
+                      yet.  On some machines, like the alpha, it is possible
+                      that temp5 == insn, so next generate the sequence that
+                      saves the compared values and then emit both
+                      sequences ensuring seq1 occurs before seq2.  */
+                   seq2 = get_insns ();
+                   end_sequence ();
+
+                   /* Now that we can't fail, generate the copy insns that
+                      preserve the compared values.  */
+                   start_sequence ();
+                   emit_move_insn (cond0, XEXP (temp4, 0));
+                   if (cond1 != XEXP (temp4, 1))
+                     emit_move_insn (cond1, XEXP (temp4, 1));
+                   seq1 = get_insns ();
+                   end_sequence ();
+
+                   emit_insns_before (seq1, temp5);
+                   /* Insert conditional move after insn, to be sure that
+                      the jump and a possible compare won't be separated */
+                   emit_insns_after (seq2, insn);
+
+                   /* ??? We can also delete the insn that sets X to A.
+                      Flow will do it too though.  */
+                   delete_insn (temp);
+                   next = NEXT_INSN (insn);
+                   delete_jump (insn);
+                   changed = 1;
+                   continue;
+                 }
+               else
                  end_sequence ();
+             }
+#endif
 
-                 emit_insns_before (seq, temp5);
+             /* That didn't work, try a store-flag insn.
+
+                We further divide the cases into:
+
+                1) x = a; if (...) x = b; and either A or B is zero,
+                2) if (...) x = 0; and jumps are expensive,
+                3) x = a; if (...) x = b; and A and B are constants where all
+                the set bits in A are also set in B and jumps are expensive,
+                4) x = a; if (...) x = b; and A and B non-zero, and jumps are
+                more expensive, and
+                5) if (...) x = b; if jumps are even more expensive.  */
+
+             if (GET_MODE_CLASS (GET_MODE (temp1)) == MODE_INT
+                 && ((GET_CODE (temp3) == CONST_INT)
+                     /* Make the latter case look like
+                        x = x; if (...) x = 0;  */
+                     || (temp3 = temp1,
+                         ((BRANCH_COST >= 2
+                           && temp2 == const0_rtx)
+                          || BRANCH_COST >= 3)))
+                 /* If B is zero, OK; if A is zero, can only do (1) if we
+                    can reverse the condition.  See if (3) applies possibly
+                    by reversing the condition.  Prefer reversing to (4) when
+                    branches are very expensive.  */
+                 && (((BRANCH_COST >= 2
+                       || STORE_FLAG_VALUE == -1
+                       || (STORE_FLAG_VALUE == 1
+                        /* Check that the mask is a power of two,
+                           so that it can probably be generated
+                           with a shift.  */
+                           && exact_log2 (INTVAL (temp3)) >= 0))
+                      && (reversep = 0, temp2 == const0_rtx))
+                     || ((BRANCH_COST >= 2
+                          || STORE_FLAG_VALUE == -1
+                          || (STORE_FLAG_VALUE == 1
+                              && exact_log2 (INTVAL (temp2)) >= 0))
+                         && temp3 == const0_rtx
+                         && (reversep = can_reverse_comparison_p (temp4, insn)))
+                     || (BRANCH_COST >= 2
+                         && GET_CODE (temp2) == CONST_INT
+                         && GET_CODE (temp3) == CONST_INT
+                         && ((INTVAL (temp2) & INTVAL (temp3)) == INTVAL (temp2)
+                             || ((INTVAL (temp2) & INTVAL (temp3)) == INTVAL (temp3)
+                                 && (reversep = can_reverse_comparison_p (temp4,
+                                                                          insn)))))
+                     || BRANCH_COST >= 3)
+                 )
+               {
+                 enum rtx_code code = GET_CODE (temp4);
+                 rtx uval, cval, var = temp1;
+                 int normalizep;
+                 rtx target;
 
-                 start_sequence ();
+                 /* If necessary, reverse the condition.  */
+                 if (reversep)
+                   code = reverse_condition (code), uval = temp2, cval = temp3;
+                 else
+                   uval = temp3, cval = temp2;
+
+                 /* If CVAL is non-zero, normalize to -1.  Otherwise, if UVAL
+                    is the constant 1, it is best to just compute the result
+                    directly.  If UVAL is constant and STORE_FLAG_VALUE
+                    includes all of its bits, it is best to compute the flag
+                    value unnormalized and `and' it with UVAL.  Otherwise,
+                    normalize to -1 and `and' with UVAL.  */
+                 normalizep = (cval != const0_rtx ? -1
+                               : (uval == const1_rtx ? 1
+                                  : (GET_CODE (uval) == CONST_INT
+                                     && (INTVAL (uval) & ~STORE_FLAG_VALUE) == 0)
+                                  ? 0 : -1));
+
+                 /* We will be putting the store-flag insn immediately in
+                    front of the comparison that was originally being done,
+                    so we know all the variables in TEMP4 will be valid.
+                    However, this might be in front of the assignment of
+                    A to VAR.  If it is, it would clobber the store-flag
+                    we will be emitting.
+
+                    Therefore, emit into a temporary which will be copied to
+                    VAR immediately after TEMP.  */
 
-                 /* Both CVAL and UVAL are non-zero.  */
-                 if (cval != const0_rtx && uval != const0_rtx)
+                 start_sequence ();
+                 target = emit_store_flag (gen_reg_rtx (GET_MODE (var)), code,
+                                           XEXP (temp4, 0), XEXP (temp4, 1),
+                                           VOIDmode,
+                                           (code == LTU || code == LEU 
+                                            || code == GEU || code == GTU),
+                                           normalizep);
+                 if (target)
                    {
-                     rtx tem1, tem2;
+                     rtx seq;
+                     rtx before = insn;
 
-                     tem1 = expand_and (uval, target, NULL_RTX);
-                     if (GET_CODE (cval) == CONST_INT
-                         && GET_CODE (uval) == CONST_INT
-                         && (INTVAL (cval) & INTVAL (uval)) == INTVAL (cval))
-                       tem2 = cval;
-                     else
-                       {
-                         tem2 = expand_unop (GET_MODE (var), one_cmpl_optab,
-                                             target, NULL_RTX, 0);
-                         tem2 = expand_and (cval, tem2,
-                                            (GET_CODE (tem2) == REG
-                                             ? tem2 : 0));
-                       }
+                     seq = get_insns ();
+                     end_sequence ();
 
-                     /* If we usually make new pseudos, do so here.  This
-                        turns out to help machines that have conditional
-                        move insns.  */
+                     /* Put the store-flag insns in front of the first insn
+                        used to compute the condition to ensure that we
+                        use the same values of them as the current 
+                        comparison.  However, the remainder of the insns we
+                        generate will be placed directly in front of the
+                        jump insn, in case any of the pseudos we use
+                        are modified earlier.  */
 
-                     if (flag_expensive_optimizations)
-                       target = 0;
+                     emit_insns_before (seq, temp5);
 
-                     target = expand_binop (GET_MODE (var), ior_optab,
-                                            tem1, tem2, target,
-                                            1, OPTAB_WIDEN);
-                   }
-                 else if (normalizep != 1)
-                   {
-                     /* We know that either CVAL or UVAL is zero.  If
-                        UVAL is zero, negate TARGET and `and' with CVAL.
-                        Otherwise, `and' with UVAL.  */
-                     if (uval == const0_rtx)
+                     start_sequence ();
+
+                     /* Both CVAL and UVAL are non-zero.  */
+                     if (cval != const0_rtx && uval != const0_rtx)
                        {
-                         target = expand_unop (GET_MODE (var), one_cmpl_optab,
-                                               target, NULL_RTX, 0);
-                         uval = cval;
+                         rtx tem1, tem2;
+
+                         tem1 = expand_and (uval, target, NULL_RTX);
+                         if (GET_CODE (cval) == CONST_INT
+                             && GET_CODE (uval) == CONST_INT
+                             && (INTVAL (cval) & INTVAL (uval)) == INTVAL (cval))
+                           tem2 = cval;
+                         else
+                           {
+                             tem2 = expand_unop (GET_MODE (var), one_cmpl_optab,
+                                                 target, NULL_RTX, 0);
+                             tem2 = expand_and (cval, tem2,
+                                                (GET_CODE (tem2) == REG
+                                                 ? tem2 : 0));
+                           }
+
+                         /* If we usually make new pseudos, do so here.  This
+                            turns out to help machines that have conditional
+                            move insns.  */
+                         /* ??? Conditional moves have already been handled.
+                            This may be obsolete.  */
+
+                         if (flag_expensive_optimizations)
+                           target = 0;
+
+                         target = expand_binop (GET_MODE (var), ior_optab,
+                                                tem1, tem2, target,
+                                                1, OPTAB_WIDEN);
                        }
+                     else if (normalizep != 1)
+                       {
+                         /* We know that either CVAL or UVAL is zero.  If
+                            UVAL is zero, negate TARGET and `and' with CVAL.
+                            Otherwise, `and' with UVAL.  */
+                         if (uval == const0_rtx)
+                           {
+                             target = expand_unop (GET_MODE (var), one_cmpl_optab,
+                                                   target, NULL_RTX, 0);
+                             uval = cval;
+                           }
 
-                     target = expand_and (uval, target,
-                                          (GET_CODE (target) == REG
-                                           && ! preserve_subexpressions_p ()
-                                           ? target : NULL_RTX));
-                   }
+                         target = expand_and (uval, target,
+                                              (GET_CODE (target) == REG
+                                               && ! preserve_subexpressions_p ()
+                                               ? target : NULL_RTX));
+                       }
                  
-                 emit_move_insn (var, target);
-                 seq = get_insns ();
-                 end_sequence ();
-
+                     emit_move_insn (var, target);
+                     seq = get_insns ();
+                     end_sequence ();
 #ifdef HAVE_cc0
-                 /* If INSN uses CC0, we must not separate it from the
-                    insn that sets cc0.  */
-
-                 if (reg_mentioned_p (cc0_rtx, PATTERN (before)))
-                   before = prev_nonnote_insn (before);
+                     /* If INSN uses CC0, we must not separate it from the
+                        insn that sets cc0.  */
+                     if (reg_mentioned_p (cc0_rtx, PATTERN (before)))
+                       before = prev_nonnote_insn (before);
 #endif
+                     emit_insns_before (seq, before);
 
-                 emit_insns_before (seq, before);
-
-                 delete_insn (temp);
-                 next = NEXT_INSN (insn);
-
-                 delete_jump (insn);
-                 changed = 1;
-                 continue;
+                     delete_insn (temp);
+                     next = NEXT_INSN (insn);
+                     delete_jump (insn);
+                     changed = 1;
+                     continue;
+                   }
+                 else
+                   end_sequence ();
                }
-             else
-               end_sequence ();
            }
 
          /* If branches are expensive, convert
@@ -1245,6 +1466,8 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
              && (XEXP (SET_SRC (temp1), 1) == const1_rtx
                  || XEXP (SET_SRC (temp1), 1) == constm1_rtx)
              && rtx_equal_p (temp2, XEXP (SET_SRC (temp1), 0))
+             && ! side_effects_p (temp2)
+             && ! may_trap_p (temp2)
              /* INSN must either branch to the insn after TEMP or the insn
                 after TEMP must branch to the same place as INSN.  */
              && (reallabelprev == temp
@@ -1413,7 +1636,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
                  else if (ultimate && GET_CODE (ultimate) != RETURN)
                    ultimate = XEXP (ultimate, 0);
 
-                 if (ultimate)
+                 if (ultimate && JUMP_LABEL(insn) != ultimate)
                    changed |= redirect_jump (insn, ultimate);
                }
            }
@@ -1644,7 +1867,8 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
            }
          /* Detect a conditional jump jumping over an unconditional jump.  */
 
-         else if (this_is_condjump && ! this_is_simplejump
+         else if ((this_is_condjump || this_is_condjump_in_parallel)
+                  && ! this_is_simplejump
                   && reallabelprev != 0
                   && GET_CODE (reallabelprev) == JUMP_INSN
                   && prev_active_insn (reallabelprev) == insn
@@ -1746,6 +1970,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
                        rtx range2beg = next_active_insn (label1);
                        rtx range1after, range2after;
                        rtx range1before, range2before;
+                       rtx rangenext;
 
                        /* Include in each range any notes before it, to be
                           sure that we get the line number note if any, even
@@ -1779,6 +2004,41 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
                        PREV_INSN (range1beg) = range2before;
                        NEXT_INSN (range1end) = range2after;
                        PREV_INSN (range2after) = range1end;
+
+                       /* Check for a loop end note between the end of
+                          range2, and the next code label.  If there is one,
+                          then what we have really seen is
+                          if (foo) break; end_of_loop;
+                          and moved the break sequence outside the loop.
+                          We must move the LOOP_END note to where the
+                          loop really ends now, or we will confuse loop
+                          optimization.  Stop if we find a LOOP_BEG note
+                          first, since we don't want to move the LOOP_END
+                          note in that case.  */
+                       for (;range2after != label2; range2after = rangenext)
+                         {
+                           rangenext = NEXT_INSN (range2after);
+                           if (GET_CODE (range2after) == NOTE)
+                             {
+                               if (NOTE_LINE_NUMBER (range2after)
+                                   == NOTE_INSN_LOOP_END)
+                                 {
+                                   NEXT_INSN (PREV_INSN (range2after))
+                                     = rangenext;
+                                   PREV_INSN (rangenext)
+                                     = PREV_INSN (range2after);
+                                   PREV_INSN (range2after) 
+                                     = PREV_INSN (range1beg);
+                                   NEXT_INSN (range2after) = range1beg;
+                                   NEXT_INSN (PREV_INSN (range1beg))
+                                     = range2after;
+                                   PREV_INSN (range1beg) = range2after;
+                                 }
+                               else if (NOTE_LINE_NUMBER (range2after)
+                                        == NOTE_INSN_LOOP_BEG)
+                                 break;
+                             }
+                         }
                        changed = 1;
                        continue;
                      }
@@ -1787,7 +2047,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
 
              /* Now that the jump has been tensioned,
                 try cross jumping: check for identical code
-                before the jump and before its target label. */
+                before the jump and before its target label.  */
 
              /* First, cross jumping of conditional jumps:  */
 
@@ -1822,7 +2082,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
                      INSN_CODE (insn) = -1;
                      emit_barrier_after (insn);
                      /* Add to jump_chain unless this is a new label
-                        whose UID is too large. */
+                        whose UID is too large.  */
                      if (INSN_UID (JUMP_LABEL (insn)) < max_jump_chain)
                        {
                          jump_chain[INSN_UID (insn)]
@@ -1967,6 +2227,8 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
                  then one of them follows the note.  */
               || (GET_CODE (insn) == JUMP_INSN
                   && GET_CODE (PATTERN (insn)) == RETURN)
+              /* A barrier can follow the return insn.  */
+              || GET_CODE (insn) == BARRIER
               /* Other kinds of notes can follow also.  */
               || (GET_CODE (insn) == NOTE
                   && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END)))
@@ -1991,12 +2253,6 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
    followed by a jump to the exit of the loop.  Then delete the unconditional
    jump after INSN.
 
-   Note that it is possible we can get confused here if the jump immediately
-   after the loop start branches outside the loop but within an outer loop.
-   If we are near the exit of that loop, we will copy its exit test.  This
-   will not generate incorrect code, but could suppress some optimizations.
-   However, such cases are degenerate loops anyway.
-
    Return 1 if we made the change, else 0.
 
    This is only safe immediately after a regscan pass because it uses the
@@ -2006,8 +2262,8 @@ static int
 duplicate_loop_exit_test (loop_start)
      rtx loop_start;
 {
-  rtx insn, set, p;
-  rtx copy, link;
+  rtx insn, set, reg, p, link;
+  rtx copy = 0;
   int num_insns = 0;
   rtx exitcode = NEXT_INSN (JUMP_LABEL (next_nonnote_insn (loop_start)));
   rtx lastexit;
@@ -2037,9 +2293,19 @@ duplicate_loop_exit_test (loop_start)
        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_BLOCK_BEG
-             || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
+             || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END
+             || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_CONT)
            return 0;
          break;
        case JUMP_INSN:
@@ -2063,12 +2329,14 @@ duplicate_loop_exit_test (loop_start)
   for (insn = exitcode; insn != lastexit; insn = NEXT_INSN (insn))
     if (GET_CODE (insn) == INSN
        && (set = single_set (insn)) != 0
-       && GET_CODE (SET_DEST (set)) == REG
-       && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
-       && regno_first_uid[REGNO (SET_DEST (set))] == INSN_UID (insn))
+       && ((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 (SET_DEST (set))] == INSN_UID (p))
+         if (regno_last_uid[REGNO (reg)] == INSN_UID (p))
            break;
 
        if (p != lastexit)
@@ -2078,13 +2346,12 @@ duplicate_loop_exit_test (loop_start)
            if (reg_map == 0)
              {
                reg_map = (rtx *) alloca (max_reg * sizeof (rtx));
-               bzero (reg_map, max_reg * sizeof (rtx));
+               bzero ((char *) reg_map, max_reg * sizeof (rtx));
              }
 
-           REG_LOOP_TEST_P (SET_DEST (set)) = 1;
+           REG_LOOP_TEST_P (reg) = 1;
 
-           reg_map[REGNO (SET_DEST (set))]
-             = gen_reg_rtx (GET_MODE (SET_DEST (set)));
+           reg_map[REGNO (reg)] = gen_reg_rtx (GET_MODE (reg));
          }
       }
 
@@ -2151,7 +2418,7 @@ duplicate_loop_exit_test (loop_start)
 
   /* Now clean up by emitting a jump to the end label and deleting the jump
      at the start of the loop.  */
-  if (GET_CODE (copy) != BARRIER)
+  if (! copy || GET_CODE (copy) != BARRIER)
     {
       copy = emit_jump_insn_before (gen_jump (get_label_after (insn)),
                                    loop_start);
@@ -2166,11 +2433,11 @@ duplicate_loop_exit_test (loop_start)
       emit_barrier_before (loop_start);
     }
 
-  delete_insn (next_nonnote_insn (loop_start));
-
   /* Mark the exit code as the virtual top of the converted loop.  */
   emit_note_before (NOTE_INSN_LOOP_VTOP, exitcode);
 
+  delete_insn (next_nonnote_insn (loop_start));
+
   return 1;
 }
 \f
@@ -2297,13 +2564,13 @@ find_cross_jump (e1, e2, minimum, f1, f2)
 #ifdef STACK_REGS
       /* If cross_jump_death_matters is not 0, the insn's mode
         indicates whether or not the insn contains any stack-like
-        regs. */
+        regs.  */
 
       if (!lose && cross_jump_death_matters && GET_MODE (i1) == QImode)
        {
          /* If register stack conversion has already been done, then
             death notes must also be compared before it is certain that
-            the two instruction streams match. */
+            the two instruction streams match.  */
 
          rtx note;
          HARD_REG_SET i1_regset, i2_regset;
@@ -2830,6 +3097,39 @@ condjump_p (insn)
   return 0;
 }
 
+/* Return nonzero if INSN is a (possibly) conditional jump
+   and nothing more.  */
+
+int
+condjump_in_parallel_p (insn)
+     rtx insn;
+{
+  register rtx x = PATTERN (insn);
+
+  if (GET_CODE (x) != PARALLEL)
+    return 0;
+  else
+    x = XVECEXP (x, 0, 0);
+
+  if (GET_CODE (x) != SET)
+    return 0;
+  if (GET_CODE (SET_DEST (x)) != PC)
+    return 0;
+  if (GET_CODE (SET_SRC (x)) == LABEL_REF)
+    return 1;
+  if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE)
+    return 0;
+  if (XEXP (SET_SRC (x), 2) == pc_rtx
+      && (GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF
+         || GET_CODE (XEXP (SET_SRC (x), 1)) == RETURN))
+    return 1;
+  if (XEXP (SET_SRC (x), 1) == pc_rtx
+      && (GET_CODE (XEXP (SET_SRC (x), 2)) == LABEL_REF
+         || GET_CODE (XEXP (SET_SRC (x), 2)) == RETURN))
+    return 1;
+  return 0;
+}
+
 /* Return 1 if X is an RTX that does nothing but set the condition codes
    and CLOBBER or USE registers.
    Return -1 if X does explicitly set the condition codes,
@@ -2885,7 +3185,8 @@ follow_jumps (label)
        (depth < 10
        && (insn = next_active_insn (value)) != 0
        && GET_CODE (insn) == JUMP_INSN
-       && (JUMP_LABEL (insn) != 0 || GET_CODE (PATTERN (insn)) == RETURN)
+       && ((JUMP_LABEL (insn) != 0 && simplejump_p (insn))
+           || GET_CODE (PATTERN (insn)) == RETURN)
        && (next = NEXT_INSN (insn))
        && GET_CODE (next) == BARRIER);
        depth++)
@@ -3305,6 +3606,24 @@ delete_insn (insn)
        return next;
       }
 
+  /* Likewise if we're deleting a dispatch table.  */
+
+  if (GET_CODE (insn) == JUMP_INSN
+      && (GET_CODE (PATTERN (insn)) == ADDR_VEC
+         || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
+    {
+      rtx pat = PATTERN (insn);
+      int i, diff_vec_p = GET_CODE (pat) == ADDR_DIFF_VEC;
+      int len = XVECLEN (pat, diff_vec_p);
+
+      for (i = 0; i < len; i++)
+       if (--LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0)) == 0)
+         delete_insn (XEXP (XVECEXP (pat, diff_vec_p, i), 0));
+      while (next && INSN_DELETED_P (next))
+       next = NEXT_INSN (next);
+      return next;
+    }
+
   while (prev && (INSN_DELETED_P (prev) || GET_CODE (prev) == NOTE))
     prev = PREV_INSN (prev);
 
@@ -3326,7 +3645,7 @@ delete_insn (insn)
       register RTX_CODE code;
       while (next != 0
             && (GET_RTX_CLASS (code = GET_CODE (next)) == 'i'
-                || code == NOTE
+                || code == NOTE || code == BARRIER
                 || (code == CODE_LABEL && INSN_DELETED_P (next))))
        {
          if (code == NOTE
@@ -4015,7 +4334,8 @@ thread_jumps (f, max_reg, flag_before_loop)
          bzero (modified_regs, max_reg * sizeof (char));
          modified_mem = 0;
 
-         bcopy (all_reset, same_regs, max_reg * sizeof (int));
+         bcopy ((char *) all_reset, (char *) same_regs,
+                max_reg * sizeof (int));
          num_same_regs = 0;
 
          label = JUMP_LABEL (b1);
@@ -4225,7 +4545,7 @@ rtx_equal_for_thread_p (x, y, yinsn)
 
     case MEM:
       /* If memory modified or either volatile, not equivalent.
-        Else, check address. */
+        Else, check address.  */
       if (modified_mem || MEM_VOLATILE_P (x) || MEM_VOLATILE_P (y))
        return 0;