OSDN Git Service

* parse.y (build_assertion): If we're in an inner class, create the
[pf3gnuchains/gcc-fork.git] / gcc / recog.c
index 649f366..9b5f4d4 100644 (file)
@@ -1,6 +1,6 @@
 /* Subroutines used by or related to instruction recognition.
    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
-   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -22,6 +22,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "tm_p.h"
 #include "insn-config.h"
@@ -54,10 +56,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #endif
 #endif
 
-static void validate_replace_rtx_1     PARAMS ((rtx *, rtx, rtx, rtx));
-static rtx *find_single_use_1          PARAMS ((rtx, rtx *));
-static void validate_replace_src_1     PARAMS ((rtx *, void *));
-static rtx split_insn                  PARAMS ((rtx));
+static void validate_replace_rtx_1 (rtx *, rtx, rtx, rtx);
+static rtx *find_single_use_1 (rtx, rtx *);
+static void validate_replace_src_1 (rtx *, void *);
+static rtx split_insn (rtx);
 
 /* Nonzero means allow operands to be volatile.
    This should be 0 if you are generating rtl, such as if you are calling
@@ -86,18 +88,21 @@ int which_alternative;
 
 int reload_completed;
 
+/* Nonzero after thread_prologue_and_epilogue_insns has run.  */
+int epilogue_completed;
+
 /* Initialize data used by the function `recog'.
    This must be called once in the compilation of a function
    before any insn recognition may be done in the function.  */
 
 void
-init_recog_no_volatile ()
+init_recog_no_volatile (void)
 {
   volatile_ok = 0;
 }
 
 void
-init_recog ()
+init_recog (void)
 {
   volatile_ok = 1;
 }
@@ -112,8 +117,7 @@ init_recog ()
    through this one.  (The only exception is in combine.c.)  */
 
 int
-recog_memoized_1 (insn)
-     rtx insn;
+recog_memoized_1 (rtx insn)
 {
   if (INSN_CODE (insn) < 0)
     INSN_CODE (insn) = recog (PATTERN (insn), insn, 0);
@@ -124,8 +128,7 @@ recog_memoized_1 (insn)
    and that the operands mentioned in it are legitimate.  */
 
 int
-check_asm_operands (x)
-     rtx x;
+check_asm_operands (rtx x)
 {
   int noperands;
   rtx *operands;
@@ -147,8 +150,8 @@ check_asm_operands (x)
   if (noperands == 0)
     return 1;
 
-  operands = (rtx *) alloca (noperands * sizeof (rtx));
-  constraints = (const char **) alloca (noperands * sizeof (char *));
+  operands = alloca (noperands * sizeof (rtx));
+  constraints = alloca (noperands * sizeof (char *));
 
   decode_asm_operands (x, operands, NULL, constraints, NULL);
 
@@ -201,11 +204,7 @@ static int num_changes = 0;
    Otherwise, perform the change and return 1.  */
 
 int
-validate_change (object, loc, new, in_group)
-    rtx object;
-    rtx *loc;
-    rtx new;
-    int in_group;
+validate_change (rtx object, rtx *loc, rtx new, int in_group)
 {
   rtx old = *loc;
 
@@ -227,9 +226,7 @@ validate_change (object, loc, new, in_group)
       else
        changes_allocated *= 2;
 
-      changes =
-       (change_t*) xrealloc (changes,
-                             sizeof (change_t) * changes_allocated);
+      changes = xrealloc (changes, sizeof (change_t) * changes_allocated);
     }
 
   changes[num_changes].object = object;
@@ -259,8 +256,7 @@ validate_change (object, loc, new, in_group)
    were valid; i.e. whether INSN can still be recognized.  */
 
 int
-insn_invalid_p (insn)
-     rtx insn;
+insn_invalid_p (rtx insn)
 {
   rtx pat = PATTERN (insn);
   int num_clobbers = 0;
@@ -310,7 +306,7 @@ insn_invalid_p (insn)
 
 /* Return number of changes made and not validated yet.  */
 int
-num_changes_pending ()
+num_changes_pending (void)
 {
   return num_changes;
 }
@@ -319,7 +315,7 @@ num_changes_pending ()
    Return 1 if all changes are valid, zero otherwise.  */
 
 int
-apply_change_group ()
+apply_change_group (void)
 {
   int i;
   rtx last_validated = NULL_RTX;
@@ -337,7 +333,7 @@ apply_change_group ()
     {
       rtx object = changes[i].object;
 
-      /* if there is no object to test or if it is the same as the one we
+      /* If there is no object to test or if it is the same as the one we
          already tested, ignore it.  */
       if (object == 0 || object == last_validated)
        continue;
@@ -420,7 +416,7 @@ apply_change_group ()
 /* Return the number of changes so far in the current group.  */
 
 int
-num_validated_changes ()
+num_validated_changes (void)
 {
   return num_changes;
 }
@@ -428,8 +424,7 @@ num_validated_changes ()
 /* Retract the changes numbered NUM and up.  */
 
 void
-cancel_changes (num)
-     int num;
+cancel_changes (int num)
 {
   int i;
 
@@ -448,9 +443,7 @@ cancel_changes (num)
    validate_change passing OBJECT.  */
 
 static void
-validate_replace_rtx_1 (loc, from, to, object)
-     rtx *loc;
-     rtx from, to, object;
+validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object)
 {
   int i, j;
   const char *fmt;
@@ -483,16 +476,38 @@ validate_replace_rtx_1 (loc, from, to, object)
       return;
     }
 
-  /* Call ourself recursively to perform the replacements.  */
+  /* 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.  */
 
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+  if (GET_CODE (x) == PARALLEL)
     {
-      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);
+      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.  */
+             if (ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (x, 0, 0))) !=
+                 ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (x, 0, j))))
+               abort ();
+             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)
@@ -631,8 +646,7 @@ validate_replace_rtx_1 (loc, from, to, object)
    if INSN is still valid.  */
 
 int
-validate_replace_rtx_subexp (from, to, insn, loc)
-     rtx from, to, insn, *loc;
+validate_replace_rtx_subexp (rtx from, rtx to, rtx insn, rtx *loc)
 {
   validate_replace_rtx_1 (loc, from, to, insn);
   return apply_change_group ();
@@ -642,8 +656,7 @@ validate_replace_rtx_subexp (from, to, insn, loc)
    changes have been made, validate by seeing if INSN is still valid.  */
 
 int
-validate_replace_rtx (from, to, insn)
-     rtx from, to, insn;
+validate_replace_rtx (rtx from, rtx to, rtx insn)
 {
   validate_replace_rtx_1 (&PATTERN (insn), from, to, insn);
   return apply_change_group ();
@@ -652,8 +665,7 @@ validate_replace_rtx (from, to, insn)
 /* Try replacing every occurrence of FROM in INSN with TO.  */
 
 void
-validate_replace_rtx_group (from, to, insn)
-     rtx from, to, insn;
+validate_replace_rtx_group (rtx from, rtx to, rtx insn)
 {
   validate_replace_rtx_1 (&PATTERN (insn), from, to, insn);
 }
@@ -667,9 +679,7 @@ struct validate_replace_src_data
 };
 
 static void
-validate_replace_src_1 (x, data)
-     rtx *x;
-     void *data;
+validate_replace_src_1 (rtx *x, void *data)
 {
   struct validate_replace_src_data *d
     = (struct validate_replace_src_data *) data;
@@ -681,8 +691,7 @@ validate_replace_src_1 (x, data)
    SET_DESTs.  */
 
 void
-validate_replace_src_group (from, to, insn)
-     rtx from, to, insn;
+validate_replace_src_group (rtx from, rtx to, rtx insn)
 {
   struct validate_replace_src_data d;
 
@@ -692,11 +701,10 @@ validate_replace_src_group (from, to, insn)
   note_uses (&PATTERN (insn), validate_replace_src_1, &d);
 }
 
-/* Same as validate_repalace_src_group, but validate by seeing if
+/* Same as validate_replace_src_group, but validate by seeing if
    INSN is still valid.  */
 int
-validate_replace_src (from, to, insn)
-     rtx from, to, insn;
+validate_replace_src (rtx from, rtx to, rtx insn)
 {
   validate_replace_src_group (from, to, insn);
   return apply_change_group ();
@@ -708,8 +716,7 @@ validate_replace_src (from, to, insn)
    EQ and NE tests do not count.  */
 
 int
-next_insn_tests_no_inequality (insn)
-     rtx insn;
+next_insn_tests_no_inequality (rtx insn)
 {
   rtx next = next_cc0_user (insn);
 
@@ -722,34 +729,6 @@ next_insn_tests_no_inequality (insn)
           || GET_CODE (next) == CALL_INSN)
          && ! inequality_comparisons_p (PATTERN (next)));
 }
-
-#if 0  /* This is useless since the insn that sets the cc's
-         must be followed immediately by the use of them.  */
-/* Return 1 if the CC value set up by INSN is not used.  */
-
-int
-next_insns_test_no_inequality (insn)
-     rtx insn;
-{
-  rtx next = NEXT_INSN (insn);
-
-  for (; next != 0; next = NEXT_INSN (next))
-    {
-      if (GET_CODE (next) == CODE_LABEL
-         || GET_CODE (next) == BARRIER)
-       return 1;
-      if (GET_CODE (next) == NOTE)
-       continue;
-      if (inequality_comparisons_p (PATTERN (next)))
-       return 0;
-      if (sets_cc0_p (PATTERN (next)) == 1)
-       return 1;
-      if (! reg_mentioned_p (cc0_rtx, PATTERN (next)))
-       return 1;
-    }
-  return 1;
-}
-#endif
 #endif
 \f
 /* This is used by find_single_use to locate an rtx that contains exactly one
@@ -758,9 +737,7 @@ next_insns_test_no_inequality (insn)
    DEST that are being used to totally replace it are not counted.  */
 
 static rtx *
-find_single_use_1 (dest, loc)
-     rtx dest;
-     rtx *loc;
+find_single_use_1 (rtx dest, rtx *loc)
 {
   rtx x = *loc;
   enum rtx_code code = GET_CODE (x);
@@ -871,10 +848,7 @@ find_single_use_1 (dest, loc)
    and last insn referencing DEST.  */
 
 rtx *
-find_single_use (dest, insn, ploc)
-     rtx dest;
-     rtx insn;
-     rtx *ploc;
+find_single_use (rtx dest, rtx insn, rtx *ploc)
 {
   rtx next;
   rtx *result;
@@ -937,9 +911,7 @@ find_single_use (dest, insn, ploc)
    class NO_REGS, see the comment for `register_operand'.  */
 
 int
-general_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+general_operand (rtx op, enum machine_mode mode)
 {
   enum rtx_code code = GET_CODE (op);
 
@@ -994,7 +966,7 @@ general_operand (op, mode)
        return 0;
 
       /* FLOAT_MODE subregs can't be paradoxical.  Combine will occasionally
-        create such rtl, and we must reject it.  */
+        create such rtl, and we must reject it.  */
       if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
          && GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub)))
        return 0;
@@ -1041,9 +1013,7 @@ general_operand (op, mode)
    expressions in the machine description.  */
 
 int
-address_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+address_operand (rtx op, enum machine_mode mode)
 {
   return memory_address_p (mode, op);
 }
@@ -1063,9 +1033,7 @@ address_operand (op, mode)
    it is most consistent to keep this function from accepting them.  */
 
 int
-register_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+register_operand (rtx op, enum machine_mode mode)
 {
   if (GET_MODE (op) != mode && mode != VOIDmode)
     return 0;
@@ -1086,7 +1054,7 @@ register_operand (op, mode)
 #ifdef CANNOT_CHANGE_MODE_CLASS
       if (GET_CODE (sub) == REG
          && REGNO (sub) < FIRST_PSEUDO_REGISTER
-         && REG_CANNOT_CHANGE_MODE_P (REGNO (sub), mode, GET_MODE (sub))
+         && REG_CANNOT_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub), mode)
          && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
          && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT)
        return 0;
@@ -1116,9 +1084,7 @@ register_operand (op, mode)
 /* Return 1 for a register in Pmode; ignore the tested mode.  */
 
 int
-pmode_register_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+pmode_register_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return register_operand (op, Pmode);
 }
@@ -1127,9 +1093,7 @@ pmode_register_operand (op, mode)
    or a hard register.  */
 
 int
-scratch_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+scratch_operand (rtx op, enum machine_mode mode)
 {
   if (GET_MODE (op) != mode && mode != VOIDmode)
     return 0;
@@ -1145,9 +1109,7 @@ scratch_operand (op, mode)
    expressions in the machine description.  */
 
 int
-immediate_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+immediate_operand (rtx op, enum machine_mode mode)
 {
   /* Don't accept CONST_INT or anything similar
      if the caller wants something floating.  */
@@ -1179,9 +1141,7 @@ immediate_operand (op, mode)
 /* Returns 1 if OP is an operand that is a CONST_INT.  */
 
 int
-const_int_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+const_int_operand (rtx op, enum machine_mode mode)
 {
   if (GET_CODE (op) != CONST_INT)
     return 0;
@@ -1197,9 +1157,7 @@ const_int_operand (op, mode)
    floating-point number.  */
 
 int
-const_double_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+const_double_operand (rtx op, enum machine_mode mode)
 {
   /* Don't accept CONST_INT or anything similar
      if the caller wants something floating.  */
@@ -1216,9 +1174,7 @@ const_double_operand (op, mode)
 /* Return 1 if OP is a general operand that is not an immediate operand.  */
 
 int
-nonimmediate_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+nonimmediate_operand (rtx op, enum machine_mode mode)
 {
   return (general_operand (op, mode) && ! CONSTANT_P (op));
 }
@@ -1226,9 +1182,7 @@ nonimmediate_operand (op, mode)
 /* Return 1 if OP is a register reference or immediate value of mode MODE.  */
 
 int
-nonmemory_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+nonmemory_operand (rtx op, enum machine_mode mode)
 {
   if (CONSTANT_P (op))
     {
@@ -1282,9 +1236,7 @@ nonmemory_operand (op, mode)
    expressions in the machine description.  */
 
 int
-push_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+push_operand (rtx op, enum machine_mode mode)
 {
   unsigned int rounded_size = GET_MODE_SIZE (mode);
 
@@ -1314,7 +1266,7 @@ push_operand (op, mode)
 #ifdef STACK_GROWS_DOWNWARD
          || INTVAL (XEXP (XEXP (op, 1), 1)) != - (int) rounded_size
 #else
-         || INTVAL (XEXP (XEXP (op, 1), 1)) != rounded_size
+         || INTVAL (XEXP (XEXP (op, 1), 1)) != (int) rounded_size
 #endif
          )
        return 0;
@@ -1330,9 +1282,7 @@ push_operand (op, mode)
    expressions in the machine description.  */
 
 int
-pop_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+pop_operand (rtx op, enum machine_mode mode)
 {
   if (GET_CODE (op) != MEM)
     return 0;
@@ -1351,9 +1301,7 @@ pop_operand (op, mode)
 /* Return 1 if ADDR is a valid memory address for mode MODE.  */
 
 int
-memory_address_p (mode, addr)
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-     rtx addr;
+memory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr)
 {
   if (GET_CODE (addr) == ADDRESSOF)
     return 1;
@@ -1372,9 +1320,7 @@ memory_address_p (mode, addr)
    expressions in the machine description.  */
 
 int
-memory_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+memory_operand (rtx op, enum machine_mode mode)
 {
   rtx inner;
 
@@ -1397,9 +1343,7 @@ memory_operand (op, mode)
    that is, a memory reference whose address is a general_operand.  */
 
 int
-indirect_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+indirect_operand (rtx op, enum machine_mode mode)
 {
   /* Before reload, a SUBREG isn't in memory (see memory_operand, above).  */
   if (! reload_completed
@@ -1432,9 +1376,7 @@ indirect_operand (op, mode)
    MATCH_OPERATOR to recognize all the branch insns.  */
 
 int
-comparison_operator (op, mode)
-    rtx op;
-    enum machine_mode mode;
+comparison_operator (rtx op, enum machine_mode mode)
 {
   return ((mode == VOIDmode || GET_MODE (op) == mode)
          && GET_RTX_CLASS (GET_CODE (op)) == '<');
@@ -1445,8 +1387,7 @@ comparison_operator (op, mode)
    Otherwise return -1.  */
 
 int
-asm_noperands (body)
-     rtx body;
+asm_noperands (rtx body)
 {
   switch (GET_CODE (body))
     {
@@ -1530,12 +1471,8 @@ asm_noperands (body)
    we don't store that info.  */
 
 const char *
-decode_asm_operands (body, operands, operand_locs, constraints, modes)
-     rtx body;
-     rtx *operands;
-     rtx **operand_locs;
-     const char **constraints;
-     enum machine_mode *modes;
+decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
+                    const char **constraints, enum machine_mode *modes)
 {
   int i;
   int noperands;
@@ -1667,9 +1604,7 @@ decode_asm_operands (body, operands, operand_locs, constraints, modes)
    Return > 0 if ok, = 0 if bad, < 0 if inconclusive.  */
 
 int
-asm_operand_ok (op, constraint)
-     rtx op;
-     const char *constraint;
+asm_operand_ok (rtx op, const char *constraint)
 {
   int result = 0;
 
@@ -1679,18 +1614,21 @@ asm_operand_ok (op, constraint)
 
   while (*constraint)
     {
-      char c = *constraint++;
+      char c = *constraint;
+      int len;
       switch (c)
        {
+       case ',':
+         constraint++;
+         continue;
        case '=':
        case '+':
        case '*':
        case '%':
-       case '?':
        case '!':
        case '#':
        case '&':
-       case ',':
+       case '?':
          break;
 
        case '0': case '1': case '2': case '3': case '4':
@@ -1699,25 +1637,27 @@ asm_operand_ok (op, constraint)
             proper matching constraint, but we can't actually fail
             the check if they didn't.  Indicate that results are
             inconclusive.  */
-         while (ISDIGIT (*constraint))
+         do
            constraint++;
-         result = -1;
-         break;
+         while (ISDIGIT (*constraint));
+         if (! result)
+           result = -1;
+         continue;
 
        case 'p':
          if (address_operand (op, VOIDmode))
-           return 1;
+           result = 1;
          break;
 
        case 'm':
        case 'V': /* non-offsettable */
          if (memory_operand (op, VOIDmode))
-           return 1;
+           result = 1;
          break;
 
        case 'o': /* offsettable */
          if (offsettable_nonstrict_memref_p (op))
-           return 1;
+           result = 1;
          break;
 
        case '<':
@@ -1732,7 +1672,7 @@ asm_operand_ok (op, constraint)
              && (1
                  || GET_CODE (XEXP (op, 0)) == PRE_DEC
                  || GET_CODE (XEXP (op, 0)) == POST_DEC))
-           return 1;
+           result = 1;
          break;
 
        case '>':
@@ -1740,7 +1680,7 @@ asm_operand_ok (op, constraint)
              && (1
                  || GET_CODE (XEXP (op, 0)) == PRE_INC
                  || GET_CODE (XEXP (op, 0)) == POST_INC))
-           return 1;
+           result = 1;
          break;
 
        case 'E':
@@ -1748,18 +1688,18 @@ asm_operand_ok (op, constraint)
          if (GET_CODE (op) == CONST_DOUBLE
              || (GET_CODE (op) == CONST_VECTOR
                  && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT))
-           return 1;
+           result = 1;
          break;
 
        case 'G':
          if (GET_CODE (op) == CONST_DOUBLE
-             && CONST_DOUBLE_OK_FOR_LETTER_P (op, 'G'))
-           return 1;
+             && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'G', constraint))
+           result = 1;
          break;
        case 'H':
          if (GET_CODE (op) == CONST_DOUBLE
-             && CONST_DOUBLE_OK_FOR_LETTER_P (op, 'H'))
-           return 1;
+             && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'H', constraint))
+           result = 1;
          break;
 
        case 's':
@@ -1767,7 +1707,7 @@ asm_operand_ok (op, constraint)
              || (GET_CODE (op) == CONST_DOUBLE
                  && GET_MODE (op) == VOIDmode))
            break;
-         /* FALLTHRU */
+         /* Fall through.  */
 
        case 'i':
          if (CONSTANT_P (op)
@@ -1775,94 +1715,97 @@ asm_operand_ok (op, constraint)
              && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
 #endif
              )
-           return 1;
+           result = 1;
          break;
 
        case 'n':
          if (GET_CODE (op) == CONST_INT
              || (GET_CODE (op) == CONST_DOUBLE
                  && GET_MODE (op) == VOIDmode))
-           return 1;
+           result = 1;
          break;
 
        case 'I':
          if (GET_CODE (op) == CONST_INT
-             && CONST_OK_FOR_LETTER_P (INTVAL (op), 'I'))
-           return 1;
+             && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'I', constraint))
+           result = 1;
          break;
        case 'J':
          if (GET_CODE (op) == CONST_INT
-             && CONST_OK_FOR_LETTER_P (INTVAL (op), 'J'))
-           return 1;
+             && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'J', constraint))
+           result = 1;
          break;
        case 'K':
          if (GET_CODE (op) == CONST_INT
-             && CONST_OK_FOR_LETTER_P (INTVAL (op), 'K'))
-           return 1;
+             && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'K', constraint))
+           result = 1;
          break;
        case 'L':
          if (GET_CODE (op) == CONST_INT
-             && CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'))
-           return 1;
+             && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'L', constraint))
+           result = 1;
          break;
        case 'M':
          if (GET_CODE (op) == CONST_INT
-             && CONST_OK_FOR_LETTER_P (INTVAL (op), 'M'))
-           return 1;
+             && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'M', constraint))
+           result = 1;
          break;
        case 'N':
          if (GET_CODE (op) == CONST_INT
-             && CONST_OK_FOR_LETTER_P (INTVAL (op), 'N'))
-           return 1;
+             && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'N', constraint))
+           result = 1;
          break;
        case 'O':
          if (GET_CODE (op) == CONST_INT
-             && CONST_OK_FOR_LETTER_P (INTVAL (op), 'O'))
-           return 1;
+             && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'O', constraint))
+           result = 1;
          break;
        case 'P':
          if (GET_CODE (op) == CONST_INT
-             && CONST_OK_FOR_LETTER_P (INTVAL (op), 'P'))
-           return 1;
+             && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'P', constraint))
+           result = 1;
          break;
 
        case 'X':
-         return 1;
+         result = 1;
+         break;
 
        case 'g':
          if (general_operand (op, VOIDmode))
-           return 1;
+           result = 1;
          break;
 
        default:
          /* For all other letters, we first check for a register class,
             otherwise it is an EXTRA_CONSTRAINT.  */
-         if (REG_CLASS_FROM_LETTER (c) != NO_REGS)
+         if (REG_CLASS_FROM_CONSTRAINT (c, constraint) != NO_REGS)
            {
            case 'r':
              if (GET_MODE (op) == BLKmode)
                break;
              if (register_operand (op, VOIDmode))
-               return 1;
-           }
-#ifdef EXTRA_CONSTRAINT
-         if (EXTRA_CONSTRAINT (op, c))
-           return 1;
-         if (EXTRA_MEMORY_CONSTRAINT (c))
-           {
-             /* Every memory operand can be reloaded to fit.  */
-             if (memory_operand (op, VOIDmode))
-               return 1;
-           }
-         if (EXTRA_ADDRESS_CONSTRAINT (c))
-           {
-             /* Every address operand can be reloaded to fit.  */
-             if (address_operand (op, VOIDmode))
-               return 1;
+               result = 1;
            }
+#ifdef EXTRA_CONSTRAINT_STR
+         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;
        }
+      len = CONSTRAINT_LEN (c, constraint);
+      do
+       constraint++;
+      while (--len && *constraint);
+      if (len)
+       return 0;
     }
 
   return result;
@@ -1873,8 +1816,7 @@ asm_operand_ok (op, constraint)
    Otherwise, return a null pointer.  */
 
 rtx *
-find_constant_term_loc (p)
-     rtx *p;
+find_constant_term_loc (rtx *p)
 {
   rtx *tem;
   enum rtx_code code = GET_CODE (*p);
@@ -1927,8 +1869,7 @@ find_constant_term_loc (p)
    don't use it before reload.  */
 
 int
-offsettable_memref_p (op)
-     rtx op;
+offsettable_memref_p (rtx op)
 {
   return ((GET_CODE (op) == MEM)
          && offsettable_address_p (1, GET_MODE (op), XEXP (op, 0)));
@@ -1938,8 +1879,7 @@ offsettable_memref_p (op)
    consider pseudo-regs valid as index or base regs.  */
 
 int
-offsettable_nonstrict_memref_p (op)
-     rtx op;
+offsettable_nonstrict_memref_p (rtx op)
 {
   return ((GET_CODE (op) == MEM)
          && offsettable_address_p (0, GET_MODE (op), XEXP (op, 0)));
@@ -1956,16 +1896,13 @@ offsettable_nonstrict_memref_p (op)
    for the sake of use in reload.c.  */
 
 int
-offsettable_address_p (strictp, mode, y)
-     int strictp;
-     enum machine_mode mode;
-     rtx y;
+offsettable_address_p (int strictp, enum machine_mode mode, rtx y)
 {
   enum rtx_code ycode = GET_CODE (y);
   rtx z;
   rtx y1 = y;
   rtx *y2;
-  int (*addressp) PARAMS ((enum machine_mode, rtx)) =
+  int (*addressp) (enum machine_mode, rtx) =
     (strictp ? strict_memory_address_p : memory_address_p);
   unsigned int mode_sz = GET_MODE_SIZE (mode);
 
@@ -2031,8 +1968,7 @@ offsettable_address_p (strictp, mode, y)
    because the amount of the increment depends on the mode.  */
 
 int
-mode_dependent_address_p (addr)
-  rtx addr ATTRIBUTE_UNUSED; /* Maybe used in GO_IF_MODE_DEPENDENT_ADDRESS.  */
+mode_dependent_address_p (rtx addr ATTRIBUTE_UNUSED /* Maybe used in GO_IF_MODE_DEPENDENT_ADDRESS.  */)
 {
   GO_IF_MODE_DEPENDENT_ADDRESS (addr, win);
   return 0;
@@ -2040,59 +1976,32 @@ mode_dependent_address_p (addr)
  win: ATTRIBUTE_UNUSED_LABEL
   return 1;
 }
-
-/* Return 1 if OP is a general operand
-   other than a memory ref with a mode dependent address.  */
-
-int
-mode_independent_operand (op, mode)
-     enum machine_mode mode;
-     rtx op;
-{
-  rtx addr;
-
-  if (! general_operand (op, mode))
-    return 0;
-
-  if (GET_CODE (op) != MEM)
-    return 1;
-
-  addr = XEXP (op, 0);
-  GO_IF_MODE_DEPENDENT_ADDRESS (addr, lose);
-  return 1;
-  /* Label `lose' might (not) be used via GO_IF_MODE_DEPENDENT_ADDRESS.  */
- lose: ATTRIBUTE_UNUSED_LABEL
-  return 0;
-}
 \f
 /* Like extract_insn, but save insn extracted and don't extract again, when
    called again for the same insn expecting that recog_data still contain the
    valid information.  This is used primary by gen_attr infrastructure that
    often does extract insn again and again.  */
 void
-extract_insn_cached (insn)
-     rtx insn;
+extract_insn_cached (rtx insn)
 {
   if (recog_data.insn == insn && INSN_CODE (insn) >= 0)
     return;
   extract_insn (insn);
   recog_data.insn = insn;
 }
-/* Do cached extract_insn, constrain_operand and complain about failures.
+/* Do cached extract_insn, constrain_operands and complain about failures.
    Used by insn_attrtab.  */
 void
-extract_constrain_insn_cached (insn)
-     rtx insn;
+extract_constrain_insn_cached (rtx insn)
 {
   extract_insn_cached (insn);
   if (which_alternative == -1
       && !constrain_operands (reload_completed))
     fatal_insn_not_found (insn);
 }
-/* Do cached constrain_operand and complain about failures.  */
+/* Do cached constrain_operands and complain about failures.  */
 int
-constrain_operands_cached (strict)
-       int strict;
+constrain_operands_cached (int strict)
 {
   if (which_alternative == -1)
     return constrain_operands (strict);
@@ -2103,8 +2012,7 @@ constrain_operands_cached (strict)
 /* Analyze INSN and fill in recog_data.  */
 
 void
-extract_insn (insn)
-     rtx insn;
+extract_insn (rtx insn)
 {
   int i;
   int icode;
@@ -2203,11 +2111,14 @@ extract_insn (insn)
    information from the constraint strings into a more usable form.
    The collected data is stored in recog_op_alt.  */
 void
-preprocess_constraints ()
+preprocess_constraints (void)
 {
   int i;
 
-  memset (recog_op_alt, 0, sizeof recog_op_alt);
+  for (i = 0; i < recog_data.n_operands; i++)
+    memset (recog_op_alt[i], 0, (recog_data.n_alternatives
+                                * sizeof (struct operand_alternative)));
+
   for (i = 0; i < recog_data.n_operands; i++)
     {
       int j;
@@ -2231,13 +2142,16 @@ preprocess_constraints ()
 
          for (;;)
            {
-             char c = *p++;
+             char c = *p;
              if (c == '#')
                do
-                 c = *p++;
+                 c = *++p;
                while (c != ',' && c != '\0');
              if (c == ',' || c == '\0')
-               break;
+               {
+                 p++;
+                 break;
+               }
 
              switch (c)
                {
@@ -2263,11 +2177,11 @@ preprocess_constraints ()
                case '5': case '6': case '7': case '8': case '9':
                  {
                    char *end;
-                   op_alt[j].matches = strtoul (p - 1, &end, 10);
+                   op_alt[j].matches = strtoul (p, &end, 10);
                    recog_op_alt[op_alt[j].matches][j].matched = i;
                    p = end;
                  }
-                 break;
+                 continue;
 
                case 'm':
                  op_alt[j].memory_ok = 1;
@@ -2299,22 +2213,28 @@ preprocess_constraints ()
                  break;
 
                default:
-                 if (EXTRA_MEMORY_CONSTRAINT (c))
+                 if (EXTRA_MEMORY_CONSTRAINT (c, p))
                    {
                      op_alt[j].memory_ok = 1;
                      break;
                    }
-                 if (EXTRA_ADDRESS_CONSTRAINT (c))
+                 if (EXTRA_ADDRESS_CONSTRAINT (c, p))
                    {
                      op_alt[j].is_address = 1;
-                     op_alt[j].class = reg_class_subunion[(int) op_alt[j].class]
-                       [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+                     op_alt[j].class
+                       = (reg_class_subunion
+                          [(int) op_alt[j].class]
+                          [(int) MODE_BASE_REG_CLASS (VOIDmode)]);
                      break;
                    }
 
-                 op_alt[j].class = reg_class_subunion[(int) op_alt[j].class][(int) REG_CLASS_FROM_LETTER ((unsigned char) c)];
+                 op_alt[j].class
+                   = (reg_class_subunion
+                      [(int) op_alt[j].class]
+                      [(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
                  break;
                }
+             p += CONSTRAINT_LEN (c, p);
            }
        }
     }
@@ -2329,7 +2249,7 @@ preprocess_constraints ()
    alternative of constraints was matched: 0 for the first alternative,
    1 for the next, etc.
 
-   In addition, when two operands are match
+   In addition, when two operands are required to match
    and it happens that the output operand is (reg) while the
    input operand is --(reg) or ++(reg) (a pre-inc or pre-dec),
    make the output operand look like the input.
@@ -2353,8 +2273,7 @@ struct funny_match
 };
 
 int
-constrain_operands (strict)
-     int strict;
+constrain_operands (int strict)
 {
   const char *constraints[MAX_RECOG_OPERANDS];
   int matching_operands[MAX_RECOG_OPERANDS];
@@ -2388,6 +2307,7 @@ constrain_operands (strict)
          int offset = 0;
          int win = 0;
          int val;
+         int len;
 
          earlyclobber[opno] = 0;
 
@@ -2412,9 +2332,16 @@ constrain_operands (strict)
          if (*p == 0 || *p == ',')
            win = 1;
 
-         while (*p && (c = *p++) != ',')
-           switch (c)
+         do
+           switch (c = *p, len = CONSTRAINT_LEN (c, p), c)
              {
+             case '\0':
+               len = 0;
+               break;
+             case ',':
+               c = '\0';
+               break;
+
              case '?':  case '!': case '*':  case '%':
              case '=':  case '+':
                break;
@@ -2422,8 +2349,10 @@ constrain_operands (strict)
              case '#':
                /* Ignore rest of this alternative as far as
                   constraint checking is concerned.  */
-               while (*p && *p != ',')
+               do
                  p++;
+               while (*p && *p != ',');
+               len = 0;
                break;
 
              case '&':
@@ -2445,7 +2374,7 @@ constrain_operands (strict)
                  char *end;
                  int match;
 
-                 match = strtoul (p - 1, &end, 10);
+                 match = strtoul (p, &end, 10);
                  p = end;
 
                  if (strict < 0)
@@ -2480,6 +2409,7 @@ constrain_operands (strict)
                      funny_match[funny_match_index++].other = match;
                    }
                }
+               len = 0;
                break;
 
              case 'p':
@@ -2515,12 +2445,25 @@ constrain_operands (strict)
                break;
 
              case 'm':
-               if (GET_CODE (op) == MEM
-                   /* Before reload, accept what reload can turn into mem.  */
-                   || (strict < 0 && CONSTANT_P (op))
-                   /* During reload, accept a pseudo  */
-                   || (reload_in_progress && GET_CODE (op) == REG
-                       && REGNO (op) >= FIRST_PSEUDO_REGISTER))
+               /* Memory operands must be valid, to the extent
+                  required by STRICT.  */
+               if (GET_CODE (op) == MEM)
+                 {
+                   if (strict > 0
+                       && !strict_memory_address_p (GET_MODE (op),
+                                                    XEXP (op, 0)))
+                     break;
+                   if (strict == 0
+                       && !memory_address_p (GET_MODE (op), XEXP (op, 0)))
+                     break;
+                   win = 1;
+                 }
+               /* Before reload, accept what reload can turn into mem.  */
+               else if (strict < 0 && CONSTANT_P (op))
+                 win = 1;
+               /* During reload, accept a pseudo  */
+               else if (reload_in_progress && GET_CODE (op) == REG
+                        && REGNO (op) >= FIRST_PSEUDO_REGISTER)
                  win = 1;
                break;
 
@@ -2549,7 +2492,7 @@ constrain_operands (strict)
              case 'G':
              case 'H':
                if (GET_CODE (op) == CONST_DOUBLE
-                   && CONST_DOUBLE_OK_FOR_LETTER_P (op, c))
+                   && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p))
                  win = 1;
                break;
 
@@ -2579,7 +2522,7 @@ constrain_operands (strict)
              case 'O':
              case 'P':
                if (GET_CODE (op) == CONST_INT
-                   && CONST_OK_FOR_LETTER_P (INTVAL (op), c))
+                   && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p))
                  win = 1;
                break;
 
@@ -2610,7 +2553,8 @@ constrain_operands (strict)
                {
                  enum reg_class class;
 
-                 class = (c == 'r' ? GENERAL_REGS : REG_CLASS_FROM_LETTER (c));
+                 class = (c == 'r'
+                          ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, p));
                  if (class != NO_REGS)
                    {
                      if (strict < 0
@@ -2622,35 +2566,29 @@ constrain_operands (strict)
                              && reg_fits_class_p (op, class, offset, mode)))
                        win = 1;
                    }
-#ifdef EXTRA_CONSTRAINT
-                 else if (EXTRA_CONSTRAINT (op, c))
+#ifdef EXTRA_CONSTRAINT_STR
+                 else if (EXTRA_CONSTRAINT_STR (op, c, p))
                    win = 1;
 
-                 if (EXTRA_MEMORY_CONSTRAINT (c))
-                   {
-                     /* Every memory operand can be reloaded to fit,
-                        so copy the condition from the 'm' case.  */
-                     if (GET_CODE (op) == MEM
-                         /* Before reload, accept what reload can turn into mem.  */
-                         || (strict < 0 && CONSTANT_P (op))
-                         /* During reload, accept a pseudo  */
-                         || (reload_in_progress && GET_CODE (op) == REG
-                             && REGNO (op) >= FIRST_PSEUDO_REGISTER))
-                       win = 1;
-                   }
-                 if (EXTRA_ADDRESS_CONSTRAINT (c))
-                   {
-                     /* Every address operand can be reloaded to fit,
-                        so copy the condition from the 'p' case.  */
-                     if (strict <= 0
-                         || (strict_memory_address_p (recog_data.operand_mode[opno],
-                                                      op)))
-                       win = 1;
-                   }
+                 else if (EXTRA_MEMORY_CONSTRAINT (c, p)
+                          /* Every memory operand can be reloaded to fit.  */
+                          && ((strict < 0 && GET_CODE (op) == MEM)
+                              /* Before reload, accept what reload can turn
+                                 into mem.  */
+                              || (strict < 0 && CONSTANT_P (op))
+                              /* During reload, accept a pseudo  */
+                              || (reload_in_progress && GET_CODE (op) == REG
+                                  && REGNO (op) >= FIRST_PSEUDO_REGISTER)))
+                   win = 1;
+                 else if (EXTRA_ADDRESS_CONSTRAINT (c, p)
+                          /* Every address operand can be reloaded to fit.  */
+                          && strict < 0)
+                   win = 1;
 #endif
                  break;
                }
              }
+         while (p += len, c);
 
          constraints[opno] = p;
          /* If this operand did not win somehow,
@@ -2718,11 +2656,8 @@ constrain_operands (strict)
    If REG occupies multiple hard regs, all of them must be in CLASS.  */
 
 int
-reg_fits_class_p (operand, class, offset, mode)
-     rtx operand;
-     enum reg_class class;
-     int offset;
-     enum machine_mode mode;
+reg_fits_class_p (rtx operand, enum reg_class class, int offset,
+                 enum machine_mode mode)
 {
   int regno = REGNO (operand);
   if (regno < FIRST_PSEUDO_REGISTER
@@ -2731,7 +2666,7 @@ reg_fits_class_p (operand, class, offset, mode)
     {
       int sr;
       regno += offset;
-      for (sr = HARD_REGNO_NREGS (regno, mode) - 1;
+      for (sr = hard_regno_nregs[regno][mode] - 1;
           sr > 0; sr--)
        if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
                                 regno + sr))
@@ -2742,115 +2677,126 @@ reg_fits_class_p (operand, class, offset, mode)
   return 0;
 }
 \f
-/* Split single instruction.  Helper function for split_all_insns.
-   Return last insn in the sequence if successful, or NULL if unsuccessful.  */
+/* Split single instruction.  Helper function for split_all_insns and
+   split_all_insns_noflow.  Return last insn in the sequence if successful,
+   or NULL if unsuccessful.  */
+
 static rtx
-split_insn (insn)
-     rtx insn;
+split_insn (rtx insn)
 {
-  rtx set;
-  if (!INSN_P (insn))
-    ;
-  /* 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.  */
+  /* Split insns here to get max fine-grain parallelism.  */
+  rtx first = PREV_INSN (insn);
+  rtx last = try_split (PATTERN (insn), insn, 1);
 
-  else if ((set = single_set (insn)) != NULL && set_noop_p (set))
-    {
-      /* Nops get in the way while scheduling, so delete them
-         now if register allocation has already been done.  It
-         is too risky to try to do this before register
-         allocation, and there are unlikely to be very many
-         nops then anyways.  */
-      if (reload_completed)
-       delete_insn_and_edges (insn);
-    }
-  else
-    {
-      /* Split insns here to get max fine-grain parallelism.  */
-      rtx first = PREV_INSN (insn);
-      rtx last = try_split (PATTERN (insn), insn, 1);
+  if (last == insn)
+    return NULL_RTX;
+
+  /* try_split returns the NOTE that INSN became.  */
+  PUT_CODE (insn, NOTE);
+  NOTE_SOURCE_FILE (insn) = 0;
+  NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
 
-      if (last != insn)
+  /* ??? Coddle to md files that generate subregs in post-reload
+     splitters instead of computing the proper hard register.  */
+  if (reload_completed && first != last)
+    {
+      first = NEXT_INSN (first);
+      for (;;)
        {
-         /* try_split returns the NOTE that INSN became.  */
-         PUT_CODE (insn, NOTE);
-         NOTE_SOURCE_FILE (insn) = 0;
-         NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-
-         /* ??? Coddle to md files that generate subregs in post-
-            reload splitters instead of computing the proper
-            hard register.  */
-         if (reload_completed && first != last)
-           {
-             first = NEXT_INSN (first);
-             while (1)
-               {
-                 if (INSN_P (first))
-                   cleanup_subreg_operands (first);
-                 if (first == last)
-                   break;
-                 first = NEXT_INSN (first);
-               }
-           }
-         return last;
+         if (INSN_P (first))
+           cleanup_subreg_operands (first);
+         if (first == last)
+           break;
+         first = NEXT_INSN (first);
        }
     }
-  return NULL_RTX;
+  return last;
 }
+
 /* Split all insns in the function.  If UPD_LIFE, update life info after.  */
 
 void
-split_all_insns (upd_life)
-     int upd_life;
+split_all_insns (int upd_life)
 {
   sbitmap blocks;
-  int changed;
+  bool changed;
   basic_block bb;
 
   blocks = sbitmap_alloc (last_basic_block);
   sbitmap_zero (blocks);
-  changed = 0;
+  changed = false;
 
   FOR_EACH_BB_REVERSE (bb)
     {
       rtx insn, next;
       bool finish = false;
 
-      for (insn = bb->head; !finish ; insn = next)
+      for (insn = BB_HEAD (bb); !finish ; insn = next)
        {
-         rtx last;
-
          /* Can't use `next_real_insn' because that might go across
             CODE_LABELS and short-out basic blocks.  */
          next = NEXT_INSN (insn);
-         finish = (insn == bb->end);
-         last = split_insn (insn);
-         if (last)
+         finish = (insn == BB_END (bb));
+         if (INSN_P (insn))
            {
-             /* The split sequence may include barrier, but the
-                BB boundary we are interested in will be set to previous
-                one.  */
-
-             while (GET_CODE (last) == BARRIER)
-               last = PREV_INSN (last);
-             SET_BIT (blocks, bb->index);
-             changed = 1;
-             insn = last;
+             rtx set = single_set (insn);
+
+             /* 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.  */
+             if (set && set_noop_p (set))
+               {
+                 /* Nops get in the way while scheduling, so delete them
+                    now if register allocation has already been done.  It
+                    is too risky to try to do this before register
+                    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
+               {
+                 rtx last = split_insn (insn);
+                 if (last)
+                   {
+                     /* The split sequence may include barrier, but the
+                        BB boundary we are interested in will be set to
+                        previous one.  */
+
+                     while (GET_CODE (last) == BARRIER)
+                       last = PREV_INSN (last);
+                     SET_BIT (blocks, bb->index);
+                     changed = true;
+                   }
+               }
            }
        }
     }
 
   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)
-    {
-      count_or_remove_death_notes (blocks, 1);
-      update_life_info (blocks, UPDATE_LIFE_LOCAL, PROP_DEATH_NOTES);
-    }
+    update_life_info (blocks, UPDATE_LIFE_GLOBAL_RM_NOTES,
+                     PROP_DEATH_NOTES);
+
 #ifdef ENABLE_CHECKING
   verify_flow_info ();
 #endif
@@ -2859,19 +2805,38 @@ split_all_insns (upd_life)
 }
 
 /* Same as split_all_insns, but do not expect CFG to be available.
-   Used by machine depedent reorg passes.  */
+   Used by machine dependent reorg passes.  */
 
 void
-split_all_insns_noflow ()
+split_all_insns_noflow (void)
 {
   rtx next, insn;
 
   for (insn = get_insns (); insn; insn = next)
     {
       next = NEXT_INSN (insn);
-      split_insn (insn);
+      if (INSN_P (insn))
+       {
+         /* 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.  */
+         rtx set = single_set (insn);
+         if (set && set_noop_p (set))
+           {
+             /* Nops get in the way while scheduling, so delete them
+                now if register allocation has already been done.  It
+                is too risky to try to do this before register
+                allocation, and there are unlikely to be very many
+                nops then anyways.
+
+                ??? Should we use delete_insn when the CFG isn't valid?  */
+             if (reload_completed)
+               delete_insn_and_edges (insn);
+           }
+         else
+           split_insn (insn);
+       }
     }
-  return;
 }
 \f
 #ifdef HAVE_peephole2
@@ -2894,8 +2859,7 @@ static int peep2_current;
    in a multi-insn pattern.  */
 
 rtx
-peep2_next_insn (n)
-     int n;
+peep2_next_insn (int n)
 {
   if (n >= MAX_INSNS_PER_PEEP2 + 1)
     abort ();
@@ -2913,9 +2877,7 @@ peep2_next_insn (n)
    after `current'.  */
 
 int
-peep2_regno_dead_p (ofs, regno)
-     int ofs;
-     int regno;
+peep2_regno_dead_p (int ofs, int regno)
 {
   if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
     abort ();
@@ -2933,9 +2895,7 @@ peep2_regno_dead_p (ofs, regno)
 /* Similarly for a REG.  */
 
 int
-peep2_reg_dead_p (ofs, reg)
-     int ofs;
-     rtx reg;
+peep2_reg_dead_p (int ofs, rtx reg)
 {
   int regno, n;
 
@@ -2950,7 +2910,7 @@ peep2_reg_dead_p (ofs, reg)
     abort ();
 
   regno = REGNO (reg);
-  n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
+  n = hard_regno_nregs[regno][GET_MODE (reg)];
   while (--n >= 0)
     if (REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno + n))
       return 0;
@@ -2969,11 +2929,8 @@ peep2_reg_dead_p (ofs, reg)
    returned.  */
 
 rtx
-peep2_find_free_register (from, to, class_str, mode, reg_set)
-     int from, to;
-     const char *class_str;
-     enum machine_mode mode;
-     HARD_REG_SET *reg_set;
+peep2_find_free_register (int from, int to, const char *class_str,
+                         enum machine_mode mode, HARD_REG_SET *reg_set)
 {
   static int search_ofs;
   enum reg_class class;
@@ -3007,7 +2964,7 @@ peep2_find_free_register (from, to, class_str, mode, reg_set)
     }
 
   class = (class_str[0] == 'r' ? GENERAL_REGS
-          : REG_CLASS_FROM_LETTER (class_str[0]));
+          : REG_CLASS_FROM_CONSTRAINT (class_str[0], class_str));
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
@@ -3041,7 +2998,7 @@ peep2_find_free_register (from, to, class_str, mode, reg_set)
        continue;
 
       success = 1;
-      for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
+      for (j = hard_regno_nregs[regno][mode] - 1; j >= 0; j--)
        {
          if (TEST_HARD_REG_BIT (*reg_set, regno + j)
              || TEST_HARD_REG_BIT (live, regno + j))
@@ -3052,7 +3009,7 @@ peep2_find_free_register (from, to, class_str, mode, reg_set)
        }
       if (success)
        {
-         for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
+         for (j = hard_regno_nregs[regno][mode] - 1; j >= 0; j--)
            SET_HARD_REG_BIT (*reg_set, regno + j);
 
          /* Start the next search with the next register.  */
@@ -3071,8 +3028,7 @@ peep2_find_free_register (from, to, class_str, mode, reg_set)
 /* Perform the peephole2 optimization pass.  */
 
 void
-peephole2_optimize (dump_file)
-     FILE *dump_file ATTRIBUTE_UNUSED;
+peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
 {
   regset_head rs_heads[MAX_INSNS_PER_PEEP2 + 2];
   rtx insn, prev;
@@ -3121,7 +3077,7 @@ peephole2_optimize (dump_file)
       pbi = init_propagate_block_info (bb, live, NULL, NULL, PROP_DEATH_NOTES);
 #endif
 
-      for (insn = bb->end; ; insn = prev)
+      for (insn = BB_END (bb); ; insn = prev)
        {
          prev = PREV_INSN (insn);
          if (INSN_P (insn))
@@ -3210,8 +3166,8 @@ peephole2_optimize (dump_file)
                                        REG_EH_REGION, NULL_RTX);
 
                  /* Replace the old sequence with the new.  */
-                 try = emit_insn_after_scope (try, peep2_insn_data[i].insn,
-                                              INSN_SCOPE (peep2_insn_data[i].insn));
+                 try = emit_insn_after_setloc (try, 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);
 
@@ -3237,7 +3193,7 @@ peephole2_optimize (dump_file)
                                                     XEXP (note, 0),
                                                     REG_NOTES (x));
 
-                           if (x != bb->end && eh_edge)
+                           if (x != BB_END (bb) && eh_edge)
                              {
                                edge nfte, nehe;
                                int flags;
@@ -3321,7 +3277,7 @@ peephole2_optimize (dump_file)
                }
            }
 
-         if (insn == bb->head)
+         if (insn == BB_HEAD (bb))
            break;
        }
 
@@ -3362,8 +3318,7 @@ peephole2_optimize (dump_file)
    SETs inside.  */
 
 int
-store_data_bypass_p (out_insn, in_insn)
-     rtx out_insn, in_insn;
+store_data_bypass_p (rtx out_insn, rtx in_insn)
 {
   rtx out_set, in_set;
 
@@ -3413,8 +3368,7 @@ store_data_bypass_p (out_insn, in_insn)
    of insn categorization may be any JUMP or CALL insn.  */
 
 int
-if_test_bypass_p (out_insn, in_insn)
-     rtx out_insn, in_insn;
+if_test_bypass_p (rtx out_insn, rtx in_insn)
 {
   rtx out_set, in_set;