OSDN Git Service

* config/alpha/alpha.c (alpha_sa_size): Force procedure type to
[pf3gnuchains/gcc-fork.git] / gcc / recog.c
index 1b81704..138b03b 100644 (file)
@@ -1,13 +1,13 @@
 /* Subroutines used by or related to instruction recognition.
    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 
 #include "config.h"
@@ -41,8 +40,10 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "basic-block.h"
 #include "output.h"
 #include "reload.h"
+#include "target.h"
 #include "timevar.h"
 #include "tree-pass.h"
+#include "df.h"
 
 #ifndef STACK_PUSH_CODE
 #ifdef STACK_GROWS_DOWNWARD
@@ -60,8 +61,15 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #endif
 #endif
 
-static void validate_replace_rtx_1 (rtx *, rtx, rtx, rtx);
-static rtx *find_single_use_1 (rtx, rtx *);
+#ifndef HAVE_ATTR_enabled
+static inline bool
+get_attr_enabled (rtx insn ATTRIBUTE_UNUSED)
+{
+  return true;
+}
+#endif
+
+static void validate_replace_rtx_1 (rtx *, rtx, rtx, rtx, bool);
 static void validate_replace_src_1 (rtx *, void *);
 static rtx split_insn (rtx);
 
@@ -69,7 +77,7 @@ static rtx split_insn (rtx);
    This should be 0 if you are generating rtl, such as if you are calling
    the functions in optabs.c and expmed.c (most of the time).
    This should be 1 if all valid insns need to be recognized,
-   such as in regclass.c and final.c and reload.c.
+   such as in reginfo.c and final.c and reload.c.
 
    init_recog and init_recog_no_volatile are responsible for setting this.  */
 
@@ -138,8 +146,8 @@ check_asm_operands (rtx x)
   if (noperands == 0)
     return 1;
 
-  operands = alloca (noperands * sizeof (rtx));
-  constraints = alloca (noperands * sizeof (char *));
+  operands = XALLOCAVEC (rtx, noperands);
+  constraints = XALLOCAVEC (const char *, noperands);
 
   decode_asm_operands (x, operands, NULL, constraints, NULL, NULL);
 
@@ -148,10 +156,7 @@ check_asm_operands (rtx x)
       const char *c = constraints[i];
       if (c[0] == '%')
        c++;
-      if (ISDIGIT ((unsigned char) c[0]) && c[1] == '\0')
-       c = constraints[c[0] - '0'];
-
-      if (! asm_operand_ok (operands[i], c))
+      if (! asm_operand_ok (operands[i], c, constraints))
        return 0;
     }
 
@@ -166,6 +171,7 @@ typedef struct change_t
   int old_code;
   rtx *loc;
   rtx old;
+  bool unshare;
 } change_t;
 
 static change_t *changes;
@@ -174,7 +180,7 @@ static int changes_allocated;
 static int num_changes = 0;
 
 /* Validate a proposed change to OBJECT.  LOC is the location in the rtl
-   at which NEW will be placed.  If OBJECT is zero, no validation is done,
+   at which NEW_RTX will be placed.  If OBJECT is zero, no validation is done,
    the change is simply made.
 
    Two types of objects are supported:  If OBJECT is a MEM, memory_address_p
@@ -191,17 +197,17 @@ static int num_changes = 0;
    is not valid for the machine, suppress the change and return zero.
    Otherwise, perform the change and return 1.  */
 
-int
-validate_change (rtx object, rtx *loc, rtx new, int in_group)
+static bool
+validate_change_1 (rtx object, rtx *loc, rtx new_rtx, bool in_group, bool unshare)
 {
   rtx old = *loc;
 
-  if (old == new || rtx_equal_p (old, new))
+  if (old == new_rtx || rtx_equal_p (old, new_rtx))
     return 1;
 
   gcc_assert (in_group != 0 || num_changes == 0);
 
-  *loc = new;
+  *loc = new_rtx;
 
   /* Save the information describing this change.  */
   if (num_changes >= changes_allocated)
@@ -213,12 +219,13 @@ validate_change (rtx object, rtx *loc, rtx new, int in_group)
       else
        changes_allocated *= 2;
 
-      changes = xrealloc (changes, sizeof (change_t) * changes_allocated);
+      changes = XRESIZEVEC (change_t, changes, changes_allocated);
     }
 
   changes[num_changes].object = object;
   changes[num_changes].loc = loc;
   changes[num_changes].old = old;
+  changes[num_changes].unshare = unshare;
 
   if (object && !MEM_P (object))
     {
@@ -239,6 +246,25 @@ validate_change (rtx object, rtx *loc, rtx new, int in_group)
     return apply_change_group ();
 }
 
+/* Wrapper for validate_change_1 without the UNSHARE argument defaulting
+   UNSHARE to false.  */
+
+bool
+validate_change (rtx object, rtx *loc, rtx new_rtx, bool in_group)
+{
+  return validate_change_1 (object, loc, new_rtx, in_group, false);
+}
+
+/* Wrapper for validate_change_1 without the UNSHARE argument defaulting
+   UNSHARE to true.  */
+
+bool
+validate_unshare_change (rtx object, rtx *loc, rtx new_rtx, bool in_group)
+{
+  return validate_change_1 (object, loc, new_rtx, in_group, true);
+}
+
+
 /* Keep X canonicalized if some changes have made it non-canonical; only
    modifies the operands of X, not (for example) its code.  Simplifications
    are not the job of this routine.
@@ -353,6 +379,16 @@ verify_changes (int num)
          if (! memory_address_p (GET_MODE (object), XEXP (object, 0)))
            break;
        }
+      else if (REG_P (changes[i].old)
+              && asm_noperands (PATTERN (object)) > 0
+              && REG_EXPR (changes[i].old) != NULL_TREE
+              && DECL_ASSEMBLER_NAME_SET_P (REG_EXPR (changes[i].old))
+              && DECL_REGISTER (REG_EXPR (changes[i].old)))
+       {
+         /* Don't allow changes of hard register operands to inline
+            assemblies if they have been defined as register asm ("x").  */
+         break;
+       }
       else if (insn_invalid_p (object))
        {
          rtx pat = PATTERN (object);
@@ -406,22 +442,35 @@ verify_changes (int num)
   return (i == num_changes);
 }
 
-/* A group of changes has previously been issued with validate_change and
-   verified with verify_changes.  Update the BB_DIRTY flags of the affected
-   blocks, and clear num_changes.  */
+/* A group of changes has previously been issued with validate_change
+   and verified with verify_changes.  Call df_insn_rescan for each of
+   the insn changed and clear num_changes.  */
 
 void
 confirm_change_group (void)
 {
   int i;
-  basic_block bb;
+  rtx last_object = NULL;
 
   for (i = 0; i < num_changes; i++)
-    if (changes[i].object
-       && INSN_P (changes[i].object)
-       && (bb = BLOCK_FOR_INSN (changes[i].object)))
-      bb->flags |= BB_DIRTY;
+    {
+      rtx object = changes[i].object;
+
+      if (changes[i].unshare)
+       *changes[i].loc = copy_rtx (*changes[i].loc);
 
+      /* Avoid unnecessary rescanning when multiple changes to same instruction
+         are made.  */
+      if (object)
+       {
+         if (object != last_object && last_object && INSN_P (last_object))
+           df_insn_rescan (last_object);
+         last_object = object;
+       }
+    }
+
+  if (last_object && INSN_P (last_object))
+    df_insn_rescan (last_object);
   num_changes = 0;
 }
 
@@ -471,96 +520,25 @@ cancel_changes (int num)
   num_changes = num;
 }
 
-/* Replace every occurrence of FROM in X with TO.  Mark each change with
-   validate_change passing OBJECT.  */
+/* A subroutine of validate_replace_rtx_1 that tries to simplify the resulting
+   rtx.  */
 
 static void
-validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object)
+simplify_while_replacing (rtx *loc, rtx to, rtx object, 
+                          enum machine_mode op0_mode)
 {
-  int i, j;
-  const char *fmt;
   rtx x = *loc;
-  enum rtx_code code;
-  enum machine_mode op0_mode = VOIDmode;
-  int prev_changes = num_changes;
-  rtx new;
-
-  if (!x)
-    return;
-
-  code = GET_CODE (x);
-  fmt = GET_RTX_FORMAT (code);
-  if (fmt[0] == 'e')
-    op0_mode = GET_MODE (XEXP (x, 0));
-
-  /* X matches FROM if it is the same rtx or they are both referring to the
-     same register in the same mode.  Avoid calling rtx_equal_p unless the
-     operands look similar.  */
-
-  if (x == from
-      || (REG_P (x) && REG_P (from)
-         && GET_MODE (x) == GET_MODE (from)
-         && REGNO (x) == REGNO (from))
-      || (GET_CODE (x) == GET_CODE (from) && GET_MODE (x) == GET_MODE (from)
-         && rtx_equal_p (x, from)))
-    {
-      validate_change (object, loc, to, 1);
-      return;
-    }
-
-  /* Call ourself recursively to perform the replacements.
-     We must not replace inside already replaced expression, otherwise we
-     get infinite recursion for replacements like (reg X)->(subreg (reg X))
-     done by regmove, so we must special case shared ASM_OPERANDS.  */
-
-  if (GET_CODE (x) == PARALLEL)
-    {
-      for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
-       {
-         if (j && GET_CODE (XVECEXP (x, 0, j)) == SET
-             && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == ASM_OPERANDS)
-           {
-             /* Verify that operands are really shared.  */
-             gcc_assert (ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (x, 0, 0)))
-                         == ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP
-                                                             (x, 0, j))));
-             validate_replace_rtx_1 (&SET_DEST (XVECEXP (x, 0, j)),
-                                     from, to, object);
-           }
-         else
-           validate_replace_rtx_1 (&XVECEXP (x, 0, j), from, to, object);
-       }
-    }
-  else
-    for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-      {
-       if (fmt[i] == 'e')
-         validate_replace_rtx_1 (&XEXP (x, i), from, to, object);
-       else if (fmt[i] == 'E')
-         for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-           validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object);
-      }
-
-  /* If we didn't substitute, there is nothing more to do.  */
-  if (num_changes == prev_changes)
-    return;
-
-  /* Allow substituted expression to have different mode.  This is used by
-     regmove to change mode of pseudo register.  */
-  if (fmt[0] == 'e' && GET_MODE (XEXP (x, 0)) != VOIDmode)
-    op0_mode = GET_MODE (XEXP (x, 0));
-
-  /* Do changes needed to keep rtx consistent.  Don't do any other
-     simplifications, as it is not our job.  */
+  enum rtx_code code = GET_CODE (x);
+  rtx new_rtx;
 
   if (SWAPPABLE_OPERANDS_P (x)
       && swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
     {
-      validate_change (object, loc,
-                      gen_rtx_fmt_ee (COMMUTATIVE_ARITH_P (x) ? code
-                                      : swap_condition (code),
-                                      GET_MODE (x), XEXP (x, 1),
-                                      XEXP (x, 0)), 1);
+      validate_unshare_change (object, loc,
+                              gen_rtx_fmt_ee (COMMUTATIVE_ARITH_P (x) ? code
+                                              : swap_condition (code),
+                                              GET_MODE (x), XEXP (x, 1),
+                                              XEXP (x, 0)), 1);
       x = *loc;
       code = GET_CODE (x);
     }
@@ -572,13 +550,13 @@ validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object)
          simplify_gen_binary to try to simplify it.
          ??? We may want later to remove this, once simplification is
          separated from this function.  */
-      if (GET_CODE (XEXP (x, 1)) == CONST_INT && XEXP (x, 1) == to)
+      if (CONST_INT_P (XEXP (x, 1)) && XEXP (x, 1) == to)
        validate_change (object, loc,
                         simplify_gen_binary
                         (PLUS, GET_MODE (x), XEXP (x, 0), XEXP (x, 1)), 1);
       break;
     case MINUS:
-      if (GET_CODE (XEXP (x, 1)) == CONST_INT
+      if (CONST_INT_P (XEXP (x, 1))
          || GET_CODE (XEXP (x, 1)) == CONST_DOUBLE)
        validate_change (object, loc,
                         simplify_gen_binary
@@ -591,25 +569,25 @@ validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object)
     case SIGN_EXTEND:
       if (GET_MODE (XEXP (x, 0)) == VOIDmode)
        {
-         new = simplify_gen_unary (code, GET_MODE (x), XEXP (x, 0),
+         new_rtx = simplify_gen_unary (code, GET_MODE (x), XEXP (x, 0),
                                    op0_mode);
          /* If any of the above failed, substitute in something that
             we know won't be recognized.  */
-         if (!new)
-           new = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
-         validate_change (object, loc, new, 1);
+         if (!new_rtx)
+           new_rtx = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
+         validate_change (object, loc, new_rtx, 1);
        }
       break;
     case SUBREG:
       /* All subregs possible to simplify should be simplified.  */
-      new = simplify_subreg (GET_MODE (x), SUBREG_REG (x), op0_mode,
+      new_rtx = simplify_subreg (GET_MODE (x), SUBREG_REG (x), op0_mode,
                             SUBREG_BYTE (x));
 
       /* Subregs of VOIDmode operands are incorrect.  */
-      if (!new && GET_MODE (SUBREG_REG (x)) == VOIDmode)
-       new = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
-      if (new)
-       validate_change (object, loc, new, 1);
+      if (!new_rtx && GET_MODE (SUBREG_REG (x)) == VOIDmode)
+       new_rtx = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
+      if (new_rtx)
+       validate_change (object, loc, new_rtx, 1);
       break;
     case ZERO_EXTRACT:
     case SIGN_EXTRACT:
@@ -619,8 +597,8 @@ validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object)
          happen, we might just fail in some cases).  */
 
       if (MEM_P (XEXP (x, 0))
-         && GET_CODE (XEXP (x, 1)) == CONST_INT
-         && GET_CODE (XEXP (x, 2)) == CONST_INT
+         && CONST_INT_P (XEXP (x, 1))
+         && CONST_INT_P (XEXP (x, 2))
          && !mode_dependent_address_p (XEXP (XEXP (x, 0), 0))
          && !MEM_VOLATILE_P (XEXP (x, 0)))
        {
@@ -673,22 +651,143 @@ validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object)
     }
 }
 
+/* Replace every occurrence of FROM in X with TO.  Mark each change with
+   validate_change passing OBJECT.  */
+
+static void
+validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object, 
+                        bool simplify)
+{
+  int i, j;
+  const char *fmt;
+  rtx x = *loc;
+  enum rtx_code code;
+  enum machine_mode op0_mode = VOIDmode;
+  int prev_changes = num_changes;
+
+  if (!x)
+    return;
+
+  code = GET_CODE (x);
+  fmt = GET_RTX_FORMAT (code);
+  if (fmt[0] == 'e')
+    op0_mode = GET_MODE (XEXP (x, 0));
+
+  /* X matches FROM if it is the same rtx or they are both referring to the
+     same register in the same mode.  Avoid calling rtx_equal_p unless the
+     operands look similar.  */
+
+  if (x == from
+      || (REG_P (x) && REG_P (from)
+         && GET_MODE (x) == GET_MODE (from)
+         && REGNO (x) == REGNO (from))
+      || (GET_CODE (x) == GET_CODE (from) && GET_MODE (x) == GET_MODE (from)
+         && rtx_equal_p (x, from)))
+    {
+      validate_unshare_change (object, loc, to, 1);
+      return;
+    }
+
+  /* Call ourself recursively to perform the replacements.
+     We must not replace inside already replaced expression, otherwise we
+     get infinite recursion for replacements like (reg X)->(subreg (reg X))
+     done by regmove, so we must special case shared ASM_OPERANDS.  */
+
+  if (GET_CODE (x) == PARALLEL)
+    {
+      for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
+       {
+         if (j && GET_CODE (XVECEXP (x, 0, j)) == SET
+             && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == ASM_OPERANDS)
+           {
+             /* Verify that operands are really shared.  */
+             gcc_assert (ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (x, 0, 0)))
+                         == ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP
+                                                             (x, 0, j))));
+             validate_replace_rtx_1 (&SET_DEST (XVECEXP (x, 0, j)),
+                                     from, to, object, simplify);
+           }
+         else
+           validate_replace_rtx_1 (&XVECEXP (x, 0, j), from, to, object, 
+                                    simplify);
+       }
+    }
+  else
+    for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+      {
+       if (fmt[i] == 'e')
+         validate_replace_rtx_1 (&XEXP (x, i), from, to, object, simplify);
+       else if (fmt[i] == 'E')
+         for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+           validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object, 
+                                    simplify);
+      }
+
+  /* If we didn't substitute, there is nothing more to do.  */
+  if (num_changes == prev_changes)
+    return;
+
+  /* Allow substituted expression to have different mode.  This is used by
+     regmove to change mode of pseudo register.  */
+  if (fmt[0] == 'e' && GET_MODE (XEXP (x, 0)) != VOIDmode)
+    op0_mode = GET_MODE (XEXP (x, 0));
+
+  /* Do changes needed to keep rtx consistent.  Don't do any other
+     simplifications, as it is not our job.  */
+  if (simplify)
+    simplify_while_replacing (loc, to, object, op0_mode);
+}
+
+/* Try replacing every occurrence of FROM in subexpression LOC of INSN
+   with TO.  After all changes have been made, validate by seeing
+   if INSN is still valid.  */
+
+int
+validate_replace_rtx_subexp (rtx from, rtx to, rtx insn, rtx *loc)
+{
+  validate_replace_rtx_1 (loc, from, to, insn, true);
+  return apply_change_group ();
+}
+
 /* Try replacing every occurrence of FROM in INSN with TO.  After all
    changes have been made, validate by seeing if INSN is still valid.  */
 
 int
 validate_replace_rtx (rtx from, rtx to, rtx insn)
 {
-  validate_replace_rtx_1 (&PATTERN (insn), from, to, insn);
+  validate_replace_rtx_1 (&PATTERN (insn), from, to, insn, true);
   return apply_change_group ();
 }
 
+/* Try replacing every occurrence of FROM in WHERE with TO.  Assume that WHERE
+   is a part of INSN.  After all changes have been made, validate by seeing if 
+   INSN is still valid.  
+   validate_replace_rtx (from, to, insn) is equivalent to 
+   validate_replace_rtx_part (from, to, &PATTERN (insn), insn).  */
+
+int
+validate_replace_rtx_part (rtx from, rtx to, rtx *where, rtx insn)
+{
+  validate_replace_rtx_1 (where, from, to, insn, true);
+  return apply_change_group ();
+}
+
+/* Same as above, but do not simplify rtx afterwards.  */
+int 
+validate_replace_rtx_part_nosimplify (rtx from, rtx to, rtx *where, 
+                                      rtx insn)
+{
+  validate_replace_rtx_1 (where, from, to, insn, false);
+  return apply_change_group ();
+
+}
+
 /* Try replacing every occurrence of FROM in INSN with TO.  */
 
 void
 validate_replace_rtx_group (rtx from, rtx to, rtx insn)
 {
-  validate_replace_rtx_1 (&PATTERN (insn), from, to, insn);
+  validate_replace_rtx_1 (&PATTERN (insn), from, to, insn, true);
 }
 
 /* Function called by note_uses to replace used subexpressions.  */
@@ -705,7 +804,7 @@ validate_replace_src_1 (rtx *x, void *data)
   struct validate_replace_src_data *d
     = (struct validate_replace_src_data *) data;
 
-  validate_replace_rtx_1 (x, d->from, d->to, d->insn);
+  validate_replace_rtx_1 (x, d->from, d->to, d->insn, true);
 }
 
 /* Try replacing every occurrence of FROM in INSN with TO, avoiding
@@ -781,168 +880,6 @@ next_insn_tests_no_inequality (rtx insn)
 }
 #endif
 \f
-/* This is used by find_single_use to locate an rtx that contains exactly one
-   use of DEST, which is typically either a REG or CC0.  It returns a
-   pointer to the innermost rtx expression containing DEST.  Appearances of
-   DEST that are being used to totally replace it are not counted.  */
-
-static rtx *
-find_single_use_1 (rtx dest, rtx *loc)
-{
-  rtx x = *loc;
-  enum rtx_code code = GET_CODE (x);
-  rtx *result = 0;
-  rtx *this_result;
-  int i;
-  const char *fmt;
-
-  switch (code)
-    {
-    case CONST_INT:
-    case CONST:
-    case LABEL_REF:
-    case SYMBOL_REF:
-    case CONST_DOUBLE:
-    case CONST_VECTOR:
-    case CLOBBER:
-      return 0;
-
-    case SET:
-      /* If the destination is anything other than CC0, PC, a REG or a SUBREG
-        of a REG that occupies all of the REG, the insn uses DEST if
-        it is mentioned in the destination or the source.  Otherwise, we
-        need just check the source.  */
-      if (GET_CODE (SET_DEST (x)) != CC0
-         && GET_CODE (SET_DEST (x)) != PC
-         && !REG_P (SET_DEST (x))
-         && ! (GET_CODE (SET_DEST (x)) == SUBREG
-               && REG_P (SUBREG_REG (SET_DEST (x)))
-               && (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x))))
-                     + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
-                   == ((GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
-                        + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))))
-       break;
-
-      return find_single_use_1 (dest, &SET_SRC (x));
-
-    case MEM:
-    case SUBREG:
-      return find_single_use_1 (dest, &XEXP (x, 0));
-
-    default:
-      break;
-    }
-
-  /* If it wasn't one of the common cases above, check each expression and
-     vector of this code.  Look for a unique usage of DEST.  */
-
-  fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    {
-      if (fmt[i] == 'e')
-       {
-         if (dest == XEXP (x, i)
-             || (REG_P (dest) && REG_P (XEXP (x, i))
-                 && REGNO (dest) == REGNO (XEXP (x, i))))
-           this_result = loc;
-         else
-           this_result = find_single_use_1 (dest, &XEXP (x, i));
-
-         if (result == 0)
-           result = this_result;
-         else if (this_result)
-           /* Duplicate usage.  */
-           return 0;
-       }
-      else if (fmt[i] == 'E')
-       {
-         int j;
-
-         for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-           {
-             if (XVECEXP (x, i, j) == dest
-                 || (REG_P (dest)
-                     && REG_P (XVECEXP (x, i, j))
-                     && REGNO (XVECEXP (x, i, j)) == REGNO (dest)))
-               this_result = loc;
-             else
-               this_result = find_single_use_1 (dest, &XVECEXP (x, i, j));
-
-             if (result == 0)
-               result = this_result;
-             else if (this_result)
-               return 0;
-           }
-       }
-    }
-
-  return result;
-}
-\f
-/* See if DEST, produced in INSN, is used only a single time in the
-   sequel.  If so, return a pointer to the innermost rtx expression in which
-   it is used.
-
-   If PLOC is nonzero, *PLOC is set to the insn containing the single use.
-
-   This routine will return usually zero either before flow is called (because
-   there will be no LOG_LINKS notes) or after reload (because the REG_DEAD
-   note can't be trusted).
-
-   If DEST is cc0_rtx, we look only at the next insn.  In that case, we don't
-   care about REG_DEAD notes or LOG_LINKS.
-
-   Otherwise, we find the single use by finding an insn that has a
-   LOG_LINKS pointing at INSN and has a REG_DEAD note for DEST.  If DEST is
-   only referenced once in that insn, we know that it must be the first
-   and last insn referencing DEST.  */
-
-rtx *
-find_single_use (rtx dest, rtx insn, rtx *ploc)
-{
-  rtx next;
-  rtx *result;
-  rtx link;
-
-#ifdef HAVE_cc0
-  if (dest == cc0_rtx)
-    {
-      next = NEXT_INSN (insn);
-      if (next == 0
-         || (!NONJUMP_INSN_P (next) && !JUMP_P (next)))
-       return 0;
-
-      result = find_single_use_1 (dest, &PATTERN (next));
-      if (result && ploc)
-       *ploc = next;
-      return result;
-    }
-#endif
-
-  if (reload_completed || reload_in_progress || !REG_P (dest))
-    return 0;
-
-  for (next = next_nonnote_insn (insn);
-       next != 0 && !LABEL_P (next);
-       next = next_nonnote_insn (next))
-    if (INSN_P (next) && dead_or_set_p (next, dest))
-      {
-       for (link = LOG_LINKS (next); link; link = XEXP (link, 1))
-         if (XEXP (link, 0) == insn)
-           break;
-
-       if (link)
-         {
-           result = find_single_use_1 (dest, &PATTERN (next));
-           if (ploc)
-             *ploc = next;
-           return result;
-         }
-      }
-
-  return 0;
-}
-\f
 /* Return 1 if OP is a valid general operand for machine mode MODE.
    This is either a register reference, a memory reference,
    or a constant.  In the case of a memory reference, the address
@@ -975,7 +912,7 @@ general_operand (rtx op, enum machine_mode mode)
       && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
     return 0;
 
-  if (GET_CODE (op) == CONST_INT
+  if (CONST_INT_P (op)
       && mode != VOIDmode
       && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
     return 0;
@@ -1152,7 +1089,7 @@ immediate_operand (rtx op, enum machine_mode mode)
       && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
     return 0;
 
-  if (GET_CODE (op) == CONST_INT
+  if (CONST_INT_P (op)
       && mode != VOIDmode
       && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
     return 0;
@@ -1169,7 +1106,7 @@ immediate_operand (rtx op, enum machine_mode mode)
 int
 const_int_operand (rtx op, enum machine_mode mode)
 {
-  if (GET_CODE (op) != CONST_INT)
+  if (!CONST_INT_P (op))
     return 0;
 
   if (mode != VOIDmode
@@ -1192,7 +1129,7 @@ const_double_operand (rtx op, enum machine_mode mode)
       && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
     return 0;
 
-  return ((GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT)
+  return ((GET_CODE (op) == CONST_DOUBLE || CONST_INT_P (op))
          && (mode == VOIDmode || GET_MODE (op) == mode
              || GET_MODE (op) == VOIDmode));
 }
@@ -1219,7 +1156,7 @@ nonmemory_operand (rtx op, enum machine_mode mode)
          && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
        return 0;
 
-      if (GET_CODE (op) == CONST_INT
+      if (CONST_INT_P (op)
          && mode != VOIDmode
          && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
        return 0;
@@ -1286,7 +1223,7 @@ push_operand (rtx op, enum machine_mode mode)
       if (GET_CODE (op) != PRE_MODIFY
          || GET_CODE (XEXP (op, 1)) != PLUS
          || XEXP (XEXP (op, 1), 0) != XEXP (op, 0)
-         || GET_CODE (XEXP (XEXP (op, 1), 1)) != CONST_INT
+         || !CONST_INT_P (XEXP (XEXP (op, 1), 1))
 #ifdef STACK_GROWS_DOWNWARD
          || INTVAL (XEXP (XEXP (op, 1), 1)) != - (int) rounded_size
 #else
@@ -1327,11 +1264,15 @@ pop_operand (rtx op, enum machine_mode mode)
 int
 memory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr)
 {
+#ifdef GO_IF_LEGITIMATE_ADDRESS
   GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
   return 0;
 
  win:
   return 1;
+#else
+  return targetm.legitimate_address_p (mode, addr, 0);
+#endif
 }
 
 /* Return 1 if OP is a valid memory reference with mode MODE,
@@ -1383,7 +1324,7 @@ indirect_operand (rtx op, enum machine_mode mode)
 
       return ((offset == 0 && general_operand (XEXP (inner, 0), Pmode))
              || (GET_CODE (XEXP (inner, 0)) == PLUS
-                 && GET_CODE (XEXP (XEXP (inner, 0), 1)) == CONST_INT
+                 && CONST_INT_P (XEXP (XEXP (inner, 0), 1))
                  && INTVAL (XEXP (XEXP (inner, 0), 1)) == -offset
                  && general_operand (XEXP (XEXP (inner, 0), 0), Pmode)));
     }
@@ -1393,6 +1334,32 @@ indirect_operand (rtx op, enum machine_mode mode)
          && general_operand (XEXP (op, 0), Pmode));
 }
 
+/* Return 1 if this is an ordered comparison operator (not including
+   ORDERED and UNORDERED).  */
+
+int
+ordered_comparison_operator (rtx op, enum machine_mode mode)
+{
+  if (mode != VOIDmode && GET_MODE (op) != mode)
+    return false;
+  switch (GET_CODE (op))
+    {
+    case EQ:
+    case NE:
+    case LT:
+    case LTU:
+    case LE:
+    case LEU:
+    case GT:
+    case GTU:
+    case GE:
+    case GEU:
+      return true;
+    default:
+      return false;
+    }
+}
+
 /* Return 1 if this is a comparison operator.  This allows the use of
    MATCH_OPERATOR to recognize all the branch insns.  */
 
@@ -1408,7 +1375,7 @@ comparison_operator (rtx op, enum machine_mode mode)
    Otherwise return -1.  */
 
 int
-asm_noperands (rtx body)
+asm_noperands (const_rtx body)
 {
   switch (GET_CODE (body))
     {
@@ -1619,14 +1586,7 @@ decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
     }
 
   if (loc)
-    {
-#ifdef USE_MAPPED_LOCATION
-      *loc = ASM_OPERANDS_SOURCE_LOCATION (asmop);
-#else
-      loc->file = ASM_OPERANDS_SOURCE_FILE (asmop);
-      loc->line = ASM_OPERANDS_SOURCE_LINE (asmop);
-#endif
-    }
+    *loc = ASM_OPERANDS_SOURCE_LOCATION (asmop);
 
   return ASM_OPERANDS_TEMPLATE (asmop);
 }
@@ -1635,7 +1595,7 @@ decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
    Return > 0 if ok, = 0 if bad, < 0 if inconclusive.  */
 
 int
-asm_operand_ok (rtx op, const char *constraint)
+asm_operand_ok (rtx op, const char *constraint, const char **constraints)
 {
   int result = 0;
 
@@ -1663,15 +1623,29 @@ asm_operand_ok (rtx op, const char *constraint)
 
        case '0': case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '8': case '9':
-         /* For best results, our caller should have given us the
-            proper matching constraint, but we can't actually fail
-            the check if they didn't.  Indicate that results are
-            inconclusive.  */
-         do
-           constraint++;
-         while (ISDIGIT (*constraint));
-         if (! result)
-           result = -1;
+         /* If caller provided constraints pointer, look up
+            the maching constraint.  Otherwise, our caller should have
+            given us the proper matching constraint, but we can't
+            actually fail the check if they didn't.  Indicate that
+            results are inconclusive.  */
+         if (constraints)
+           {
+             char *end;
+             unsigned long match;
+
+             match = strtoul (constraint, &end, 10);
+             if (!result)
+               result = asm_operand_ok (op, constraints[match], NULL);
+             constraint = (const char *) end;
+           }
+         else
+           {
+             do
+               constraint++;
+             while (ISDIGIT (*constraint));
+             if (! result)
+               result = -1;
+           }
          continue;
 
        case 'p':
@@ -1679,7 +1653,7 @@ asm_operand_ok (rtx op, const char *constraint)
            result = 1;
          break;
 
-       case 'm':
+       case TARGET_MEM_CONSTRAINT:
        case 'V': /* non-offsettable */
          if (memory_operand (op, VOIDmode))
            result = 1;
@@ -1691,7 +1665,7 @@ asm_operand_ok (rtx op, const char *constraint)
          break;
 
        case '<':
-         /* ??? Before flow, auto inc/dec insns are not supposed to exist,
+         /* ??? Before auto-inc-dec, auto inc/dec insns are not supposed to exist,
             excepting those that expand_call created.  Further, on some
             machines which do not have generalized auto inc/dec, an inc/dec
             is not a memory_operand.
@@ -1733,7 +1707,7 @@ asm_operand_ok (rtx op, const char *constraint)
          break;
 
        case 's':
-         if (GET_CODE (op) == CONST_INT
+         if (CONST_INT_P (op)
              || (GET_CODE (op) == CONST_DOUBLE
                  && GET_MODE (op) == VOIDmode))
            break;
@@ -1745,49 +1719,49 @@ asm_operand_ok (rtx op, const char *constraint)
          break;
 
        case 'n':
-         if (GET_CODE (op) == CONST_INT
+         if (CONST_INT_P (op)
              || (GET_CODE (op) == CONST_DOUBLE
                  && GET_MODE (op) == VOIDmode))
            result = 1;
          break;
 
        case 'I':
-         if (GET_CODE (op) == CONST_INT
+         if (CONST_INT_P (op)
              && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'I', constraint))
            result = 1;
          break;
        case 'J':
-         if (GET_CODE (op) == CONST_INT
+         if (CONST_INT_P (op)
              && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'J', constraint))
            result = 1;
          break;
        case 'K':
-         if (GET_CODE (op) == CONST_INT
+         if (CONST_INT_P (op)
              && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'K', constraint))
            result = 1;
          break;
        case 'L':
-         if (GET_CODE (op) == CONST_INT
+         if (CONST_INT_P (op)
              && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'L', constraint))
            result = 1;
          break;
        case 'M':
-         if (GET_CODE (op) == CONST_INT
+         if (CONST_INT_P (op)
              && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'M', constraint))
            result = 1;
          break;
        case 'N':
-         if (GET_CODE (op) == CONST_INT
+         if (CONST_INT_P (op)
              && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'N', constraint))
            result = 1;
          break;
        case 'O':
-         if (GET_CODE (op) == CONST_INT
+         if (CONST_INT_P (op)
              && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'O', constraint))
            result = 1;
          break;
        case 'P':
-         if (GET_CODE (op) == CONST_INT
+         if (CONST_INT_P (op)
              && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'P', constraint))
            result = 1;
          break;
@@ -1813,16 +1787,14 @@ asm_operand_ok (rtx op, const char *constraint)
                result = 1;
            }
 #ifdef EXTRA_CONSTRAINT_STR
+         else if (EXTRA_MEMORY_CONSTRAINT (c, constraint))
+           /* Every memory operand can be reloaded to fit.  */
+           result = result || memory_operand (op, VOIDmode);
+         else if (EXTRA_ADDRESS_CONSTRAINT (c, constraint))
+           /* Every address operand can be reloaded to fit.  */
+           result = result || address_operand (op, VOIDmode);
          else if (EXTRA_CONSTRAINT_STR (op, c, constraint))
            result = 1;
-         else if (EXTRA_MEMORY_CONSTRAINT (c, constraint)
-                  /* Every memory operand can be reloaded to fit.  */
-                  && memory_operand (op, VOIDmode))
-           result = 1;
-         else if (EXTRA_ADDRESS_CONSTRAINT (c, constraint)
-                  /* Every address operand can be reloaded to fit.  */
-                  && address_operand (op, VOIDmode))
-           result = 1;
 #endif
          break;
        }
@@ -2056,11 +2028,9 @@ extract_insn (rtx insn)
   int noperands;
   rtx body = PATTERN (insn);
 
-  recog_data.insn = NULL;
   recog_data.n_operands = 0;
   recog_data.n_alternatives = 0;
   recog_data.n_dups = 0;
-  which_alternative = -1;
 
   switch (GET_CODE (body))
     {
@@ -2140,6 +2110,22 @@ extract_insn (rtx insn)
         : OP_IN);
 
   gcc_assert (recog_data.n_alternatives <= MAX_RECOG_ALTERNATIVES);
+
+  if (INSN_CODE (insn) < 0)
+    for (i = 0; i < recog_data.n_alternatives; i++)
+      recog_data.alternative_enabled_p[i] = true;
+  else
+    {
+      recog_data.insn = insn;
+      for (i = 0; i < recog_data.n_alternatives; i++)
+       {
+         which_alternative = i;
+         recog_data.alternative_enabled_p[i] = get_attr_enabled (insn);
+       }
+    }
+
+  recog_data.insn = NULL;
+  which_alternative = -1;
 }
 
 /* After calling extract_insn, you can use this function to extract some
@@ -2169,6 +2155,12 @@ preprocess_constraints (void)
          op_alt[j].matches = -1;
          op_alt[j].matched = -1;
 
+         if (!recog_data.alternative_enabled_p[j])
+           {
+             p = skip_alternative (p);
+             continue;
+           }
+
          if (*p == '\0' || *p == ',')
            {
              op_alt[j].anything_ok = 1;
@@ -2218,7 +2210,7 @@ preprocess_constraints (void)
                  }
                  continue;
 
-               case 'm':
+               case TARGET_MEM_CONSTRAINT:
                  op_alt[j].memory_ok = 1;
                  break;
                case '<':
@@ -2307,7 +2299,7 @@ preprocess_constraints (void)
 
 struct funny_match
 {
-  int this, other;
+  int this_op, other;
 };
 
 int
@@ -2338,6 +2330,17 @@ constrain_operands (int strict)
       int lose = 0;
       funny_match_index = 0;
 
+      if (!recog_data.alternative_enabled_p[which_alternative])
+       {
+         int i;
+
+         for (i = 0; i < recog_data.n_operands; i++)
+           constraints[i] = skip_alternative (constraints[i]);
+
+         which_alternative++;
+         continue;
+       }
+
       for (opno = 0; opno < recog_data.n_operands; opno++)
        {
          rtx op = recog_data.operand[opno];
@@ -2446,7 +2449,7 @@ constrain_operands (int strict)
                     output op is the one that will be printed.  */
                  if (val == 2 && strict > 0)
                    {
-                     funny_match[funny_match_index].this = opno;
+                     funny_match[funny_match_index].this_op = opno;
                      funny_match[funny_match_index++].other = match;
                    }
                }
@@ -2491,7 +2494,7 @@ constrain_operands (int strict)
                win = 1;
                break;
 
-             case 'm':
+             case TARGET_MEM_CONSTRAINT:
                /* Memory operands must be valid, to the extent
                   required by STRICT.  */
                if (MEM_P (op))
@@ -2544,7 +2547,7 @@ constrain_operands (int strict)
                break;
 
              case 's':
-               if (GET_CODE (op) == CONST_INT
+               if (CONST_INT_P (op)
                    || (GET_CODE (op) == CONST_DOUBLE
                        && GET_MODE (op) == VOIDmode))
                  break;
@@ -2554,7 +2557,7 @@ constrain_operands (int strict)
                break;
 
              case 'n':
-               if (GET_CODE (op) == CONST_INT
+               if (CONST_INT_P (op)
                    || (GET_CODE (op) == CONST_DOUBLE
                        && GET_MODE (op) == VOIDmode))
                  win = 1;
@@ -2568,7 +2571,7 @@ constrain_operands (int strict)
              case 'N':
              case 'O':
              case 'P':
-               if (GET_CODE (op) == CONST_INT
+               if (CONST_INT_P (op)
                    && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p))
                  win = 1;
                break;
@@ -2679,7 +2682,7 @@ constrain_operands (int strict)
              while (--funny_match_index >= 0)
                {
                  recog_data.operand[funny_match[funny_match_index].other]
-                   = recog_data.operand[funny_match[funny_match_index].this];
+                   = recog_data.operand[funny_match[funny_match_index].this_op];
                }
 
              return 1;
@@ -2728,10 +2731,29 @@ split_insn (rtx insn)
   /* Split insns here to get max fine-grain parallelism.  */
   rtx first = PREV_INSN (insn);
   rtx last = try_split (PATTERN (insn), insn, 1);
+  rtx insn_set, last_set, note;
 
   if (last == insn)
     return NULL_RTX;
 
+  /* If the original instruction was a single set that was known to be
+     equivalent to a constant, see if we can say the same about the last
+     instruction in the split sequence.  The two instructions must set
+     the same destination.  */
+  insn_set = single_set (insn);
+  if (insn_set)
+    {
+      last_set = single_set (last);
+      if (last_set && rtx_equal_p (SET_DEST (last_set), SET_DEST (insn_set)))
+       {
+         note = find_reg_equal_equiv_note (insn);
+         if (note && CONSTANT_P (XEXP (note, 0)))
+           set_unique_reg_note (last, REG_EQUAL, XEXP (note, 0));
+         else if (CONSTANT_P (SET_SRC (insn_set)))
+           set_unique_reg_note (last, REG_EQUAL, SET_SRC (insn_set));
+       }
+    }
+
   /* try_split returns the NOTE that INSN became.  */
   SET_INSN_DELETED (insn);
 
@@ -2749,13 +2771,14 @@ split_insn (rtx insn)
          first = NEXT_INSN (first);
        }
     }
+
   return last;
 }
 
 /* Split all insns in the function.  If UPD_LIFE, update life info after.  */
 
 void
-split_all_insns (int upd_life)
+split_all_insns (void)
 {
   sbitmap blocks;
   bool changed;
@@ -2770,6 +2793,7 @@ split_all_insns (int upd_life)
       rtx insn, next;
       bool finish = false;
 
+      rtl_profile_for_bb (bb);
       for (insn = BB_HEAD (bb); !finish ; insn = next)
        {
          /* Can't use `next_real_insn' because that might go across
@@ -2782,7 +2806,7 @@ split_all_insns (int upd_life)
 
              /* Don't split no-op move insns.  These should silently
                 disappear later in final.  Splitting such insns would
-                break the code that handles REG_NO_CONFLICT blocks.  */
+                break the code that handles LIBCALL blocks.  */
              if (set && set_noop_p (set))
                {
                  /* Nops get in the way while scheduling, so delete them
@@ -2791,17 +2815,7 @@ split_all_insns (int upd_life)
                     allocation, and there are unlikely to be very many
                     nops then anyways.  */
                  if (reload_completed)
-                   {
-                     /* If the no-op set has a REG_UNUSED note, we need
-                        to update liveness information.  */
-                     if (find_reg_note (insn, REG_UNUSED, NULL_RTX))
-                       {
-                         SET_BIT (blocks, bb->index);
-                         changed = true;
-                       }
-                     /* ??? Is life info affected by deleting edges?  */
                      delete_insn_and_edges (insn);
-                   }
                }
              else
                {
@@ -2822,19 +2836,9 @@ split_all_insns (int upd_life)
        }
     }
 
+  default_rtl_profile ();
   if (changed)
-    {
-      int old_last_basic_block = last_basic_block;
-
-      find_many_sub_basic_blocks (blocks);
-
-      if (old_last_basic_block != last_basic_block && upd_life)
-       blocks = sbitmap_resize (blocks, last_basic_block, 1);
-    }
-
-  if (changed && upd_life)
-    update_life_info (blocks, UPDATE_LIFE_GLOBAL_RM_NOTES,
-                     PROP_DEATH_NOTES);
+    find_many_sub_basic_blocks (blocks);
 
 #ifdef ENABLE_CHECKING
   verify_flow_info ();
@@ -2858,7 +2862,7 @@ split_all_insns_noflow (void)
        {
          /* Don't split no-op move insns.  These should silently
             disappear later in final.  Splitting such insns would
-            break the code that handles REG_NO_CONFLICT blocks.  */
+            break the code that handles LIBCALL blocks.  */
          rtx set = single_set (insn);
          if (set && set_noop_p (set))
            {
@@ -2893,7 +2897,7 @@ int peep2_current_count;
 
 /* A non-insn marker indicating the last insn of the block.
    The live_before regset for this element is correct, indicating
-   global_live_at_end for the block.  */
+   DF_LIVE_OUT for the block.  */
 #define PEEP2_EOB      pc_rtx
 
 /* Return the Nth non-note insn after `current', or return NULL_RTX if it
@@ -3016,6 +3020,9 @@ peep2_find_free_register (int from, int to, const char *class_str,
       /* Don't allocate fixed registers.  */
       if (fixed_regs[regno])
        continue;
+      /* Don't allocate global registers.  */
+      if (global_regs[regno])
+       continue;
       /* Make sure the register is of the right class.  */
       if (! TEST_HARD_REG_BIT (reg_class_contents[cl], regno))
        continue;
@@ -3023,8 +3030,11 @@ peep2_find_free_register (int from, int to, const char *class_str,
       if (! HARD_REGNO_MODE_OK (regno, mode))
        continue;
       /* And that we don't create an extra save/restore.  */
-      if (! call_used_regs[regno] && ! regs_ever_live[regno])
+      if (! call_used_regs[regno] && ! df_regs_ever_live_p (regno))
+       continue;
+      if (! targetm.hard_regno_scratch_ok (regno))
        continue;
+
       /* And we don't clobber traceback for noreturn functions.  */
       if ((regno == FRAME_POINTER_REGNUM || regno == HARD_FRAME_POINTER_REGNUM)
          && (! reload_completed || frame_pointer_needed))
@@ -3057,67 +3067,61 @@ peep2_find_free_register (int from, int to, const char *class_str,
   return NULL_RTX;
 }
 
+/* Forget all currently tracked instructions, only remember current
+   LIVE regset.  */
+
+static void
+peep2_reinit_state (regset live)
+{
+  int i;
+
+  /* Indicate that all slots except the last holds invalid data.  */
+  for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i)
+    peep2_insn_data[i].insn = NULL_RTX;
+  peep2_current_count = 0;
+
+  /* Indicate that the last slot contains live_after data.  */
+  peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB;
+  peep2_current = MAX_INSNS_PER_PEEP2;
+
+  COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
+}
+
 /* Perform the peephole2 optimization pass.  */
 
 static void
 peephole2_optimize (void)
 {
   rtx insn, prev;
-  regset live;
+  bitmap live;
   int i;
   basic_block bb;
-#ifdef HAVE_conditional_execution
-  sbitmap blocks;
-  bool changed;
-#endif
   bool do_cleanup_cfg = false;
-  bool do_global_life_update = false;
   bool do_rebuild_jump_labels = false;
 
+  df_set_flags (DF_LR_RUN_DCE);
+  df_analyze ();
+
   /* Initialize the regsets we're going to use.  */
   for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
-    peep2_insn_data[i].live_before = ALLOC_REG_SET (&reg_obstack);
-  live = ALLOC_REG_SET (&reg_obstack);
-
-#ifdef HAVE_conditional_execution
-  blocks = sbitmap_alloc (last_basic_block);
-  sbitmap_zero (blocks);
-  changed = false;
-#else
-  count_or_remove_death_notes (NULL, 1);
-#endif
+    peep2_insn_data[i].live_before = BITMAP_ALLOC (&reg_obstack);
+  live = BITMAP_ALLOC (&reg_obstack);
 
   FOR_EACH_BB_REVERSE (bb)
     {
-      struct propagate_block_info *pbi;
-      reg_set_iterator rsi;
-      unsigned int j;
-
-      /* Indicate that all slots except the last holds invalid data.  */
-      for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i)
-       peep2_insn_data[i].insn = NULL_RTX;
-      peep2_current_count = 0;
-
-      /* Indicate that the last slot contains live_after data.  */
-      peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB;
-      peep2_current = MAX_INSNS_PER_PEEP2;
+      rtl_profile_for_bb (bb);
 
       /* Start up propagation.  */
-      COPY_REG_SET (live, bb->il.rtl->global_live_at_end);
-      COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
-
-#ifdef HAVE_conditional_execution
-      pbi = init_propagate_block_info (bb, live, NULL, NULL, 0);
-#else
-      pbi = init_propagate_block_info (bb, live, NULL, NULL, PROP_DEATH_NOTES);
-#endif
+      bitmap_copy (live, DF_LR_OUT (bb));
+      df_simulate_initialize_backwards (bb, live);
+      peep2_reinit_state (live);
 
       for (insn = BB_END (bb); ; insn = prev)
        {
          prev = PREV_INSN (insn);
          if (INSN_P (insn))
            {
-             rtx try, before_try, x;
+             rtx attempt, before_try, x;
              int match_len;
              rtx note;
              bool was_call = false;
@@ -3129,7 +3133,7 @@ peephole2_optimize (void)
                  && peep2_insn_data[peep2_current].insn == NULL_RTX)
                peep2_current_count++;
              peep2_insn_data[peep2_current].insn = insn;
-             propagate_one_insn (pbi, insn);
+             df_simulate_one_insn_backwards (bb, insn, live);
              COPY_REG_SET (peep2_insn_data[peep2_current].live_before, live);
 
              if (RTX_FRAME_RELATED_P (insn))
@@ -3137,14 +3141,14 @@ peephole2_optimize (void)
                  /* If an insn has RTX_FRAME_RELATED_P set, peephole
                     substitution would lose the
                     REG_FRAME_RELATED_EXPR that is attached.  */
-                 peep2_current_count = 0;
-                 try = NULL;
+                 peep2_reinit_state (live);
+                 attempt = NULL;
                }
              else
                /* Match the peephole.  */
-               try = peephole2_insns (PATTERN (insn), insn, &match_len);
+               attempt = peephole2_insns (PATTERN (insn), insn, &match_len);
 
-             if (try != NULL)
+             if (attempt != NULL)
                {
                  /* If we are splitting a CALL_INSN, look for the CALL_INSN
                     in SEQ and copy our CALL_INSN_FUNCTION_USAGE and other
@@ -3162,7 +3166,7 @@ peephole2_optimize (void)
                        continue;
                      was_call = true;
 
-                     new_insn = try;
+                     new_insn = attempt;
                      while (new_insn != NULL_RTX)
                        {
                          if (CALL_P (new_insn))
@@ -3182,10 +3186,9 @@ peephole2_optimize (void)
                          {
                          case REG_NORETURN:
                          case REG_SETJMP:
-                           REG_NOTES (new_insn)
-                             = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
-                                                  XEXP (note, 0),
-                                                  REG_NOTES (new_insn));
+                           add_reg_note (new_insn, REG_NOTE_KIND (note),
+                                         XEXP (note, 0));
+                           break;
                          default:
                            /* Discard all other reg notes.  */
                            break;
@@ -3211,10 +3214,11 @@ peephole2_optimize (void)
                                        REG_EH_REGION, NULL_RTX);
 
                  /* Replace the old sequence with the new.  */
-                 try = emit_insn_after_setloc (try, peep2_insn_data[i].insn,
-                                               INSN_LOCATOR (peep2_insn_data[i].insn));
+                 attempt = emit_insn_after_setloc (attempt,
+                                                   peep2_insn_data[i].insn,
+                                      INSN_LOCATOR (peep2_insn_data[i].insn));
                  before_try = PREV_INSN (insn);
-                 delete_insn_chain (insn, peep2_insn_data[i].insn);
+                 delete_insn_chain (insn, peep2_insn_data[i].insn, false);
 
                  /* Re-insert the EH_REGION notes.  */
                  if (note || (was_call && nonlocal_goto_handler_labels))
@@ -3226,17 +3230,14 @@ peephole2_optimize (void)
                        if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
                          break;
 
-                     for (x = try ; x != before_try ; x = PREV_INSN (x))
+                     for (x = attempt ; x != before_try ; x = PREV_INSN (x))
                        if (CALL_P (x)
                            || (flag_non_call_exceptions
                                && may_trap_p (PATTERN (x))
                                && !find_reg_note (x, REG_EH_REGION, NULL)))
                          {
                            if (note)
-                             REG_NOTES (x)
-                               = gen_rtx_EXPR_LIST (REG_EH_REGION,
-                                                    XEXP (note, 0),
-                                                    REG_NOTES (x));
+                             add_reg_note (x, REG_EH_REGION, XEXP (note, 0));
 
                            if (x != BB_END (bb) && eh_edge)
                              {
@@ -3256,10 +3257,6 @@ peephole2_optimize (void)
                                  = REG_BR_PROB_BASE - nehe->probability;
 
                                do_cleanup_cfg |= purge_dead_edges (nfte->dest);
-#ifdef HAVE_conditional_execution
-                               SET_BIT (blocks, nfte->dest->index);
-                               changed = true;
-#endif
                                bb = nfte->src;
                                eh_edge = nehe;
                              }
@@ -3271,14 +3268,6 @@ peephole2_optimize (void)
                    }
 
 #ifdef HAVE_conditional_execution
-                 /* With conditional execution, we cannot back up the
-                    live information so easily, since the conditional
-                    death data structures are not so self-contained.
-                    So record that we've made a modification to this
-                    block and update life information at the end.  */
-                 SET_BIT (blocks, bb->index);
-                 changed = true;
-
                  for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
                    peep2_insn_data[i].insn = NULL_RTX;
                  peep2_insn_data[peep2_current].insn = PEEP2_EOB;
@@ -3288,10 +3277,10 @@ peephole2_optimize (void)
                     newly created sequence.  */
                  if (++i >= MAX_INSNS_PER_PEEP2 + 1)
                    i = 0;
-                 COPY_REG_SET (live, peep2_insn_data[i].live_before);
+                 bitmap_copy (live, peep2_insn_data[i].live_before);
 
                  /* Update life information for the new sequence.  */
-                 x = try;
+                 x = attempt;
                  do
                    {
                      if (INSN_P (x))
@@ -3302,22 +3291,20 @@ peephole2_optimize (void)
                              && peep2_insn_data[i].insn == NULL_RTX)
                            peep2_current_count++;
                          peep2_insn_data[i].insn = x;
-                         propagate_one_insn (pbi, x);
-                         COPY_REG_SET (peep2_insn_data[i].live_before, live);
+                         df_insn_rescan (x);
+                         df_simulate_one_insn_backwards (bb, x, live);
+                         bitmap_copy (peep2_insn_data[i].live_before, live);
                        }
                      x = PREV_INSN (x);
                    }
                  while (x != prev);
 
-                 /* ??? Should verify that LIVE now matches what we
-                    had before the new sequence.  */
-
                  peep2_current = i;
 #endif
 
                  /* If we generated a jump instruction, it won't have
                     JUMP_LABEL set.  Recompute after we're done.  */
-                 for (x = try; x != before_try; x = PREV_INSN (x))
+                 for (x = attempt; x != before_try; x = PREV_INSN (x))
                    if (JUMP_P (x))
                      {
                        do_rebuild_jump_labels = true;
@@ -3329,44 +3316,14 @@ peephole2_optimize (void)
          if (insn == BB_HEAD (bb))
            break;
        }
-
-      /* Some peepholes can decide the don't need one or more of their
-        inputs.  If this happens, local life update is not enough.  */
-      EXECUTE_IF_AND_COMPL_IN_BITMAP (bb->il.rtl->global_live_at_start, live,
-                                     0, j, rsi)
-       {
-         do_global_life_update = true;
-         break;
-       }
-
-      free_propagate_block_info (pbi);
     }
 
+  default_rtl_profile ();
   for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
-    FREE_REG_SET (peep2_insn_data[i].live_before);
-  FREE_REG_SET (live);
-
+    BITMAP_FREE (peep2_insn_data[i].live_before);
+  BITMAP_FREE (live);
   if (do_rebuild_jump_labels)
     rebuild_jump_labels (get_insns ());
-
-  /* If we eliminated EH edges, we may be able to merge blocks.  Further,
-     we've changed global life since exception handlers are no longer
-     reachable.  */
-  if (do_cleanup_cfg)
-    {
-      cleanup_cfg (0);
-      do_global_life_update = true;
-    }
-  if (do_global_life_update)
-    update_life_info (0, UPDATE_LIFE_GLOBAL_RM_NOTES, PROP_DEATH_NOTES);
-#ifdef HAVE_conditional_execution
-  else
-    {
-      count_or_remove_death_notes (blocks, 1);
-      update_life_info (blocks, UPDATE_LIFE_LOCAL, PROP_DEATH_NOTES);
-    }
-  sbitmap_free (blocks);
-#endif
 }
 #endif /* HAVE_peephole2 */
 
@@ -3533,8 +3490,10 @@ rest_of_handle_peephole2 (void)
   return 0;
 }
 
-struct tree_opt_pass pass_peephole2 =
+struct rtl_opt_pass pass_peephole2 =
 {
+ {
+  RTL_PASS,
   "peephole2",                          /* name */
   gate_handle_peephole2,                /* gate */
   rest_of_handle_peephole2,             /* execute */
@@ -3546,64 +3505,67 @@ struct tree_opt_pass pass_peephole2 =
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_dump_func,                       /* todo_flags_finish */
-  'z'                                   /* letter */
+  TODO_df_finish | TODO_verify_rtl_sharing |
+  TODO_dump_func                       /* todo_flags_finish */
+ }
 };
 
 static unsigned int
 rest_of_handle_split_all_insns (void)
 {
-  split_all_insns (1);
+  split_all_insns ();
   return 0;
 }
 
-struct tree_opt_pass pass_split_all_insns =
+struct rtl_opt_pass pass_split_all_insns =
 {
+ {
+  RTL_PASS,
   "split1",                             /* name */
   NULL,                                 /* gate */
   rest_of_handle_split_all_insns,       /* execute */
   NULL,                                 /* sub */
   NULL,                                 /* next */
   0,                                    /* static_pass_number */
-  0,                                    /* tv_id */
+  TV_NONE,                              /* tv_id */
   0,                                    /* properties_required */
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_dump_func,                       /* todo_flags_finish */
-  0                                     /* letter */
+  TODO_dump_func                        /* todo_flags_finish */
+ }
 };
 
-/* The placement of the splitting that we do for shorten_branches
-   depends on whether regstack is used by the target or not.  */
-static bool
-gate_do_final_split (void)
+static unsigned int
+rest_of_handle_split_after_reload (void)
 {
-#if defined (HAVE_ATTR_length) && !defined (STACK_REGS)
-  return 1;
-#else
+  /* If optimizing, then go ahead and split insns now.  */
+#ifndef STACK_REGS
+  if (optimize > 0)
+#endif
+    split_all_insns ();
   return 0;
-#endif 
 }
 
-struct tree_opt_pass pass_split_for_shorten_branches =
+struct rtl_opt_pass pass_split_after_reload =
 {
-  "split3",                             /* name */
-  gate_do_final_split,                  /* gate */
-  split_all_insns_noflow,               /* execute */
+ {
+  RTL_PASS,
+  "split2",                             /* name */
+  NULL,                                 /* gate */
+  rest_of_handle_split_after_reload,    /* execute */
   NULL,                                 /* sub */
   NULL,                                 /* next */
   0,                                    /* static_pass_number */
-  TV_SHORTEN_BRANCH,                    /* tv_id */
+  TV_NONE,                              /* tv_id */
   0,                                    /* properties_required */
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_dump_func,                       /* todo_flags_finish */
-  0                                     /* letter */
+  TODO_dump_func                        /* todo_flags_finish */
+ }
 };
 
-
 static bool
 gate_handle_split_before_regstack (void)
 {
@@ -3622,19 +3584,98 @@ gate_handle_split_before_regstack (void)
 #endif
 }
 
-struct tree_opt_pass pass_split_before_regstack =
+static unsigned int
+rest_of_handle_split_before_regstack (void)
+{
+  split_all_insns ();
+  return 0;
+}
+
+struct rtl_opt_pass pass_split_before_regstack =
 {
-  "split2",                             /* name */
+ {
+  RTL_PASS,
+  "split3",                             /* name */
   gate_handle_split_before_regstack,    /* gate */
-  rest_of_handle_split_all_insns,       /* execute */
+  rest_of_handle_split_before_regstack, /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_NONE,                              /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  TODO_dump_func                        /* todo_flags_finish */
+ }
+};
+
+static bool
+gate_handle_split_before_sched2 (void)
+{
+#ifdef INSN_SCHEDULING
+  return optimize > 0 && flag_schedule_insns_after_reload;
+#else
+  return 0;
+#endif
+}
+
+static unsigned int
+rest_of_handle_split_before_sched2 (void)
+{
+#ifdef INSN_SCHEDULING
+  split_all_insns ();
+#endif
+  return 0;
+}
+
+struct rtl_opt_pass pass_split_before_sched2 =
+{
+ {
+  RTL_PASS,
+  "split4",                             /* name */
+  gate_handle_split_before_sched2,      /* gate */
+  rest_of_handle_split_before_sched2,   /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_NONE,                              /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  TODO_verify_flow |
+  TODO_dump_func                        /* todo_flags_finish */
+ }
+};
+
+/* The placement of the splitting that we do for shorten_branches
+   depends on whether regstack is used by the target or not.  */
+static bool
+gate_do_final_split (void)
+{
+#if defined (HAVE_ATTR_length) && !defined (STACK_REGS)
+  return 1;
+#else
+  return 0;
+#endif 
+}
+
+struct rtl_opt_pass pass_split_for_shorten_branches =
+{
+ {
+  RTL_PASS,
+  "split5",                             /* name */
+  gate_do_final_split,                  /* gate */
+  split_all_insns_noflow,               /* execute */
   NULL,                                 /* sub */
   NULL,                                 /* next */
   0,                                    /* static_pass_number */
-  TV_SHORTEN_BRANCH,                    /* tv_id */
+  TV_NONE,                              /* tv_id */
   0,                                    /* properties_required */
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_dump_func,                       /* todo_flags_finish */
-  0                                     /* letter */
+  TODO_dump_func | TODO_verify_rtl_sharing /* todo_flags_finish */
+ }
 };